[0.6.116] use nsec unit instead of msec
[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, gint64 position, gboolean internal_called);
209 static int              __gst_get_position(mm_player_t* player, int format, gint64 *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) && (dur_nsec > 0)) {
352                         player->duration = dur_nsec;
353                         LOGW("duration : %"G_GINT64_FORMAT" msec", GST_TIME_AS_MSECONDS(dur_nsec));
354                         has_duration = TRUE;
355                 }
356
357                 if (player->duration < 0) {
358                         LOGW("duration is Non-Initialized !!!");
359                         player->duration = 0;
360                 }
361
362                 /* update streaming service type */
363                 player->streaming_type =  __mmplayer_get_stream_service_type(player);
364
365                 /* check duration is OK */
366                 if (dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING(player)) {
367                         /* FIXIT : find another way to get duration here. */
368                         LOGW("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
369                 }
370         }
371
372         if ((flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all) {
373                 /* update audio params
374                 NOTE : We need original audio params and it can be only obtained from src pad of audio
375                 decoder. Below code only valid when we are not using 'resampler' just before
376                 'audioconverter'. */
377
378                 LOGD("try to update audio attrs");
379                 has_audio_attrs = FALSE;
380
381                 if (player->pipeline->audiobin &&
382                          player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
383                         GstCaps *caps_a = NULL;
384                         GstPad* pad = NULL;
385                         gint samplerate = 0, channels = 0;
386
387                         pad = gst_element_get_static_pad(
388                                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink");
389
390                         if (pad) {
391                                 caps_a = gst_pad_get_current_caps(pad);
392
393                                 if (caps_a) {
394                                         p = gst_caps_get_structure(caps_a, 0);
395
396                                         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
397
398                                         gst_structure_get_int(p, "rate", &samplerate);
399                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
400
401                                         gst_structure_get_int(p, "channels", &channels);
402                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
403
404                                         SECURE_LOGD("samplerate : %d    channels : %d", samplerate, channels);
405
406                                         gst_caps_unref(caps_a);
407                                         caps_a = NULL;
408
409                                         has_audio_attrs = TRUE;
410                                 } else
411                                         LOGW("not ready to get audio caps");
412
413                                 gst_object_unref(pad);
414                         } else
415                                 LOGW("failed to get pad from audiosink");
416                 }
417         }
418
419         if ((flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all) {
420                 LOGD("try to update video attrs");
421                 has_video_attrs = FALSE;
422
423                 if (player->pipeline->videobin &&
424                          player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
425                         GstCaps *caps_v = NULL;
426                         GstPad* pad = NULL;
427                         gint tmpNu, tmpDe;
428                         gint width, height;
429
430                         pad = gst_element_get_static_pad(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink");
431                         if (pad) {
432                                 caps_v = gst_pad_get_current_caps(pad);
433
434                                 /* Use v_stream_caps, if fail to get video_sink sink pad*/
435                                 if (!caps_v && player->v_stream_caps) {
436                                         caps_v = player->v_stream_caps;
437                                         gst_caps_ref(caps_v);
438                                 }
439
440                                 if (caps_v) {
441                                         p = gst_caps_get_structure(caps_v, 0);
442                                         gst_structure_get_int(p, "width", &width);
443                                         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
444
445                                         gst_structure_get_int(p, "height", &height);
446                                         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
447
448                                         gst_structure_get_fraction(p, "framerate", &tmpNu, &tmpDe);
449
450                                         SECURE_LOGD("width : %d     height : %d", width, height);
451
452                                         gst_caps_unref(caps_v);
453                                         caps_v = NULL;
454
455                                         if (tmpDe > 0) {
456                                                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
457                                                 SECURE_LOGD("fps : %d", tmpNu / tmpDe);
458                                         }
459
460                                         has_video_attrs = TRUE;
461                                 } else
462                                         LOGD("no negitiated caps from videosink");
463                                 gst_object_unref(pad);
464                                 pad = NULL;
465                         } else {
466                                 LOGD("no videosink sink pad");
467                         }
468                 }
469         }
470
471
472         if ((flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all) {
473                 has_bitrate = FALSE;
474
475                 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
476                 if (player->duration) {
477                         guint64 data_size = 0;
478
479                         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
480                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
481
482                                 if (stat(path, &sb) == 0)
483                                         data_size = (guint64)sb.st_size;
484                         } else if (MMPLAYER_IS_HTTP_STREAMING(player)) {
485                                 data_size = player->http_content_size;
486                         }
487                         LOGD("try to update bitrate : data_size = %"G_GUINT64_FORMAT, data_size);
488
489                         if (data_size) {
490                                 guint64 bitrate = 0;
491                                 guint64 msec_dur = 0;
492
493                                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
494                                 if (msec_dur > 0) {
495                                         bitrate = data_size * 8 * 1000 / msec_dur;
496                                         SECURE_LOGD("file size : %u, video bitrate = %llu", data_size, bitrate);
497                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
498
499                                         has_bitrate = TRUE;
500                                 } else {
501                                         LOGD("player duration is less than 0");
502                                 }
503                         }
504
505                         if (MMPLAYER_IS_RTSP_STREAMING(player)) {
506                                 if (player->total_bitrate) {
507                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
508                                         has_bitrate = TRUE;
509                                 }
510                         }
511                 }
512         }
513
514         /* validate all */
515         if (mmf_attrs_commit(attrs)) {
516                 LOGE("failed to update attributes\n");
517                 return FALSE;
518         }
519
520         MMPLAYER_FLEAVE();
521
522         return TRUE;
523 }
524
525 static MMStreamingType __mmplayer_get_stream_service_type(mm_player_t* player)
526 {
527         MMStreamingType streaming_type = STREAMING_SERVICE_NONE;
528
529         MMPLAYER_FENTER();
530
531         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
532                         player->pipeline &&
533                         player->pipeline->mainbin &&
534                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
535                         STREAMING_SERVICE_NONE);
536
537         /* streaming service type if streaming */
538         if (!MMPLAYER_IS_STREAMING(player))
539                 return STREAMING_SERVICE_NONE;
540
541         if (MMPLAYER_IS_HTTP_STREAMING(player))
542                 streaming_type = (player->duration == 0) ?
543                         STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
544
545         switch (streaming_type) {
546         case STREAMING_SERVICE_LIVE:
547                 LOGD("it's live streaming");
548                 break;
549         case STREAMING_SERVICE_VOD:
550                 LOGD("it's vod streaming");
551                 break;
552         default:
553                 LOGE("should not get here");
554                 break;
555         }
556
557         MMPLAYER_FLEAVE();
558
559         return streaming_type;
560 }
561
562
563 /* this function sets the player state and also report
564  * it to applicaton by calling callback function
565  */
566 int
567 __mmplayer_set_state(mm_player_t* player, int state)
568 {
569         MMMessageParamType msg = {0, };
570         gboolean post_bos = FALSE;
571
572         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
573
574         if (MMPLAYER_CURRENT_STATE(player) == state) {
575                 LOGW("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
576                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
577                 return MM_ERROR_NONE;
578         }
579
580         /* update player states */
581         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
582         MMPLAYER_CURRENT_STATE(player) = state;
583
584         if (MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player))
585                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
586
587         /* print state */
588         MMPLAYER_PRINT_STATE(player);
589
590         switch (MMPLAYER_CURRENT_STATE(player)) {
591         case MM_PLAYER_STATE_NULL:
592         case MM_PLAYER_STATE_READY:
593                 break;
594
595         case MM_PLAYER_STATE_PAUSED:
596                 {
597                         if (!player->sent_bos) {
598                                 /* rtsp case, get content attrs by GstMessage */
599                                 if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
600                                         /* it's first time to update all content attrs. */
601                                         _mmplayer_update_content_attrs(player, ATTR_ALL);
602                                 }
603                         }
604
605                         /* add audio callback probe if condition is satisfied */
606                         if (!player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
607                                 __mmplayer_configure_audio_callback(player);
608
609                         /* FIXIT : handle return value */
610                 }
611                 break;
612
613         case MM_PLAYER_STATE_PLAYING:
614                 {
615                         /* try to get content metadata */
616                         if (!player->sent_bos) {
617                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
618                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
619                                  * legacy mmfw-player api */
620                                 _mmplayer_update_content_attrs(player, ATTR_MISSING_ONLY);
621                         }
622
623                         if ((player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME)) {
624                                 if (!player->sent_bos)
625                                         __mmplayer_handle_missed_plugin(player);
626                         }
627
628                         if (player->resumed_by_rewind && player->playback_rate < 0.0) {
629                                 /* initialize because auto resume is done well. */
630                                 player->resumed_by_rewind = FALSE;
631                                 player->playback_rate = 1.0;
632                         }
633
634                         if (!player->sent_bos) {
635                                 /* check audio codec field is set or not
636                                  * we can get it from typefinder or codec's caps.
637                                  */
638                                 gchar *audio_codec = NULL;
639                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
640
641                                 /* The codec format can't be sent for audio only case like amr, mid etc.
642                                  * Because, parser don't make related TAG.
643                                  * So, if it's not set yet, fill it with found data.
644                                  */
645                                 if (!audio_codec) {
646                                         if (g_strrstr(player->type, "audio/midi"))
647                                                 audio_codec = g_strdup("MIDI");
648                                         else if (g_strrstr(player->type, "audio/x-amr"))
649                                                 audio_codec = g_strdup("AMR");
650                                         else if (g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion= (int)1"))
651                                                 audio_codec = g_strdup("AAC");
652                                         else
653                                                 audio_codec = g_strdup("unknown");
654                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
655
656                                         MMPLAYER_FREEIF(audio_codec);
657                                         if (mmf_attrs_commit(player->attrs))
658                                                 LOGE("failed to update attributes\n");
659
660                                         LOGD("set audio codec type with caps\n");
661                                 }
662
663                                 post_bos = TRUE;
664                         }
665                 }
666                 break;
667
668         case MM_PLAYER_STATE_NONE:
669         default:
670                 LOGW("invalid target state, there is nothing to do.\n");
671                 break;
672         }
673
674
675         /* post message to application */
676         if (MMPLAYER_TARGET_STATE(player) == state) {
677                 /* fill the message with state of player */
678                 msg.union_type = MM_MSG_UNION_STATE;
679                 msg.state.previous = MMPLAYER_PREV_STATE(player);
680                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
681
682                 LOGD("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
683
684                 /* state changed by resource callback */
685                 if (player->interrupted_by_resource) {
686                         msg.state.code = MM_PLAYER_FOCUS_CHANGED_BY_RESOURCE_CONFLICT;
687                         MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
688                 } else { /* state changed by usecase */
689                         MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_CHANGED, &msg);
690                 }
691         } else {
692                 LOGD("intermediate state, do nothing.\n");
693                 MMPLAYER_PRINT_STATE(player);
694                 return MM_ERROR_NONE;
695         }
696
697         if (post_bos) {
698                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BEGIN_OF_STREAM, NULL);
699                 player->sent_bos = TRUE;
700         }
701
702         return MM_ERROR_NONE;
703 }
704
705 static gpointer __mmplayer_next_play_thread(gpointer data)
706 {
707         mm_player_t* player = (mm_player_t*) data;
708         MMPlayerGstElement *mainbin = NULL;
709
710         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
711
712         MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
713         while (!player->next_play_thread_exit) {
714                 LOGD("next play thread started. waiting for signal.\n");
715                 MMPLAYER_NEXT_PLAY_THREAD_WAIT(player);
716
717                 LOGD("reconfigure pipeline for gapless play.\n");
718
719                 if (player->next_play_thread_exit) {
720                         if (player->gapless.reconfigure) {
721                                 player->gapless.reconfigure = false;
722                                 MMPLAYER_PLAYBACK_UNLOCK(player);
723                         }
724                         LOGD("exiting gapless play thread\n");
725                         break;
726                 }
727
728                 mainbin = player->pipeline->mainbin;
729
730                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
731                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
732                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
733                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
734                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
735
736                 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
737         }
738         MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
739
740         return NULL;
741 }
742
743 static void
744 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
745 {
746         MMHandleType attrs = 0;
747         guint64 data_size = 0;
748         gchar* path = NULL;
749         gint64 pos_nsec = 0;
750         struct stat sb;
751
752         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
753
754         __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_nsec);       /* to update player->last_position */
755
756         attrs = MMPLAYER_GET_ATTRS(player);
757         if (!attrs) {
758                 LOGE("fail to get attributes.\n");
759                 return;
760         }
761
762         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
763                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
764
765                 if (stat(path, &sb) == 0)
766                         data_size = (guint64)sb.st_size;
767         } else if (MMPLAYER_IS_HTTP_STREAMING(player))
768                 data_size = player->http_content_size;
769
770         __mm_player_streaming_buffering(player->streamer,
771                                                                                 buffering_msg,
772                                                                                 data_size,
773                                                                                 player->last_position,
774                                                                                 player->duration);
775
776         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
777
778         return;
779 }
780
781 static int
782 __mmplayer_handle_buffering_message(mm_player_t* player)
783 {
784         int ret = MM_ERROR_NONE;
785         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
786         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
787         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
788         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
789
790         if (!player || !player->streamer || (MMPLAYER_IS_LIVE_STREAMING(player) && MMPLAYER_IS_RTSP_STREAMING(player))) {
791                 LOGW("do nothing for buffering msg\n");
792                 ret = MM_ERROR_PLAYER_INVALID_STATE;
793                 goto exit;
794         }
795
796         prev_state = MMPLAYER_PREV_STATE(player);
797         current_state = MMPLAYER_CURRENT_STATE(player);
798         target_state = MMPLAYER_TARGET_STATE(player);
799         pending_state = MMPLAYER_PENDING_STATE(player);
800
801         LOGD("player state : prev %s, current %s, pending %s, target %s, buffering %d",
802                 MMPLAYER_STATE_GET_NAME(prev_state),
803                 MMPLAYER_STATE_GET_NAME(current_state),
804                 MMPLAYER_STATE_GET_NAME(pending_state),
805                 MMPLAYER_STATE_GET_NAME(target_state),
806                 player->streamer->is_buffering);
807
808         if (!player->streamer->is_buffering) {
809                 /* NOTE : if buffering has done, player has to go to target state. */
810                 switch (target_state) {
811                 case MM_PLAYER_STATE_PAUSED:
812                         {
813                                 switch (pending_state) {
814                                 case MM_PLAYER_STATE_PLAYING:
815                                         __gst_pause(player, TRUE);
816                                         break;
817
818                                 case MM_PLAYER_STATE_PAUSED:
819                                         LOGD("player is already going to paused state, there is nothing to do.\n");
820                                         break;
821
822                                 case MM_PLAYER_STATE_NONE:
823                                 case MM_PLAYER_STATE_NULL:
824                                 case MM_PLAYER_STATE_READY:
825                                 default:
826                                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
827                                         break;
828                                 }
829                         }
830                         break;
831
832                 case MM_PLAYER_STATE_PLAYING:
833                         {
834                                 switch (pending_state) {
835                                 case MM_PLAYER_STATE_NONE:
836                                         {
837                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
838                                                         __gst_resume(player, TRUE);
839                                         }
840                                         break;
841
842                                 case MM_PLAYER_STATE_PAUSED:
843                                         /* NOTE: It should be worked as asynchronously.
844                                          * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
845                                          */
846                                         if (current_state == MM_PLAYER_STATE_PLAYING) {
847                                                 /* NOTE: If the current state is PLAYING, it means, async __gst_pause() is not completed yet.
848                                                  * The current state should be changed to paused purposely to prevent state conflict.
849                                                  */
850                                                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
851                                         }
852                                         __gst_resume(player, TRUE);
853                                         break;
854
855                                 case MM_PLAYER_STATE_PLAYING:
856                                         LOGD("player is already going to playing state, there is nothing to do.\n");
857                                         break;
858
859                                 case MM_PLAYER_STATE_NULL:
860                                 case MM_PLAYER_STATE_READY:
861                                 default:
862                                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
863                                         break;
864                                 }
865                         }
866                         break;
867
868                 case MM_PLAYER_STATE_NULL:
869                 case MM_PLAYER_STATE_READY:
870                 case MM_PLAYER_STATE_NONE:
871                 default:
872                         LOGW("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state));
873                         break;
874                 }
875         } else {
876                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
877                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
878                  */
879                 switch (pending_state) {
880                 case MM_PLAYER_STATE_NONE:
881                         {
882                                 if (current_state != MM_PLAYER_STATE_PAUSED) {
883                                         /* rtsp streaming pause makes rtsp server stop sending data. */
884                                         if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
885                                                 LOGD("set pause state during buffering\n");
886                                                 __gst_pause(player, TRUE);
887                                         }
888                                 }
889                         }
890                         break;
891
892                 case MM_PLAYER_STATE_PLAYING:
893                         /* rtsp streaming pause makes rtsp server stop sending data. */
894                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
895                                 __gst_pause(player, TRUE);
896                         break;
897
898                 case MM_PLAYER_STATE_PAUSED:
899                         break;
900
901                 case MM_PLAYER_STATE_NULL:
902                 case MM_PLAYER_STATE_READY:
903                 default:
904                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
905                         break;
906                 }
907         }
908
909 exit:
910         return ret;
911 }
912
913 static void
914 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
915 {
916         MMPlayerGstElement *textbin;
917         MMPLAYER_FENTER();
918
919         MMPLAYER_RETURN_IF_FAIL(player &&
920                                         player->pipeline &&
921                                         player->pipeline->textbin);
922
923         MMPLAYER_RETURN_IF_FAIL(player->pipeline->textbin[MMPLAYER_T_IDENTITY].gst);
924
925         textbin = player->pipeline->textbin;
926
927         if (is_drop) {
928                 LOGD("Drop subtitle text after getting EOS\n");
929
930                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
931                 g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
932
933                 player->is_subtitle_force_drop = TRUE;
934         } else {
935                 if (player->is_subtitle_force_drop == TRUE) {
936                         LOGD("Enable subtitle data path without drop\n");
937
938                         g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
939                         g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
940
941                         LOGD("non-connected with external display");
942
943                         player->is_subtitle_force_drop = FALSE;
944                 }
945         }
946 }
947
948 static VariantData *
949 __mmplayer_adaptive_var_info(const VariantData *self, gpointer user_data)
950 {
951         VariantData *var_info = NULL;
952         g_return_val_if_fail(self != NULL, NULL);
953
954         var_info = g_new0(VariantData, 1);
955         if (!var_info) return NULL;
956         var_info->bandwidth = self->bandwidth;
957         var_info->width = self->width;
958         var_info->height = self->height;
959         return var_info;
960 }
961
962 void _mmplayer_bus_msg_thread_destroy(MMHandleType hplayer)
963 {
964         mm_player_t* player = (mm_player_t*)hplayer;
965         GstMessage *msg = NULL;
966         GQueue *queue = NULL;
967
968         MMPLAYER_FENTER();
969         MMPLAYER_RETURN_IF_FAIL(player);
970
971         player->bus_msg_timeout = PLAYER_BUS_MSG_DEFAULT_TIMEOUT;
972
973         /* destroy the gst bus msg thread */
974         if (player->bus_msg_thread) {
975                 MMPLAYER_BUS_MSG_THREAD_LOCK(player);
976                 player->bus_msg_thread_exit = TRUE;
977                 MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
978                 MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
979
980                 LOGD("gst bus msg thread exit.");
981                 g_thread_join(player->bus_msg_thread); /* can request cmd lock */
982                 player->bus_msg_thread = NULL;
983
984                 g_mutex_clear(&player->bus_msg_thread_mutex);
985                 g_cond_clear(&player->bus_msg_thread_cond);
986         }
987
988         g_mutex_lock(&player->bus_msg_q_lock);
989         queue = player->bus_msg_q;
990         while (!g_queue_is_empty(queue)) {
991                 msg = (GstMessage *)g_queue_pop_head(queue);
992                 LOGW("remove remained %s msg", GST_MESSAGE_TYPE_NAME(msg));
993                 gst_message_unref(msg);
994         }
995         g_mutex_unlock(&player->bus_msg_q_lock);
996
997         MMPLAYER_FLEAVE();
998 }
999
1000 gboolean __mmplayer_gst_msg_push(GstBus *bus, GstMessage *msg, gpointer data)
1001 {
1002         mm_player_t *player = (mm_player_t *) data;
1003
1004         g_return_val_if_fail(player, FALSE);
1005         g_return_val_if_fail(msg && GST_IS_MESSAGE(msg), FALSE);
1006
1007         gst_message_ref(msg);
1008
1009         g_mutex_lock(&player->bus_msg_q_lock);
1010         g_queue_push_tail(player->bus_msg_q, msg);
1011         g_mutex_unlock(&player->bus_msg_q_lock);
1012
1013         MMPLAYER_BUS_MSG_THREAD_LOCK(player);
1014         MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
1015         MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
1016         return TRUE;
1017 }
1018
1019 static gpointer __mmplayer_gst_bus_msg_thread(gpointer data)
1020 {
1021         mm_player_t *player = (mm_player_t*)(data);
1022         GstMessage *msg = NULL;
1023         GstBus *bus = NULL;
1024
1025         MMPLAYER_FENTER();
1026         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
1027                                                 player->pipeline &&
1028                                                 player->pipeline->mainbin &&
1029                                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
1030                                                 NULL);
1031
1032         bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
1033         if (!bus) {
1034                 LOGE("cannot get BUS from the pipeline");
1035                 return NULL;
1036         }
1037
1038         MMPLAYER_BUS_MSG_THREAD_LOCK(player);
1039
1040         LOGD("[handle: %p] gst bus msg thread will be started.", player);
1041         while (!player->bus_msg_thread_exit) {
1042                 g_mutex_lock(&player->bus_msg_q_lock);
1043                 msg = g_queue_pop_head(player->bus_msg_q);
1044                 g_mutex_unlock(&player->bus_msg_q_lock);
1045                 if (msg == NULL) {
1046                         MMPLAYER_BUS_MSG_THREAD_WAIT(player);
1047                         continue;
1048                 }
1049                 MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
1050                 /* handle the gst msg */
1051                 __mmplayer_gst_callback(msg, player);
1052                 MMPLAYER_BUS_MSG_THREAD_LOCK(player);
1053                 gst_message_unref(msg);
1054         }
1055
1056         MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
1057         gst_object_unref(GST_OBJECT(bus));
1058
1059         MMPLAYER_FLEAVE();
1060         return NULL;
1061 }
1062
1063 static void
1064 __mmplayer_gst_callback(GstMessage *msg, gpointer data)
1065 {
1066         mm_player_t* player = (mm_player_t*)(data);
1067         static gboolean async_done = FALSE;
1068
1069         MMPLAYER_RETURN_IF_FAIL(player);
1070         MMPLAYER_RETURN_IF_FAIL(msg && GST_IS_MESSAGE(msg));
1071
1072         switch (GST_MESSAGE_TYPE(msg)) {
1073         case GST_MESSAGE_UNKNOWN:
1074                 LOGD("unknown message received\n");
1075                 break;
1076
1077         case GST_MESSAGE_EOS:
1078                 {
1079                         MMHandleType attrs = 0;
1080                         gint count = 0;
1081
1082                         LOGD("GST_MESSAGE_EOS received\n");
1083
1084                         /* NOTE : EOS event is comming multiple time. watch out it */
1085                         /* check state. we only process EOS when pipeline state goes to PLAYING */
1086                         if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)) {
1087                                 LOGD("EOS received on non-playing state. ignoring it\n");
1088                                 break;
1089                         }
1090
1091                         if (player->pipeline) {
1092                                 if (player->pipeline->textbin)
1093                                         __mmplayer_drop_subtitle(player, TRUE);
1094
1095                                 if ((player->audio_stream_cb) && (player->set_mode.pcm_extraction) && (!player->audio_stream_render_cb_ex)) {
1096                                         GstPad *pad = NULL;
1097
1098                                         pad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1099
1100                                         LOGD("release audio callback\n");
1101
1102                                         /* release audio callback */
1103                                         gst_pad_remove_probe(pad, player->audio_cb_probe_id);
1104                                         player->audio_cb_probe_id = 0;
1105                                         /* audio callback should be free because it can be called even though probe remove.*/
1106                                         player->audio_stream_cb = NULL;
1107                                         player->audio_stream_cb_user_param = NULL;
1108
1109                                 }
1110                         }
1111                         if ((player->audio_stream_render_cb_ex) && (!player->audio_stream_sink_sync))
1112                                 __mmplayer_audio_stream_clear_buffer(player, TRUE);
1113
1114                         /* rewind if repeat count is greater then zero */
1115                         /* get play count */
1116                         attrs = MMPLAYER_GET_ATTRS(player);
1117
1118                         if (attrs) {
1119                                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1120
1121                                 LOGD("play count: %d, playback rate: %f\n", count, player->playback_rate);
1122
1123                                 if (count == -1 || player->playback_rate < 0.0) /* default value is 1 */ {
1124                                         if (player->playback_rate < 0.0) {
1125                                                 player->resumed_by_rewind = TRUE;
1126                                                 _mmplayer_set_mute((MMHandleType)player, 0);
1127                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_RESUMED_BY_REW, NULL);
1128                                         }
1129
1130                                         __mmplayer_handle_eos_delay(player, player->ini.delay_before_repeat);
1131
1132                                         /* initialize */
1133                                         player->sent_bos = FALSE;
1134
1135                                         /* not posting eos when repeating */
1136                                         break;
1137                                 }
1138                         }
1139
1140                         if (player->pipeline)
1141                                 MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-eos");
1142
1143                         /* post eos message to application */
1144                         __mmplayer_handle_eos_delay(player, player->ini.eos_delay);
1145
1146                         /* reset last position */
1147                         player->last_position = 0;
1148                 }
1149                 break;
1150
1151         case GST_MESSAGE_ERROR:
1152                 {
1153                         GError *error = NULL;
1154                         gchar* debug = NULL;
1155
1156                         /* generating debug info before returning error */
1157                         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-error");
1158
1159                         /* get error code */
1160                         gst_message_parse_error(msg, &error, &debug);
1161
1162                         if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
1163                                 /* Note : the streaming error from the streaming source is handled
1164                                  *   using __mmplayer_handle_streaming_error.
1165                                  */
1166                                 __mmplayer_handle_streaming_error(player, msg);
1167
1168                                 /* dump state of all element */
1169                                 __mmplayer_dump_pipeline_state(player);
1170                         } else {
1171                                 /* traslate gst error code to msl error code. then post it
1172                                  * to application if needed
1173                                  */
1174                                 __mmplayer_handle_gst_error(player, msg, error);
1175
1176                                 if (debug)
1177                                         LOGE("error debug : %s", debug);
1178                         }
1179
1180                         if (MMPLAYER_IS_HTTP_PD(player))
1181                                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
1182
1183                         MMPLAYER_FREEIF(debug);
1184                         g_error_free(error);
1185                 }
1186                 break;
1187
1188         case GST_MESSAGE_WARNING:
1189                 {
1190                         char* debug = NULL;
1191                         GError* error = NULL;
1192
1193                         gst_message_parse_warning(msg, &error, &debug);
1194
1195                         LOGD("warning : %s\n", error->message);
1196                         LOGD("debug : %s\n", debug);
1197
1198                         MMPLAYER_POST_MSG(player, MM_MESSAGE_WARNING, NULL);
1199
1200                         MMPLAYER_FREEIF(debug);
1201                         g_error_free(error);
1202                 }
1203                 break;
1204
1205         case GST_MESSAGE_TAG:
1206                 {
1207                         LOGD("GST_MESSAGE_TAG\n");
1208                         if (!__mmplayer_gst_extract_tag_from_msg(player, msg))
1209                                 LOGW("failed to extract tags from gstmessage\n");
1210                 }
1211                 break;
1212
1213         case GST_MESSAGE_BUFFERING:
1214                 {
1215                         MMMessageParamType msg_param = {0, };
1216                         int bRet = MM_ERROR_NONE;
1217
1218                         if (!(player->pipeline && player->pipeline->mainbin)) {
1219                                 LOGE("player pipeline handle is null");
1220                                 break;
1221                         }
1222
1223                         if (!MMPLAYER_IS_STREAMING(player))
1224                                 break;
1225
1226                         if (player->pd_mode == MM_PLAYER_PD_MODE_URI) {
1227                                 if (!MMPLAYER_CMD_TRYLOCK(player)) {
1228                                         /* skip the playback control by buffering msg while user request is handled. */
1229                                         gint per = 0;
1230
1231                                         LOGW("[PD mode] can't get cmd lock, only post buffering msg");
1232
1233                                         gst_message_parse_buffering(msg, &per);
1234                                         LOGD("[PD mode][%s] buffering %d %%....", GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)), per);
1235
1236                                         msg_param.connection.buffering = per;
1237                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1238                                         break;
1239                                 }
1240                         } else {
1241                                 MMPLAYER_CMD_LOCK(player);
1242                         }
1243
1244                         /* ignore the prev buffering message */
1245                         if ((player->streamer) && (player->streamer->is_buffering == FALSE)
1246                                 && (player->streamer->is_buffering_done == TRUE)) {
1247                                 gint buffer_percent = 0;
1248
1249                                 gst_message_parse_buffering(msg, &buffer_percent);
1250
1251                                 if (buffer_percent == MAX_BUFFER_PERCENT) {
1252                                         LOGD("Ignored all the previous buffering msg!(got %d%%)\n", buffer_percent);
1253                                         player->streamer->is_buffering_done = FALSE;
1254                                 }
1255                                 MMPLAYER_CMD_UNLOCK(player);
1256                                 break;
1257                         }
1258
1259                         __mmplayer_update_buffer_setting(player, msg);
1260
1261                         bRet = __mmplayer_handle_buffering_message(player);
1262
1263                         if (bRet == MM_ERROR_NONE) {
1264                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1265                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1266
1267                                 if (MMPLAYER_IS_RTSP_STREAMING(player) &&
1268                                         player->pending_resume &&
1269                                         (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) {
1270
1271                                         player->is_external_subtitle_added_now = FALSE;
1272                                         player->pending_resume = FALSE;
1273                                         _mmplayer_resume((MMHandleType)player);
1274                                 }
1275
1276                                 if (MMPLAYER_IS_RTSP_STREAMING(player) &&
1277                                         (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) {
1278
1279                                         if (player->doing_seek) {
1280                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
1281                                                         player->doing_seek = FALSE;
1282                                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1283                                                 } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
1284                                                         async_done = TRUE;
1285                                                 }
1286                                         }
1287                                 }
1288                         } else if (bRet == MM_ERROR_PLAYER_INVALID_STATE) {
1289                                 if (!player->streamer) {
1290                                         LOGW("player->streamer is NULL, so discarding the buffering percent update\n");
1291                                         MMPLAYER_CMD_UNLOCK(player);
1292                                         break;
1293                                 }
1294
1295                                 if ((MMPLAYER_IS_LIVE_STREAMING(player)) && (MMPLAYER_IS_RTSP_STREAMING(player))) {
1296
1297                                         LOGD("player->last_position=%"G_GINT64_FORMAT" , player->streamer->buffering_percent=%d \n",
1298                                                         GST_TIME_AS_SECONDS(player->last_position), player->streamer->buffering_percent);
1299
1300                                         if ((GST_TIME_AS_SECONDS(player->last_position) <= 0) && (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED)) {
1301                                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1302                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1303                                         } else {
1304                                                 LOGD("Not updating Buffering Message for Live RTSP case !!!\n");
1305                                         }
1306                                 } else {
1307                                         msg_param.connection.buffering = player->streamer->buffering_percent;
1308                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1309                                 }
1310                         }
1311                         MMPLAYER_CMD_UNLOCK(player);
1312                 }
1313                 break;
1314
1315         case GST_MESSAGE_STATE_CHANGED:
1316                 {
1317                         MMPlayerGstElement *mainbin;
1318                         const GValue *voldstate, *vnewstate, *vpending;
1319                         GstState oldstate = GST_STATE_NULL;
1320                         GstState newstate = GST_STATE_NULL;
1321                         GstState pending = GST_STATE_NULL;
1322
1323                         if (!(player->pipeline && player->pipeline->mainbin)) {
1324                                 LOGE("player pipeline handle is null");
1325                                 break;
1326                         }
1327
1328                         mainbin = player->pipeline->mainbin;
1329
1330                         /* we only handle messages from pipeline */
1331                         if (msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst)
1332                                 break;
1333
1334                         /* get state info from msg */
1335                         voldstate = gst_structure_get_value(gst_message_get_structure(msg), "old-state");
1336                         vnewstate = gst_structure_get_value(gst_message_get_structure(msg), "new-state");
1337                         vpending = gst_structure_get_value(gst_message_get_structure(msg), "pending-state");
1338
1339                         if (!voldstate || !vnewstate) {
1340                                 LOGE("received msg has wrong format.");
1341                                 break;
1342                         }
1343
1344                         oldstate = (GstState)voldstate->data[0].v_int;
1345                         newstate = (GstState)vnewstate->data[0].v_int;
1346                         if (vpending)
1347                                 pending = (GstState)vpending->data[0].v_int;
1348
1349                         LOGD("state changed [%s] : %s ---> %s     final : %s\n",
1350                                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
1351                                 gst_element_state_get_name((GstState)oldstate),
1352                                 gst_element_state_get_name((GstState)newstate),
1353                                 gst_element_state_get_name((GstState)pending));
1354
1355                         if (newstate == GST_STATE_PLAYING) {
1356                                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) && (player->pending_seek.is_pending)) {
1357
1358                                         int retVal = MM_ERROR_NONE;
1359                                         LOGD("trying to play from (%"G_GINT64_FORMAT") pending position\n", player->pending_seek.pos);
1360
1361                                         retVal = __gst_set_position(player, player->pending_seek.format, player->pending_seek.pos, TRUE);
1362
1363                                         if (MM_ERROR_NONE != retVal)
1364                                                 LOGE("failed to seek pending postion. just keep staying current position.\n");
1365
1366                                         player->pending_seek.is_pending = FALSE;
1367                                 }
1368                         }
1369
1370                         if (oldstate == newstate) {
1371                                 LOGD("pipeline reports state transition to old state");
1372                                 break;
1373                         }
1374
1375                         switch (newstate) {
1376                         case GST_STATE_VOID_PENDING:
1377                                 break;
1378
1379                         case GST_STATE_NULL:
1380                                 break;
1381
1382                         case GST_STATE_READY:
1383                                 break;
1384
1385                         case GST_STATE_PAUSED:
1386                                 {
1387                                         gboolean prepare_async = FALSE;
1388                                         player->bus_msg_timeout = PLAYER_BUS_MSG_DEFAULT_TIMEOUT;
1389
1390                                         if (!player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
1391                                                 __mmplayer_configure_audio_callback(player);
1392
1393                                         if (!player->sent_bos && oldstate == GST_STATE_READY) {
1394                                                 // managed prepare async case
1395                                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
1396                                                 LOGD("checking prepare mode for async transition - %d", prepare_async);
1397                                         }
1398
1399                                         if (MMPLAYER_IS_STREAMING(player) || MMPLAYER_IS_MS_BUFF_SRC(player) || prepare_async) {
1400                                                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
1401
1402                                                 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
1403                                                         __mm_player_streaming_set_content_bitrate(player->streamer,
1404                                                                 player->total_maximum_bitrate, player->total_bitrate);
1405
1406                                                 if (player->pending_seek.is_pending) {
1407                                                         LOGW("trying to do pending seek");
1408                                                         MMPLAYER_CMD_LOCK(player);
1409                                                         __gst_pending_seek(player);
1410                                                         MMPLAYER_CMD_UNLOCK(player);
1411                                                 }
1412                                         }
1413                                 }
1414                                 break;
1415
1416                         case GST_STATE_PLAYING:
1417                                 {
1418                                         player->bus_msg_timeout = PLAYER_BUS_MSG_DEFAULT_TIMEOUT;
1419
1420                                         if (MMPLAYER_IS_STREAMING(player)) {
1421                                                 // managed prepare async case when buffering is completed
1422                                                 // pending state should be reset otherwise, it's still playing even though it's resumed after bufferging.
1423                                                 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
1424                                                         (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
1425                                                         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
1426
1427                                                 if (MMPLAYER_IS_RTSP_STREAMING(player) && (MMPLAYER_IS_LIVE_STREAMING(player))) {
1428
1429                                                         LOGD("Current Buffering Percent = %d", player->streamer->buffering_percent);
1430                                                         if (player->streamer->buffering_percent < 100) {
1431
1432                                                                 MMMessageParamType msg_param = {0, };
1433                                                                 LOGW("Posting Buffering Completed Message to Application !!!");
1434
1435                                                                 msg_param.connection.buffering = 100;
1436                                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1437                                                         }
1438                                                 }
1439                                         }
1440
1441                                         if (player->gapless.stream_changed) {
1442                                                 _mmplayer_update_content_attrs(player, ATTR_ALL);
1443                                                 player->gapless.stream_changed = FALSE;
1444                                         }
1445
1446                                         if (player->doing_seek && async_done) {
1447                                                 player->doing_seek = FALSE;
1448                                                 async_done = FALSE;
1449                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1450                                         }
1451                                 }
1452                                 break;
1453
1454                         default:
1455                                 break;
1456                         }
1457                 }
1458                 break;
1459
1460         case GST_MESSAGE_CLOCK_LOST:
1461                         {
1462                                 GstClock *clock = NULL;
1463                                 gboolean need_new_clock = FALSE;
1464
1465                                 gst_message_parse_clock_lost(msg, &clock);
1466                                 LOGD("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
1467
1468                                 if (!player->videodec_linked)
1469                                         need_new_clock = TRUE;
1470                                 else if (!player->ini.use_system_clock)
1471                                         need_new_clock = TRUE;
1472
1473                                 if (need_new_clock) {
1474                                         LOGD("Provide clock is TRUE, do pause->resume\n");
1475                                         __gst_pause(player, FALSE);
1476                                         __gst_resume(player, FALSE);
1477                                 }
1478                         }
1479                         break;
1480
1481         case GST_MESSAGE_NEW_CLOCK:
1482                         {
1483                                 GstClock *clock = NULL;
1484                                 gst_message_parse_new_clock(msg, &clock);
1485                                 LOGD("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
1486                         }
1487                         break;
1488
1489         case GST_MESSAGE_ELEMENT:
1490                         {
1491                                 const gchar *structure_name;
1492                                 gint count = 0, idx = 0;
1493                                 MMHandleType attrs = 0;
1494
1495                                 attrs = MMPLAYER_GET_ATTRS(player);
1496                                 if (!attrs) {
1497                                         LOGE("cannot get content attribute");
1498                                         break;
1499                                 }
1500
1501                                 if (gst_message_get_structure(msg) == NULL)
1502                                         break;
1503
1504                                 structure_name = gst_structure_get_name(gst_message_get_structure(msg));
1505                                 if (!structure_name)
1506                                         break;
1507
1508                                 LOGD("GST_MESSAGE_ELEMENT %s from %s", structure_name, GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)));
1509
1510                                 if (!strcmp(structure_name, "adaptive-streaming-variant")) {
1511                                         const GValue *var_info = NULL;
1512
1513                                         var_info = gst_structure_get_value(gst_message_get_structure(msg), "video-variant-info");
1514                                         if (var_info != NULL) {
1515                                                 if (player->adaptive_info.var_list)
1516                                                         g_list_free_full(player->adaptive_info.var_list, g_free);
1517
1518                                                 /* share addr or copy the list */
1519                                                 player->adaptive_info.var_list =
1520                                                         g_list_copy_deep((GList *)g_value_get_pointer(var_info), (GCopyFunc)__mmplayer_adaptive_var_info, NULL);
1521
1522                                                 count = g_list_length(player->adaptive_info.var_list);
1523                                                 if (count > 0) {
1524                                                         VariantData *temp = NULL;
1525
1526                                                         /* print out for debug */
1527                                                         LOGD("num of variant_info %d", count);
1528                                                         for (idx = 0; idx < count; idx++) {
1529                                                                 temp = g_list_nth_data(player->adaptive_info.var_list, idx);
1530                                                                 if (temp)
1531                                                                         LOGD("variant(%d) [b]%d [w]%d [h]%d ", idx, temp->bandwidth, temp->width, temp->height);
1532                                                         }
1533                                                 }
1534                                         }
1535                                 }
1536
1537                                 if (!strcmp(structure_name, "prepare-decode-buffers")) {
1538                                         gint num_buffers = 0;
1539                                         gint extra_num_buffers = 0;
1540
1541                                         if (gst_structure_get_int(gst_message_get_structure(msg), "num_buffers", &num_buffers)) {
1542                                                 player->video_num_buffers = num_buffers;
1543                                                 LOGD("video_num_buffers : %d", player->video_num_buffers);
1544                                         }
1545
1546                                         if (gst_structure_get_int(gst_message_get_structure(msg), "extra_num_buffers", &extra_num_buffers)) {
1547                                                 player->video_extra_num_buffers = extra_num_buffers;
1548                                                 LOGD("num_of_vout_extra num buffers : %d", extra_num_buffers);
1549                                         }
1550                                         break;
1551                                 }
1552
1553                                 if (!strcmp(structure_name, "Language_list")) {
1554                                         const GValue *lang_list = NULL;
1555                                         lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
1556                                         if (lang_list != NULL) {
1557                                                 count = g_list_length((GList *)g_value_get_pointer(lang_list));
1558                                                 if (count > 1)
1559                                                         LOGD("Total audio tracks(from parser) = %d \n", count);
1560                                         }
1561                                 }
1562
1563                                 if (!strcmp(structure_name, "Ext_Sub_Language_List")) {
1564                                         const GValue *lang_list = NULL;
1565                                         MMPlayerLangStruct *temp = NULL;
1566
1567                                         lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
1568                                         if (lang_list != NULL) {
1569                                                 count = g_list_length((GList *)g_value_get_pointer(lang_list));
1570                                                 if (count) {
1571                                                         MMPLAYER_SUBTITLE_INFO_LOCK(player);
1572                                                         player->subtitle_language_list = (GList *)g_value_get_pointer(lang_list);
1573                                                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
1574                                                         if (mmf_attrs_commit(attrs))
1575                                                                 LOGE("failed to commit.\n");
1576                                                         LOGD("Total subtitle tracks = %d \n", count);
1577
1578                                                         while (count) {
1579                                                                 temp = g_list_nth_data(player->subtitle_language_list, count - 1);
1580                                                                 if (temp)
1581                                                                         LOGD("value of lang_key is %s and lang_code is %s",
1582                                                                                                 temp->language_key, temp->language_code);
1583                                                                 count--;
1584                                                         }
1585                                                         MMPLAYER_SUBTITLE_INFO_SIGNAL(player);
1586                                                         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
1587                                                 }
1588                                         }
1589                                 }
1590
1591                                 /* custom message */
1592                                 if (!strcmp(structure_name, "audio_codec_not_supported")) {
1593                                         MMMessageParamType msg_param = {0,};
1594                                         msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
1595                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
1596                                 }
1597
1598                                 /* custom message for RTSP attribute :
1599                                     RTSP case, buffer is not come from server before PLAYING state. However,we have to get attribute after PAUSE state chaged.
1600                                     sdp which has contents info is received when rtsp connection is opened.
1601                                     extract duration ,codec info , resolution from sdp and get it by GstMessage */
1602                                 if (!strcmp(structure_name, "rtspsrc_properties")) {
1603
1604                                         gchar *audio_codec = NULL;
1605                                         gchar *video_codec = NULL;
1606                                         gchar *video_frame_size = NULL;
1607
1608                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_duration", G_TYPE_UINT64, &player->duration, NULL);
1609                                         LOGD("rtsp duration : %"G_GINT64_FORMAT" msec", GST_TIME_AS_MSECONDS(player->duration));
1610                                         player->streaming_type = __mmplayer_get_stream_service_type(player);
1611
1612                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_audio_codec", G_TYPE_STRING, &audio_codec, NULL);
1613                                         LOGD("rtsp_audio_codec : %s", audio_codec);
1614                                         if (audio_codec)
1615                                                 mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1616
1617                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_video_codec", G_TYPE_STRING, &video_codec, NULL);
1618                                         LOGD("rtsp_video_codec : %s", video_codec);
1619                                         if (video_codec)
1620                                                 mm_attrs_set_string_by_name(player->attrs, "content_video_codec", video_codec);
1621
1622                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_video_frame_size", G_TYPE_STRING, &video_frame_size, NULL);
1623                                         LOGD("rtsp_video_frame_size : %s", video_frame_size);
1624                                         if (video_frame_size) {
1625
1626                                                 char *seperator = strchr(video_frame_size, '-');
1627                                                 if (seperator) {
1628
1629                                                         char video_width[10] = {0,};
1630                                                         int frame_size_len = strlen(video_frame_size);
1631                                                         int separtor_len = strlen(seperator);
1632
1633                                                         strncpy(video_width, video_frame_size, (frame_size_len - separtor_len));
1634                                                         mm_attrs_set_int_by_name(attrs, "content_video_width", atoi(video_width));
1635
1636                                                         seperator++;
1637                                                         mm_attrs_set_int_by_name(attrs, "content_video_height", atoi(seperator));
1638                                                 }
1639                                         }
1640
1641                                         if (mmf_attrs_commit(attrs))
1642                                                 LOGE("failed to commit.\n");
1643                                 }
1644                         }
1645                         break;
1646
1647         case GST_MESSAGE_DURATION_CHANGED:
1648                 {
1649                         LOGD("GST_MESSAGE_DURATION_CHANGED\n");
1650                         if (!__mmplayer_gst_handle_duration(player, msg))
1651                                 LOGW("failed to update duration");
1652                 }
1653
1654                 break;
1655
1656         case GST_MESSAGE_ASYNC_START:
1657                         LOGD("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1658                 break;
1659
1660         case GST_MESSAGE_ASYNC_DONE:
1661                 {
1662                         LOGD("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1663
1664                         /* we only handle messages from pipeline */
1665                         if (msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst)
1666                                 break;
1667
1668                         if (player->doing_seek) {
1669                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
1670                                         player->doing_seek = FALSE;
1671                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1672                                 } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
1673                                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1674                                                 (player->streamer) &&
1675                                                 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
1676                                                 (player->streamer->is_buffering == FALSE)) {
1677                                                 GstQuery *query = NULL;
1678                                                 gboolean busy = FALSE;
1679                                                 gint percent = 0;
1680
1681                                                 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer) {
1682                                                         query = gst_query_new_buffering(GST_FORMAT_PERCENT);
1683                                                         if (gst_element_query(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query))
1684                                                                 gst_query_parse_buffering_percent(query, &busy, &percent);
1685                                                         gst_query_unref(query);
1686
1687                                                         LOGD("buffered percent(%s): %d\n",
1688                                                                 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
1689                                                 }
1690
1691                                                 if (percent >= 100) {
1692                                                         player->streamer->is_buffering = FALSE;
1693                                                         __mmplayer_handle_buffering_message(player);
1694                                                 }
1695                                         }
1696
1697                                         async_done = TRUE;
1698                                 }
1699                         }
1700                 }
1701                 break;
1702
1703         #if 0 /* delete unnecessary logs */
1704         case GST_MESSAGE_REQUEST_STATE:         LOGD("GST_MESSAGE_REQUEST_STATE\n"); break;
1705         case GST_MESSAGE_STEP_START:            LOGD("GST_MESSAGE_STEP_START\n"); break;
1706         case GST_MESSAGE_QOS:                           LOGD("GST_MESSAGE_QOS\n"); break;
1707         case GST_MESSAGE_PROGRESS:                      LOGD("GST_MESSAGE_PROGRESS\n"); break;
1708         case GST_MESSAGE_ANY:                           LOGD("GST_MESSAGE_ANY\n"); break;
1709         case GST_MESSAGE_INFO:                          LOGD("GST_MESSAGE_STATE_DIRTY\n"); break;
1710         case GST_MESSAGE_STATE_DIRTY:           LOGD("GST_MESSAGE_STATE_DIRTY\n"); break;
1711         case GST_MESSAGE_STEP_DONE:                     LOGD("GST_MESSAGE_STEP_DONE\n"); break;
1712         case GST_MESSAGE_CLOCK_PROVIDE:         LOGD("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
1713         case GST_MESSAGE_STRUCTURE_CHANGE:      LOGD("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
1714         case GST_MESSAGE_STREAM_STATUS:         LOGD("GST_MESSAGE_STREAM_STATUS\n"); break;
1715         case GST_MESSAGE_APPLICATION:           LOGD("GST_MESSAGE_APPLICATION\n"); break;
1716         case GST_MESSAGE_SEGMENT_START:         LOGD("GST_MESSAGE_SEGMENT_START\n"); break;
1717         case GST_MESSAGE_SEGMENT_DONE:          LOGD("GST_MESSAGE_SEGMENT_DONE\n"); break;
1718         case GST_MESSAGE_LATENCY:                               LOGD("GST_MESSAGE_LATENCY\n"); break;
1719         #endif
1720
1721         default:
1722                 break;
1723         }
1724
1725         /* should not call 'gst_message_unref(msg)' */
1726         return;
1727 }
1728
1729 static gboolean
1730 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
1731 {
1732         gint64 bytes = 0;
1733
1734         MMPLAYER_FENTER();
1735
1736         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
1737         MMPLAYER_RETURN_VAL_IF_FAIL(msg, FALSE);
1738
1739         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1740                 (msg->src) && (msg->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst)) {
1741                 LOGD("msg src : [%s]", GST_ELEMENT_NAME(GST_ELEMENT_CAST(msg->src)));
1742
1743                 if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes)) {
1744                         LOGD("data total size of http content: %"G_GINT64_FORMAT, bytes);
1745                         player->http_content_size = (bytes > 0) ? (bytes) : (0);
1746                 }
1747         } else
1748                 /* handling audio clip which has vbr. means duration is keep changing */
1749                 _mmplayer_update_content_attrs(player, ATTR_DURATION);
1750
1751         MMPLAYER_FLEAVE();
1752
1753         return TRUE;
1754 }
1755
1756 static void __mmplayer_get_metadata_360_from_tags(GstTagList *tags,
1757                 mm_player_spherical_metadata_t *metadata) {
1758         gst_tag_list_get_int(tags, "is_spherical", &metadata->is_spherical);
1759         gst_tag_list_get_int(tags, "is_stitched", &metadata->is_stitched);
1760         gst_tag_list_get_string(tags, "stitching_software",
1761                         &metadata->stitching_software);
1762         gst_tag_list_get_string(tags, "projection_type",
1763                         &metadata->projection_type_string);
1764         gst_tag_list_get_string(tags, "stereo_mode", &metadata->stereo_mode_string);
1765         gst_tag_list_get_int(tags, "source_count", &metadata->source_count);
1766         gst_tag_list_get_int(tags, "init_view_heading",
1767                         &metadata->init_view_heading);
1768         gst_tag_list_get_int(tags, "init_view_pitch", &metadata->init_view_pitch);
1769         gst_tag_list_get_int(tags, "init_view_roll", &metadata->init_view_roll);
1770         gst_tag_list_get_int(tags, "timestamp", &metadata->timestamp);
1771         gst_tag_list_get_int(tags, "full_pano_width_pixels",
1772                         &metadata->full_pano_width_pixels);
1773         gst_tag_list_get_int(tags, "full_pano_height_pixels",
1774                         &metadata->full_pano_height_pixels);
1775         gst_tag_list_get_int(tags, "cropped_area_image_width",
1776                         &metadata->cropped_area_image_width);
1777         gst_tag_list_get_int(tags, "cropped_area_image_height",
1778                         &metadata->cropped_area_image_height);
1779         gst_tag_list_get_int(tags, "cropped_area_left",
1780                         &metadata->cropped_area_left);
1781         gst_tag_list_get_int(tags, "cropped_area_top", &metadata->cropped_area_top);
1782         gst_tag_list_get_int(tags, "ambisonic_type", &metadata->ambisonic_type);
1783         gst_tag_list_get_int(tags, "ambisonic_format", &metadata->ambisonic_format);
1784         gst_tag_list_get_int(tags, "ambisonic_order", &metadata->ambisonic_order);
1785 }
1786
1787 static gboolean
1788 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg)
1789 {
1790
1791 /* macro for better code readability */
1792 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
1793 if (gst_tag_list_get_string(tag_list, gsttag, &string)) {\
1794         if (string != NULL) { \
1795                 SECURE_LOGD("update tag string : %s\n", string); \
1796                 if (strlen(string) > MM_MAX_STRING_LENGTH) { \
1797                         char *new_string = malloc(MM_MAX_STRING_LENGTH); \
1798                         strncpy(new_string, string, MM_MAX_STRING_LENGTH-1); \
1799                         new_string[MM_MAX_STRING_LENGTH-1] = '\0'; \
1800                         mm_attrs_set_string_by_name(attribute, playertag, new_string); \
1801                         g_free(new_string); \
1802                         new_string = NULL; \
1803                 } else { \
1804                         mm_attrs_set_string_by_name(attribute, playertag, string); \
1805                 } \
1806                 g_free(string); \
1807                 string = NULL; \
1808         } \
1809 }
1810
1811 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
1812 do {    \
1813         GstSample *sample = NULL;\
1814         if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample)) {\
1815                 GstMapInfo info = GST_MAP_INFO_INIT;\
1816                 buffer = gst_sample_get_buffer(sample);\
1817                 if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) {\
1818                         LOGD("failed to get image data from tag");\
1819                         gst_sample_unref(sample);\
1820                         return FALSE;\
1821                 } \
1822                 SECURE_LOGD("update album cover data : %p, size : %d\n", info.data, info.size);\
1823                 MMPLAYER_FREEIF(player->album_art);\
1824                 player->album_art = (gchar *)g_malloc(info.size);\
1825                 if (player->album_art) {\
1826                         memcpy(player->album_art, info.data, info.size);\
1827                         mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, info.size);\
1828                         if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {\
1829                                 msg_param.data = (void *)player->album_art;\
1830                                 msg_param.size = info.size;\
1831                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_IMAGE_BUFFER, &msg_param);\
1832                                 SECURE_LOGD("post message image buffer data : %p, size : %d\n", info.data, info.size);\
1833                         } \
1834                 } \
1835                 gst_buffer_unmap(buffer, &info);\
1836                 gst_sample_unref(sample);\
1837         }       \
1838 } while (0)
1839
1840 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
1841 do {    \
1842         if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint)) { \
1843                 if (v_uint) { \
1844                         int i = 0; \
1845                         gchar *tag_list_str = NULL; \
1846                         MMPlayerTrackType track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
1847                         if (strstr(GST_OBJECT_NAME(msg->src), "audio")) \
1848                                 track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
1849                         else if (strstr(GST_OBJECT_NAME(msg->src), "video")) \
1850                                 track_type = MM_PLAYER_TRACK_TYPE_VIDEO; \
1851                         else \
1852                                 track_type = MM_PLAYER_TRACK_TYPE_TEXT; \
1853                         if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) { \
1854                                 if (track_type == MM_PLAYER_TRACK_TYPE_AUDIO) \
1855                                         mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
1856                                 player->bitrate[track_type] = v_uint; \
1857                                 player->total_bitrate = 0; \
1858                                 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
1859                                         player->total_bitrate += player->bitrate[i]; \
1860                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate); \
1861                                 SECURE_LOGD("update bitrate %d[bps] of stream #%d.\n", v_uint, (int)track_type); \
1862                         } else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) { \
1863                                 player->maximum_bitrate[track_type] = v_uint; \
1864                                 player->total_maximum_bitrate = 0; \
1865                                 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
1866                                         player->total_maximum_bitrate += player->maximum_bitrate[i]; \
1867                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate);\
1868                                 SECURE_LOGD("update maximum bitrate %d[bps] of stream #%d\n", v_uint, (int)track_type);\
1869                         } else { \
1870                                 mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
1871                         } \
1872                         v_uint = 0;\
1873                         g_free(tag_list_str); \
1874                 } \
1875         } \
1876 } while (0)
1877
1878 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
1879 if (gst_tag_list_get_date(tag_list, gsttag, &date)) {\
1880         if (date != NULL) {\
1881                 string = g_strdup_printf("%d", g_date_get_year(date));\
1882                 mm_attrs_set_string_by_name(attribute, playertag, string);\
1883                 SECURE_LOGD("metainfo year : %s\n", string);\
1884                 MMPLAYER_FREEIF(string);\
1885                 g_date_free(date);\
1886         } \
1887 }
1888
1889 #define MMPLAYER_UPDATE_TAG_DATE_TIME(gsttag, attribute, playertag) \
1890 if (gst_tag_list_get_date_time(tag_list, gsttag, &datetime)) {\
1891         if (datetime != NULL) {\
1892                 string = g_strdup_printf("%d", gst_date_time_get_year(datetime));\
1893                 mm_attrs_set_string_by_name(attribute, playertag, string);\
1894                 SECURE_LOGD("metainfo year : %s\n", string);\
1895                 MMPLAYER_FREEIF(string);\
1896                 gst_date_time_unref(datetime);\
1897         } \
1898 }
1899
1900 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
1901 if (gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64)) {\
1902         if (v_uint64) {\
1903                 /* FIXIT : don't know how to store date */\
1904                 g_assert(1);\
1905                 v_uint64 = 0;\
1906         } \
1907 }
1908
1909 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
1910 if (gst_tag_list_get_double(tag_list, gsttag, &v_double)) {\
1911         if (v_double) {\
1912                 /* FIXIT : don't know how to store date */\
1913                 g_assert(1);\
1914                 v_double = 0;\
1915         } \
1916 }
1917
1918         /* function start */
1919         GstTagList* tag_list = NULL;
1920
1921         MMHandleType attrs = 0;
1922
1923         char *string = NULL;
1924         guint v_uint = 0;
1925         GDate *date = NULL;
1926         GstDateTime *datetime = NULL;
1927         /* album cover */
1928         GstBuffer *buffer = NULL;
1929         gint index = 0;
1930         MMMessageParamType msg_param = {0, };
1931
1932         /* currently not used. but those are needed for above macro */
1933         //guint64 v_uint64 = 0;
1934         //gdouble v_double = 0;
1935
1936         MMPLAYER_RETURN_VAL_IF_FAIL(player && msg, FALSE);
1937
1938         attrs = MMPLAYER_GET_ATTRS(player);
1939
1940         MMPLAYER_RETURN_VAL_IF_FAIL(attrs, FALSE);
1941
1942         /* get tag list from gst message */
1943         gst_message_parse_tag(msg, &tag_list);
1944
1945         /* store tags to player attributes */
1946         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
1947         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
1948         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
1949         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
1950         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
1951         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
1952         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
1953         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
1954         MMPLAYER_UPDATE_TAG_DATE_TIME(GST_TAG_DATE_TIME, attrs, "tag_date");
1955         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
1956         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
1957         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
1958         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
1959         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
1960         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
1961         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
1962         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
1963         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
1964         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
1965         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
1966         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
1967         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
1968         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
1969         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
1970         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
1971         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
1972         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
1973         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
1974         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
1975         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
1976         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
1977         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
1978         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
1979         MMPLAYER_UPDATE_TAG_LOCK(player);
1980         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
1981         MMPLAYER_UPDATE_TAG_UNLOCK(player);
1982         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
1983         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
1984         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
1985         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
1986         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
1987         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
1988         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
1989         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
1990         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
1991         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
1992         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
1993         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
1994         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, attrs, "content_video_orientation");
1995
1996         if (strstr(GST_OBJECT_NAME(msg->src), "demux")) {
1997                 if (player->video360_metadata.is_spherical == -1) {
1998                         __mmplayer_get_metadata_360_from_tags(tag_list, &player->video360_metadata);
1999                         mm_attrs_set_int_by_name(attrs, "content_video_is_spherical",
2000                                         player->video360_metadata.is_spherical);
2001                         if (player->video360_metadata.is_spherical == 1) {
2002                                 LOGD("This is spherical content for 360 playback.");
2003                                 player->is_content_spherical = TRUE;
2004                         } else {
2005                                 LOGD("This is not spherical content");
2006                                 player->is_content_spherical = FALSE;
2007                         }
2008
2009                         if (player->video360_metadata.projection_type_string) {
2010                                 if (!strcmp(player->video360_metadata.projection_type_string, "equirectangular")) {
2011                                         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
2012                                 } else {
2013                                         LOGE("Projection %s: code not implemented.\n", player->video360_metadata.projection_type_string);
2014                                         player->is_content_spherical = player->is_video360_enabled = FALSE;
2015                                 }
2016                         }
2017
2018                         if (player->video360_metadata.stereo_mode_string) {
2019                                 if (!strcmp(player->video360_metadata.stereo_mode_string, "mono")) {
2020                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
2021                                 } else if (!strcmp(player->video360_metadata.stereo_mode_string, "left-right")) {
2022                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_STEREOSCOPIC_LEFT_RIGHT;
2023                                 } else if (!strcmp(player->video360_metadata.stereo_mode_string, "top-bottom")) {
2024                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_STEREOSCOPIC_TOP_BOTTOM;
2025                                 } else {
2026                                         LOGE("Stereo mode %s: code not implemented.\n", player->video360_metadata.stereo_mode_string);
2027                                         player->is_content_spherical = player->is_video360_enabled = FALSE;
2028                                 }
2029                         }
2030                 }
2031         }
2032
2033         if (mmf_attrs_commit(attrs))
2034                 LOGE("failed to commit.\n");
2035
2036         gst_tag_list_free(tag_list);
2037
2038         return TRUE;
2039 }
2040
2041 static void
2042 __mmplayer_gst_rtp_no_more_pads(GstElement *element,  gpointer data)
2043 {
2044         mm_player_t* player = (mm_player_t*) data;
2045
2046         MMPLAYER_FENTER();
2047
2048         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2049           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2050           * num_dynamic_pad. and this is no-more-pad situation which means no more pad will be added.
2051           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2052
2053           * [1] audio and video will be dumped with filesink.
2054           * [2] autoplugging is done by just using pad caps.
2055           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
2056           * and the video will be dumped via filesink.
2057           */
2058         if (player->num_dynamic_pad == 0) {
2059                 LOGD("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
2060
2061                 if (!__mmplayer_gst_remove_fakesink(player,
2062                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]))
2063                         /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
2064                          * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
2065                          * source element are not same. To overcome this situation, this function will called
2066                          * several places and several times. Therefore, this is not an error case.
2067                          */
2068                         return;
2069         }
2070
2071         /* create dot before error-return. for debugging */
2072         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-no-more-pad");
2073
2074         player->no_more_pad = TRUE;
2075
2076         MMPLAYER_FLEAVE();
2077 }
2078
2079 static gboolean
2080 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink)
2081 {
2082         GstElement* parent = NULL;
2083
2084         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
2085
2086         /* if we have no fakesink. this meas we are using decodebin which doesn'
2087         t need to add extra fakesink */
2088         MMPLAYER_RETURN_VAL_IF_FAIL(fakesink, TRUE);
2089
2090         /* lock */
2091         MMPLAYER_FSINK_LOCK(player);
2092
2093         if (!fakesink->gst)
2094                 goto ERROR;
2095
2096         /* get parent of fakesink */
2097         parent = (GstElement*)gst_object_get_parent((GstObject*)fakesink->gst);
2098         if (!parent) {
2099                 LOGD("fakesink already removed\n");
2100                 goto ERROR;
2101         }
2102
2103         gst_element_set_locked_state(fakesink->gst, TRUE);
2104
2105         /* setting the state to NULL never returns async
2106          * so no need to wait for completion of state transiton
2107          */
2108         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(fakesink->gst, GST_STATE_NULL))
2109                 LOGE("fakesink state change failure!\n");
2110                 /* FIXIT : should I return here? or try to proceed to next? */
2111                 /* return FALSE; */
2112
2113         /* remove fakesink from it's parent */
2114         if (!gst_bin_remove(GST_BIN(parent), fakesink->gst)) {
2115                 LOGE("failed to remove fakesink\n");
2116
2117                 gst_object_unref(parent);
2118
2119                 goto ERROR;
2120         }
2121
2122         gst_object_unref(parent);
2123
2124         LOGD("state-holder removed\n");
2125
2126         gst_element_set_locked_state(fakesink->gst, FALSE);
2127
2128         MMPLAYER_FSINK_UNLOCK(player);
2129         return TRUE;
2130
2131 ERROR:
2132         if (fakesink->gst)
2133                 gst_element_set_locked_state(fakesink->gst, FALSE);
2134
2135         MMPLAYER_FSINK_UNLOCK(player);
2136         return FALSE;
2137 }
2138
2139
2140 static void
2141 __mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data)
2142 {
2143         GstPad *sinkpad = NULL;
2144         GstCaps* caps = NULL;
2145         GstElement* new_element = NULL;
2146         GstStructure* str = NULL;
2147         const gchar* name = NULL;
2148
2149         mm_player_t* player = (mm_player_t*) data;
2150
2151         MMPLAYER_FENTER();
2152
2153         MMPLAYER_RETURN_IF_FAIL(element && pad);
2154         MMPLAYER_RETURN_IF_FAIL(player &&
2155                                         player->pipeline &&
2156                                         player->pipeline->mainbin);
2157
2158
2159         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2160          * num_dynamic_pad will decreased after creating a sinkbin.
2161          */
2162         player->num_dynamic_pad++;
2163         LOGD("stream count inc : %d\n", player->num_dynamic_pad);
2164
2165         caps = gst_pad_query_caps(pad, NULL);
2166
2167         MMPLAYER_CHECK_NULL(caps);
2168
2169         /* clear  previous result*/
2170         player->have_dynamic_pad = FALSE;
2171
2172         str = gst_caps_get_structure(caps, 0);
2173
2174         if (!str) {
2175                 LOGE("cannot get structure from caps.\n");
2176                 goto ERROR;
2177         }
2178
2179         name = gst_structure_get_name(str);
2180         if (!name) {
2181                 LOGE("cannot get mimetype from structure.\n");
2182                 goto ERROR;
2183         }
2184
2185         if (strstr(name, "video")) {
2186                 gint stype = 0;
2187                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
2188
2189                 if (stype == MM_DISPLAY_SURFACE_NULL || stype == MM_DISPLAY_SURFACE_REMOTE) {
2190                         if (player->v_stream_caps) {
2191                                 gst_caps_unref(player->v_stream_caps);
2192                                 player->v_stream_caps = NULL;
2193                         }
2194
2195                         new_element = gst_element_factory_make("fakesink", NULL);
2196                         player->num_dynamic_pad--;
2197                         goto NEW_ELEMENT;
2198                 }
2199         }
2200
2201         /* clear  previous result*/
2202         player->have_dynamic_pad = FALSE;
2203
2204         if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
2205                 LOGE("failed to autoplug for caps");
2206                 goto ERROR;
2207         }
2208
2209         /* check if there's dynamic pad*/
2210         if (player->have_dynamic_pad) {
2211                 LOGE("using pad caps assums there's no dynamic pad !\n");
2212                 goto ERROR;
2213         }
2214
2215         gst_caps_unref(caps);
2216         caps = NULL;
2217
2218 NEW_ELEMENT:
2219
2220         /* excute new_element if created*/
2221         if (new_element) {
2222                 LOGD("adding new element to pipeline\n");
2223
2224                 /* set state to READY before add to bin */
2225                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_READY);
2226
2227                 /* add new element to the pipeline */
2228                 if (FALSE == gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)) {
2229                         LOGE("failed to add autoplug element to bin\n");
2230                         goto ERROR;
2231                 }
2232
2233                 /* get pad from element */
2234                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(new_element), "sink");
2235                 if (!sinkpad) {
2236                         LOGE("failed to get sinkpad from autoplug element\n");
2237                         goto ERROR;
2238                 }
2239
2240                 /* link it */
2241                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2242                         LOGE("failed to link autoplug element\n");
2243                         goto ERROR;
2244                 }
2245
2246                 gst_object_unref(sinkpad);
2247                 sinkpad = NULL;
2248
2249                 /* run. setting PLAYING here since streamming source is live source */
2250                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_PLAYING);
2251         }
2252
2253         if (caps)
2254                 gst_caps_unref(caps);
2255
2256         MMPLAYER_FLEAVE();
2257
2258         return;
2259
2260 STATE_CHANGE_FAILED:
2261 ERROR:
2262         /* FIXIT : take care if new_element has already added to pipeline */
2263         if (new_element)
2264                 gst_object_unref(GST_OBJECT(new_element));
2265
2266         if (sinkpad)
2267                 gst_object_unref(GST_OBJECT(sinkpad));
2268
2269         if (caps)
2270                 gst_caps_unref(caps);
2271
2272         /* FIXIT : how to inform this error to MSL ????? */
2273         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2274          * then post an error to application
2275          */
2276 }
2277
2278 static GstPadProbeReturn
2279 __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
2280 {
2281         LOGD("pad(%s:%s) is blocked", GST_DEBUG_PAD_NAME(pad));
2282         return GST_PAD_PROBE_OK;
2283 }
2284
2285 static GstPadProbeReturn
2286 __mmplayer_gst_selector_event_probe(GstPad * pad, GstPadProbeInfo * info, gpointer data)
2287 {
2288         GstPadProbeReturn ret = GST_PAD_PROBE_OK;
2289         GstEvent *event = GST_PAD_PROBE_INFO_DATA(info);
2290         mm_player_t* player = (mm_player_t*)data;
2291         GstCaps* caps = NULL;
2292         GstStructure* str = NULL;
2293         const gchar* name = NULL;
2294         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2295
2296
2297         if (GST_EVENT_IS_DOWNSTREAM(event)) {
2298                 if (GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START &&
2299                         GST_EVENT_TYPE(event) != GST_EVENT_FLUSH_STOP &&
2300                         GST_EVENT_TYPE(event) != GST_EVENT_SEGMENT &&
2301                         GST_EVENT_TYPE(event) != GST_EVENT_EOS)
2302                         return ret;
2303         } else if (GST_EVENT_IS_UPSTREAM(event)) {
2304                 if (GST_EVENT_TYPE(event) != GST_EVENT_QOS)
2305                         return ret;
2306         }
2307
2308         caps = gst_pad_query_caps(pad, NULL);
2309         if (!caps) {
2310                 LOGE("failed to get caps from pad[%s:%s]", GST_DEBUG_PAD_NAME(pad));
2311                 return ret;
2312         }
2313
2314         str = gst_caps_get_structure(caps, 0);
2315         if (!str) {
2316                 LOGE("failed to get structure from caps");
2317                 goto ERROR;
2318         }
2319
2320         name = gst_structure_get_name(str);
2321         if (!name) {
2322                 LOGE("failed to get name from str");
2323                 goto ERROR;
2324         }
2325
2326         if (strstr(name, "audio")) {
2327                 stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2328         } else if (strstr(name, "video")) {
2329                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2330         } else {
2331                 /* text track is not supportable */
2332                 LOGE("invalid name %s", name);
2333                 goto ERROR;
2334         }
2335
2336         switch (GST_EVENT_TYPE(event)) {
2337         case GST_EVENT_EOS:
2338                 {
2339                         /* in case of gapless, drop eos event not to send it to sink */
2340                         if (player->gapless.reconfigure && !player->msg_posted) {
2341                                 LOGD("[%d] %s:%s EOS received but will be drop", stream_type, GST_DEBUG_PAD_NAME(pad));
2342                                 ret = GST_PAD_PROBE_DROP;
2343                         }
2344                         break;
2345                 }
2346         case GST_EVENT_STREAM_START:
2347                 {
2348                         gint64 stop_running_time = 0;
2349                         gint64 position_running_time = 0;
2350                         gint64 position = 0;
2351                         gint idx = 0;
2352
2353                         for (idx = MM_PLAYER_TRACK_TYPE_AUDIO; idx < MM_PLAYER_TRACK_TYPE_TEXT; idx++) {
2354                                 if ((player->gapless.update_segment[idx] == TRUE) ||
2355                                         !(player->selector[idx].event_probe_id)) {
2356                                         /* LOGW("[%d] skip", idx); */
2357                                         continue;
2358                                 }
2359
2360                                 if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].stop)) {
2361                                         stop_running_time =
2362                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2363                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].stop);
2364                                 } else if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].duration)) {
2365                                         stop_running_time =
2366                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2367                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].duration);
2368                                 } else {
2369                                         LOGD("duration: %"GST_TIME_FORMAT, GST_TIME_ARGS(player->duration));
2370                                         stop_running_time =
2371                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2372                                                                 GST_FORMAT_TIME, player->duration);
2373                                 }
2374
2375                                 position_running_time =
2376                                         gst_segment_to_running_time(&player->gapless.segment[idx],
2377                                         GST_FORMAT_TIME, player->gapless.segment[idx].position);
2378
2379                                 LOGD("[type:%d] time info %" GST_TIME_FORMAT " , %"
2380                                         GST_TIME_FORMAT" , %" GST_TIME_FORMAT,
2381                                         idx,
2382                                         GST_TIME_ARGS(stop_running_time),
2383                                         GST_TIME_ARGS(position_running_time),
2384                                         GST_TIME_ARGS(gst_segment_to_running_time(&player->gapless.segment[idx],
2385                                         GST_FORMAT_TIME, player->gapless.segment[idx].start)));
2386
2387                                 position_running_time = MAX(position_running_time, stop_running_time);
2388                                 position_running_time -= gst_segment_to_running_time(&player->gapless.segment[idx],
2389                                                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].start);
2390                                 position_running_time = MAX(0, position_running_time);
2391                                 position = MAX(position, position_running_time);
2392                         }
2393
2394                         if (position != 0) {
2395                                 LOGD("[%d]GST_EVENT_STREAM_START: start_time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
2396                                         stream_type, GST_TIME_ARGS(player->gapless.start_time[stream_type]),
2397                                         GST_TIME_ARGS(player->gapless.start_time[stream_type] + position));
2398
2399                                 player->gapless.start_time[stream_type] += position;
2400                         }
2401                         break;
2402                 }
2403         case GST_EVENT_FLUSH_STOP:
2404                 {
2405                         LOGD("[%d] GST_EVENT_FLUSH_STOP", stream_type);
2406                         gst_segment_init(&player->gapless.segment[stream_type], GST_FORMAT_UNDEFINED);
2407                         player->gapless.start_time[stream_type] = 0;
2408                         break;
2409                 }
2410         case GST_EVENT_SEGMENT:
2411                 {
2412                         GstSegment segment;
2413                         GstEvent *tmpev;
2414
2415                         LOGD("[%d] GST_EVENT_SEGMENT", stream_type);
2416                         gst_event_copy_segment(event, &segment);
2417
2418                         if (segment.format == GST_FORMAT_TIME) {
2419                                 LOGD("segment base:%" GST_TIME_FORMAT ", offset:%" GST_TIME_FORMAT
2420                                          ", start:%" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT
2421                                          ", time: %" GST_TIME_FORMAT ", pos: %" GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT,
2422                                         GST_TIME_ARGS(segment.base), GST_TIME_ARGS(segment.offset),
2423                                         GST_TIME_ARGS(segment.start), GST_TIME_ARGS(segment.stop),
2424                                         GST_TIME_ARGS(segment.time), GST_TIME_ARGS(segment.position), GST_TIME_ARGS(segment.duration));
2425
2426                                 /* keep the all the segment ev to cover the seeking */
2427                                 gst_segment_copy_into(&segment, &player->gapless.segment[stream_type]);
2428                                 player->gapless.update_segment[stream_type] = TRUE;
2429
2430                                 if (!player->gapless.running)
2431                                         break;
2432
2433                                 player->gapless.segment[stream_type].base = player->gapless.start_time[stream_type];
2434
2435                                 LOGD("[%d] new base: %" GST_TIME_FORMAT, stream_type, GST_TIME_ARGS(player->gapless.segment[stream_type].base));
2436
2437                                 tmpev = gst_event_new_segment(&player->gapless.segment[stream_type]);
2438                                 gst_event_set_seqnum(tmpev, gst_event_get_seqnum(event));
2439                                 gst_event_unref(event);
2440                                 GST_PAD_PROBE_INFO_DATA(info) = tmpev;
2441                         }
2442                         break;
2443                 }
2444         case GST_EVENT_QOS:
2445                 {
2446                         gdouble proportion = 0.0;
2447                         GstClockTimeDiff diff = 0;
2448                         GstClockTime timestamp = 0;
2449                         gint64 running_time_diff = -1;
2450                         GstQOSType type = 0;
2451                         GstEvent *tmpev = NULL;
2452
2453                         running_time_diff = player->gapless.segment[stream_type].base;
2454
2455                         if (running_time_diff <= 0) /* don't need to adjust */
2456                                 break;
2457
2458                         gst_event_parse_qos(event, &type, &proportion, &diff, &timestamp);
2459                         gst_event_unref(event);
2460
2461                         if (timestamp < running_time_diff) {
2462                                 LOGW("QOS event from previous group");
2463                                 ret = GST_PAD_PROBE_DROP;
2464                                 break;
2465                         }
2466
2467                         LOGD("[%d] Adjusting QOS event: %" GST_TIME_FORMAT
2468                                  " - %" GST_TIME_FORMAT " = %" GST_TIME_FORMAT,
2469                                                 stream_type, GST_TIME_ARGS(timestamp),
2470                                                 GST_TIME_ARGS(running_time_diff),
2471                                                 GST_TIME_ARGS(timestamp - running_time_diff));
2472
2473                         timestamp -= running_time_diff;
2474
2475                         /* That case is invalid for QoS events */
2476                         if (diff < 0 && -diff > timestamp) {
2477                                 LOGW("QOS event from previous group");
2478                                 ret = GST_PAD_PROBE_DROP;
2479                                 break;
2480                         }
2481
2482                         tmpev = gst_event_new_qos(GST_QOS_TYPE_UNDERFLOW, proportion, diff, timestamp);
2483                         GST_PAD_PROBE_INFO_DATA(info) = tmpev;
2484
2485                         break;
2486                 }
2487         default:
2488                 break;
2489         }
2490
2491 ERROR:
2492         if (caps)
2493                 gst_caps_unref(caps);
2494         return ret;
2495 }
2496
2497 static void
2498 __mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
2499 {
2500         mm_player_t* player = NULL;
2501         GstElement* pipeline = NULL;
2502         GstElement* selector = NULL;
2503         GstElement* fakesink = NULL;
2504         GstCaps* caps = NULL;
2505         GstStructure* str = NULL;
2506         const gchar* name = NULL;
2507         GstPad* sinkpad = NULL;
2508         GstPad* srcpad = NULL;
2509         gboolean first_track = FALSE;
2510
2511         enum MainElementID elemId = MMPLAYER_M_NUM;
2512         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2513
2514         /* check handles */
2515         player = (mm_player_t*)data;
2516
2517         MMPLAYER_RETURN_IF_FAIL(elem && pad);
2518         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2519
2520         //LOGD("pad-added signal handling\n");
2521
2522         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
2523
2524         /* get mimetype from caps */
2525         caps = gst_pad_query_caps(pad, NULL);
2526         if (!caps) {
2527                 LOGE("cannot get caps from pad.\n");
2528                 goto ERROR;
2529         }
2530
2531         str = gst_caps_get_structure(caps, 0);
2532         if (!str) {
2533                 LOGE("cannot get structure from caps.\n");
2534                 goto ERROR;
2535         }
2536
2537         name = gst_structure_get_name(str);
2538         if (!name) {
2539                 LOGE("cannot get mimetype from structure.\n");
2540                 goto ERROR;
2541         }
2542
2543         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
2544         //LOGD("detected mimetype : %s\n", name);
2545
2546         if (strstr(name, "video")) {
2547                 gint stype = 0;
2548
2549                 mm_attrs_set_int_by_name(player->attrs, "content_video_found", TRUE);
2550                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
2551
2552                 /* don't make video because of not required, and not support multiple track */
2553                 if (stype == MM_DISPLAY_SURFACE_NULL) {
2554                         LOGD("no video sink by null surface");
2555
2556                         gchar *caps_str = gst_caps_to_string(caps);
2557                         if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
2558                                 strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
2559                                 player->set_mode.video_zc = TRUE;
2560
2561                         MMPLAYER_FREEIF(caps_str);
2562
2563                         if (player->v_stream_caps) {
2564                                 gst_caps_unref(player->v_stream_caps);
2565                                 player->v_stream_caps = NULL;
2566                         }
2567
2568                         LOGD("create fakesink instead of videobin");
2569
2570                         /* fake sink */
2571                         fakesink = gst_element_factory_make("fakesink", NULL);
2572                         if (fakesink == NULL) {
2573                                 LOGE("ERROR : fakesink create error\n");
2574                                 goto ERROR;
2575                         }
2576
2577                         if (player->ini.set_dump_element_flag)
2578                                 __mmplayer_add_dump_buffer_probe(player, fakesink);
2579
2580                         player->video_fakesink = fakesink;
2581
2582                         /* store it as it's sink element */
2583                         __mmplayer_add_sink(player, player->video_fakesink);
2584
2585                         gst_bin_add(GST_BIN(pipeline), fakesink);
2586
2587                         // link
2588                         sinkpad = gst_element_get_static_pad(fakesink, "sink");
2589
2590                         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2591                                 LOGW("failed to link fakesink\n");
2592                                 gst_object_unref(GST_OBJECT(fakesink));
2593                                 goto ERROR;
2594                         }
2595
2596                         if (stype == MM_DISPLAY_SURFACE_REMOTE) {
2597                                 MMPLAYER_SIGNAL_CONNECT(player, sinkpad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2598                                                 "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
2599                         }
2600
2601                         if (player->set_mode.media_packet_video_stream) {
2602                                 g_object_set(G_OBJECT(fakesink), "signal-handoffs", TRUE, NULL);
2603
2604                                 MMPLAYER_SIGNAL_CONNECT(player,
2605                                                                                 G_OBJECT(fakesink),
2606                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2607                                                                                 "handoff",
2608                                                                                 G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
2609                                                                                 (gpointer)player);
2610
2611                                 MMPLAYER_SIGNAL_CONNECT(player,
2612                                                                                 G_OBJECT(fakesink),
2613                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2614                                                                                 "preroll-handoff",
2615                                                                                 G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
2616                                                                                 (gpointer)player);
2617                         }
2618
2619                         g_object_set(G_OBJECT(fakesink), "async", TRUE, "sync", TRUE, NULL);
2620                         gst_element_set_state(fakesink, GST_STATE_PAUSED);
2621                         goto DONE;
2622                 }
2623
2624                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
2625                         __mmplayer_gst_decode_callback(elem, pad, player);
2626                         goto DONE;
2627                 }
2628
2629                 LOGD("video selector \n");
2630                 elemId = MMPLAYER_M_V_INPUT_SELECTOR;
2631                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2632         } else {
2633                 if (strstr(name, "audio")) {
2634                         gint samplerate = 0;
2635                         gint channels = 0;
2636
2637                         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
2638                                 __mmplayer_gst_decode_callback(elem, pad, player);
2639                                 goto DONE;
2640                         }
2641
2642                         LOGD("audio selector \n");
2643                         elemId = MMPLAYER_M_A_INPUT_SELECTOR;
2644                         stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2645
2646                         gst_structure_get_int(str, "rate", &samplerate);
2647                         gst_structure_get_int(str, "channels", &channels);
2648
2649                         if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
2650                                 /* fake sink */
2651                                 fakesink = gst_element_factory_make("fakesink", NULL);
2652                                 if (fakesink == NULL) {
2653                                         LOGE("ERROR : fakesink create error\n");
2654                                         goto ERROR;
2655                                 }
2656
2657                                 gst_bin_add(GST_BIN(pipeline), fakesink);
2658
2659                                 /* link */
2660                                 sinkpad = gst_element_get_static_pad(fakesink, "sink");
2661
2662                                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2663                                         LOGW("failed to link fakesink\n");
2664                                         gst_object_unref(GST_OBJECT(fakesink));
2665                                         goto ERROR;
2666                                 }
2667
2668                                 g_object_set(G_OBJECT(fakesink), "async", TRUE, NULL);
2669                                 g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL);
2670                                 gst_element_set_state(fakesink, GST_STATE_PAUSED);
2671
2672                                 goto DONE;
2673                         }
2674                 } else if (strstr(name, "text")) {
2675                         LOGD("text selector \n");
2676                         elemId = MMPLAYER_M_T_INPUT_SELECTOR;
2677                         stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
2678                 } else {
2679                         LOGE("wrong elem id \n");
2680                         goto ERROR;
2681                 }
2682         }
2683
2684         selector = player->pipeline->mainbin[elemId].gst;
2685         if (selector == NULL) {
2686                 selector = gst_element_factory_make("input-selector", NULL);
2687                 LOGD("Creating input-selector\n");
2688                 if (selector == NULL) {
2689                         LOGE("ERROR : input-selector create error\n");
2690                         goto ERROR;
2691                 }
2692                 g_object_set(selector, "sync-streams", TRUE, NULL);
2693
2694                 player->pipeline->mainbin[elemId].id = elemId;
2695                 player->pipeline->mainbin[elemId].gst = selector;
2696
2697                 first_track = TRUE;
2698                 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK;      // default
2699
2700                 srcpad = gst_element_get_static_pad(selector, "src");
2701
2702                 LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
2703                 player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
2704                         __mmplayer_gst_selector_blocked, NULL, NULL);
2705                 player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
2706                         __mmplayer_gst_selector_event_probe, player, NULL);
2707
2708                 gst_element_set_state(selector, GST_STATE_PAUSED);
2709                 gst_bin_add(GST_BIN(pipeline), selector);
2710         } else
2711                 LOGD("input-selector is already created.\n");
2712
2713         // link
2714         LOGD("Calling request pad with selector %p \n", selector);
2715         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
2716
2717         LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(sinkpad));
2718
2719         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2720                 LOGW("failed to link selector\n");
2721                 gst_object_unref(GST_OBJECT(selector));
2722                 goto ERROR;
2723         }
2724
2725         if (first_track) {
2726                 LOGD("this is first track --> active track \n");
2727                 g_object_set(selector, "active-pad", sinkpad, NULL);
2728         }
2729
2730         _mmplayer_track_update_info(player, stream_type, sinkpad);
2731
2732
2733 DONE:
2734 ERROR:
2735
2736         if (caps)
2737                 gst_caps_unref(caps);
2738
2739         if (sinkpad) {
2740                 gst_object_unref(GST_OBJECT(sinkpad));
2741                 sinkpad = NULL;
2742         }
2743
2744         if (srcpad) {
2745                 gst_object_unref(GST_OBJECT(srcpad));
2746                 srcpad = NULL;
2747         }
2748
2749         return;
2750 }
2751
2752 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
2753 {
2754         GstPad* srcpad = NULL;
2755         MMHandleType attrs = 0;
2756         gint active_index = 0;
2757
2758         // [link] input-selector :: textbin
2759         srcpad = gst_element_get_static_pad(text_selector, "src");
2760         if (!srcpad) {
2761                 LOGE("failed to get srcpad from selector\n");
2762                 return;
2763         }
2764
2765         LOGD("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
2766
2767         active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
2768         if ((active_index != DEFAULT_TRACK) &&
2769                 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE)) {
2770                 LOGW("failed to change text track\n");
2771                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
2772         }
2773
2774         player->no_more_pad = TRUE;
2775         __mmplayer_gst_decode_callback(text_selector, srcpad, player);
2776
2777         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
2778         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id) {
2779                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id);
2780                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id = 0;
2781         }
2782
2783         LOGD("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
2784
2785         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
2786                 player->has_closed_caption = TRUE;
2787
2788         attrs = MMPLAYER_GET_ATTRS(player);
2789         if (attrs) {
2790                 mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
2791                 if (mmf_attrs_commit(attrs))
2792                         LOGE("failed to commit.\n");
2793         } else
2794                 LOGE("cannot get content attribute");
2795
2796         if (srcpad) {
2797                 gst_object_unref(GST_OBJECT(srcpad));
2798                 srcpad = NULL;
2799         }
2800 }
2801
2802 static void
2803 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
2804 {
2805         mm_player_t* player = (mm_player_t*)data;
2806         GstElement* selector = NULL;
2807         GstElement* queue = NULL;
2808
2809         GstPad* srcpad = NULL;
2810         GstPad* sinkpad = NULL;
2811         GstCaps* caps = NULL;
2812         gchar* caps_str = NULL;
2813
2814         MMPLAYER_FENTER();
2815         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2816
2817         caps = gst_pad_get_current_caps(pad);
2818         caps_str = gst_caps_to_string(caps);
2819         LOGD("deinterleave new caps : %s\n", caps_str);
2820         MMPLAYER_FREEIF(caps_str);
2821         gst_caps_unref(caps);
2822
2823         if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL) {
2824                 LOGE("ERROR : queue create error\n");
2825                 goto ERROR;
2826         }
2827
2828         g_object_set(G_OBJECT(queue),
2829                                 "max-size-buffers", 10,
2830                                 "max-size-bytes", 0,
2831                                 "max-size-time", (guint64)0,
2832                                 NULL);
2833
2834         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
2835
2836         if (!selector) {
2837                 LOGE("there is no audio channel selector.\n");
2838                 goto ERROR;
2839         }
2840
2841         srcpad = gst_element_get_static_pad(queue, "src");
2842         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
2843
2844         LOGD("link(%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
2845
2846         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
2847                 LOGW("failed to link deinterleave - selector\n");
2848                 goto ERROR;
2849         }
2850
2851         gst_element_set_state(queue, GST_STATE_PAUSED);
2852         player->audio_mode.total_track_num++;
2853
2854 ERROR:
2855
2856         if (srcpad) {
2857                 gst_object_unref(GST_OBJECT(srcpad));
2858                 srcpad = NULL;
2859         }
2860
2861         if (sinkpad) {
2862                 gst_object_unref(GST_OBJECT(sinkpad));
2863                 sinkpad = NULL;
2864         }
2865
2866         MMPLAYER_FLEAVE();
2867         return;
2868 }
2869
2870 static void
2871 __mmplayer_gst_deinterleave_no_more_pads(GstElement *elem, gpointer data)
2872 {
2873         mm_player_t* player = NULL;
2874         GstElement* selector = NULL;
2875         GstPad* sinkpad = NULL;
2876         gint active_index = 0;
2877         gchar* change_pad_name = NULL;
2878         GstCaps* caps = NULL;   // no need to unref
2879         gint default_audio_ch = 0;
2880
2881         MMPLAYER_FENTER();
2882         player = (mm_player_t*) data;
2883
2884         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
2885
2886         if (!selector) {
2887                 LOGE("there is no audio channel selector.\n");
2888                 goto ERROR;
2889         }
2890
2891         active_index = player->audio_mode.active_pad_index;
2892
2893         if (active_index != default_audio_ch) {
2894                 gint audio_ch = default_audio_ch;
2895
2896                 /*To get the new pad from the selector*/
2897                 change_pad_name = g_strdup_printf("sink%d", active_index);
2898                 if (change_pad_name != NULL) {
2899                         sinkpad = gst_element_get_static_pad(selector, change_pad_name);
2900                         if (sinkpad != NULL) {
2901                                 LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
2902                                 g_object_set(selector, "active-pad", sinkpad, NULL);
2903
2904                                 audio_ch = active_index;
2905
2906                                 caps = gst_pad_get_current_caps(sinkpad);
2907                                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
2908
2909                                 __mmplayer_set_audio_attrs(player, caps);
2910                                 gst_caps_unref(caps);
2911                         }
2912                         MMPLAYER_FREEIF(change_pad_name);
2913                 }
2914
2915                 player->audio_mode.active_pad_index = audio_ch;
2916                 LOGD("audio LR info(0:stereo) = %d\n", player->audio_mode.active_pad_index);
2917         }
2918
2919 ERROR:
2920
2921         if (sinkpad)
2922                 gst_object_unref(sinkpad);
2923
2924         MMPLAYER_FLEAVE();
2925         return;
2926 }
2927
2928 static void
2929 __mmplayer_gst_build_deinterleave_path(GstElement *elem, GstPad *pad, gpointer data)
2930 {
2931         mm_player_t* player = NULL;
2932         MMPlayerGstElement *mainbin = NULL;
2933
2934         GstElement* tee = NULL;
2935         GstElement* stereo_queue = NULL;
2936         GstElement* mono_queue = NULL;
2937         GstElement* conv = NULL;
2938         GstElement* filter = NULL;
2939         GstElement* deinterleave = NULL;
2940         GstElement* selector = NULL;
2941
2942         GstPad* srcpad = NULL;
2943         GstPad* selector_srcpad = NULL;
2944         GstPad* sinkpad = NULL;
2945         GstCaps* caps = NULL;
2946         gulong block_id = 0;
2947
2948         MMPLAYER_FENTER();
2949
2950         /* check handles */
2951         player = (mm_player_t*) data;
2952
2953         MMPLAYER_RETURN_IF_FAIL(elem && pad);
2954         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2955
2956         mainbin = player->pipeline->mainbin;
2957
2958         /* tee */
2959         if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL) {
2960                 LOGE("ERROR : tee create error\n");
2961                 goto ERROR;
2962         }
2963
2964         mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
2965         mainbin[MMPLAYER_M_A_TEE].gst = tee;
2966
2967         gst_element_set_state(tee, GST_STATE_PAUSED);
2968
2969         /* queue */
2970         srcpad = gst_element_get_request_pad(tee, "src_%u");
2971         if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL) {
2972                 LOGE("ERROR : stereo queue create error\n");
2973                 goto ERROR;
2974         }
2975
2976         g_object_set(G_OBJECT(stereo_queue),
2977                                 "max-size-buffers", 10,
2978                                 "max-size-bytes", 0,
2979                                 "max-size-time", (guint64)0,
2980                                 NULL);
2981
2982         player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
2983         player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
2984
2985         if (srcpad) {
2986                 gst_object_unref(GST_OBJECT(srcpad));
2987                 srcpad = NULL;
2988         }
2989
2990         srcpad = gst_element_get_request_pad(tee, "src_%u");
2991
2992         if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL) {
2993                 LOGE("ERROR : mono queue create error\n");
2994                 goto ERROR;
2995         }
2996
2997         g_object_set(G_OBJECT(mono_queue),
2998                                 "max-size-buffers", 10,
2999                                 "max-size-bytes", 0,
3000                                 "max-size-time", (guint64)0,
3001                                 NULL);
3002
3003         player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3004         player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3005
3006         gst_element_set_state(stereo_queue, GST_STATE_PAUSED);
3007         gst_element_set_state(mono_queue, GST_STATE_PAUSED);
3008
3009         /* audioconvert */
3010         srcpad = gst_element_get_static_pad(mono_queue, "src");
3011         if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL) {
3012                 LOGE("ERROR : audioconvert create error\n");
3013                 goto ERROR;
3014         }
3015
3016         player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3017         player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3018
3019         /* caps filter */
3020         if (srcpad) {
3021                 gst_object_unref(GST_OBJECT(srcpad));
3022                 srcpad = NULL;
3023         }
3024         srcpad = gst_element_get_static_pad(conv, "src");
3025
3026         if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL) {
3027                 LOGE("ERROR : capsfilter create error\n");
3028                 goto ERROR;
3029         }
3030
3031         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3032         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3033
3034         caps = gst_caps_from_string("audio/x-raw-int, "
3035                                 "width = (int) 16, "
3036                                 "depth = (int) 16, "
3037                                 "channels = (int) 2");
3038
3039         g_object_set(GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL);
3040         gst_caps_unref(caps);
3041
3042         gst_element_set_state(conv, GST_STATE_PAUSED);
3043         gst_element_set_state(filter, GST_STATE_PAUSED);
3044
3045         /* deinterleave */
3046         if (srcpad) {
3047                 gst_object_unref(GST_OBJECT(srcpad));
3048                 srcpad = NULL;
3049         }
3050         srcpad = gst_element_get_static_pad(filter, "src");
3051
3052         if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL) {
3053                 LOGE("ERROR : deinterleave create error\n");
3054                 goto ERROR;
3055         }
3056
3057         g_object_set(deinterleave, "keep-positions", TRUE, NULL);
3058
3059         MMPLAYER_SIGNAL_CONNECT(player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3060                                                         G_CALLBACK(__mmplayer_gst_deinterleave_pad_added), player);
3061
3062         MMPLAYER_SIGNAL_CONNECT(player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3063                                                         G_CALLBACK(__mmplayer_gst_deinterleave_no_more_pads), player);
3064
3065         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3066         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3067
3068         /* selector */
3069         selector = gst_element_factory_make("input-selector", "audio-channel-selector");
3070         if (selector == NULL) {
3071                 LOGE("ERROR : audio-selector create error\n");
3072                 goto ERROR;
3073         }
3074
3075         g_object_set(selector, "sync-streams", TRUE, NULL);
3076         gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3077
3078         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3079         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3080
3081         selector_srcpad = gst_element_get_static_pad(selector, "src");
3082
3083         LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3084         block_id =
3085                 gst_pad_add_probe(selector_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3086                         __mmplayer_gst_selector_blocked, NULL, NULL);
3087
3088         if (srcpad) {
3089                 gst_object_unref(GST_OBJECT(srcpad));
3090                 srcpad = NULL;
3091         }
3092
3093         srcpad = gst_element_get_static_pad(stereo_queue, "src");
3094         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
3095
3096         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
3097                 LOGW("failed to link queue_stereo - selector\n");
3098                 goto ERROR;
3099         }
3100
3101         player->audio_mode.total_track_num++;
3102
3103         g_object_set(selector, "active-pad", sinkpad, NULL);
3104         gst_element_set_state(deinterleave, GST_STATE_PAUSED);
3105         gst_element_set_state(selector, GST_STATE_PAUSED);
3106
3107         __mmplayer_gst_decode_callback(selector, selector_srcpad, player);
3108
3109 ERROR:
3110
3111         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3112         if (block_id != 0) {
3113                 gst_pad_remove_probe(selector_srcpad, block_id);
3114                 block_id = 0;
3115         }
3116
3117         if (sinkpad) {
3118                 gst_object_unref(GST_OBJECT(sinkpad));
3119                 sinkpad = NULL;
3120         }
3121
3122         if (srcpad) {
3123                 gst_object_unref(GST_OBJECT(srcpad));
3124                 srcpad = NULL;
3125         }
3126
3127         if (selector_srcpad) {
3128                 gst_object_unref(GST_OBJECT(selector_srcpad));
3129                 selector_srcpad = NULL;
3130         }
3131
3132         MMPLAYER_FLEAVE();
3133         return;
3134 }
3135
3136 static void
3137 __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
3138 {
3139         mm_player_t* player = NULL;
3140         GstPad* srcpad = NULL;
3141         GstElement* video_selector = NULL;
3142         GstElement* audio_selector = NULL;
3143         GstElement* text_selector = NULL;
3144         MMHandleType attrs = 0;
3145         gint active_index = 0;
3146         gint64 dur_bytes = 0L;
3147
3148         player = (mm_player_t*) data;
3149
3150         LOGD("no-more-pad signal handling\n");
3151
3152         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3153                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE)) {
3154                 LOGW("no need to go more");
3155
3156                 if (player->gapless.reconfigure) {
3157                         player->gapless.reconfigure = FALSE;
3158                         MMPLAYER_PLAYBACK_UNLOCK(player);
3159                 }
3160
3161                 return;
3162         }
3163
3164         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3165                 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3166                 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3167                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
3168                 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
3169
3170                 if (NULL == player->streamer) {
3171                         LOGW("invalid state for buffering");
3172                         goto ERROR;
3173                 }
3174
3175                 gint init_buffering_time = player->streamer->buffering_req.prebuffer_time;
3176                 guint buffer_bytes = (guint)(init_buffering_time/1000) * ESTIMATED_BUFFER_UNIT;
3177
3178                 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
3179                 LOGD("[Decodebin2] set use-buffering on Q2(pre buffer time: %d ms, buffer size : %d)\n", init_buffering_time, buffer_bytes);
3180
3181                 init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
3182
3183                 if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
3184                         LOGE("fail to get duration.\n");
3185
3186                 // enable use-buffering on queue2 instead of multiqueue(ex)audio only streaming
3187                 // use file information was already set on Q2 when it was created.
3188                 __mm_player_streaming_set_queue2(player->streamer,
3189                                                 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
3190                                                 TRUE,                                                           // use_buffering
3191                                                 buffer_bytes,
3192                                                 init_buffering_time,
3193                                                 1.0,                                                            // low percent
3194                                                 player->ini.http_buffering_limit,       // high percent
3195                                                 MUXED_BUFFER_TYPE_MEM_QUEUE,
3196                                                 NULL,
3197                                                 ((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
3198         }
3199
3200         video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
3201         audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
3202         text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3203         if (video_selector) {
3204                 // [link] input-selector :: videobin
3205                 srcpad = gst_element_get_static_pad(video_selector, "src");
3206                 if (!srcpad) {
3207                         LOGE("failed to get srcpad from video selector\n");
3208                         goto ERROR;
3209                 }
3210
3211                 LOGD("got pad %s:%s from video selector\n", GST_DEBUG_PAD_NAME(srcpad));
3212                 if (!text_selector && !audio_selector)
3213                         player->no_more_pad = TRUE;
3214
3215                 __mmplayer_gst_decode_callback(video_selector, srcpad, player);
3216
3217                 LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3218                 if (player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id) {
3219                         gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id);
3220                         player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id = 0;
3221                 }
3222         }
3223
3224         if (audio_selector) {
3225                 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
3226                 if ((active_index != DEFAULT_TRACK) &&
3227                         (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE)) {
3228                         LOGW("failed to change audio track\n");
3229                         player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
3230                 }
3231
3232                 // [link] input-selector :: audiobin
3233                 srcpad = gst_element_get_static_pad(audio_selector, "src");
3234                 if (!srcpad) {
3235                         LOGE("failed to get srcpad from selector\n");
3236                         goto ERROR;
3237                 }
3238
3239                 LOGD("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3240                 if (!text_selector)
3241                         player->no_more_pad = TRUE;
3242
3243                 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2)) {
3244                         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3245                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id) {
3246                                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3247                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3248                         }
3249
3250                         __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
3251                 } else {
3252                         __mmplayer_gst_decode_callback(audio_selector, srcpad, player);
3253
3254                         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3255                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id) {
3256                                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3257                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3258                         }
3259                 }
3260
3261                 LOGD("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3262
3263                 attrs = MMPLAYER_GET_ATTRS(player);
3264                 if (attrs) {
3265                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", (gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3266                         if (mmf_attrs_commit(attrs))
3267                                 LOGE("failed to commit.\n");
3268                 } else
3269                         LOGE("cannot get content attribute");
3270         } else {
3271                 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst)) {
3272                         LOGD("There is no audio track : remove audiobin");
3273
3274                         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
3275                         __mmplayer_del_sink(player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
3276
3277                         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->audiobin, MMPLAYER_A_BIN);
3278                         MMPLAYER_FREEIF(player->pipeline->audiobin);
3279                 }
3280
3281                 if (player->num_dynamic_pad == 0)
3282                         __mmplayer_pipeline_complete(NULL, player);
3283         }
3284
3285         if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
3286                 if (text_selector)
3287                         __mmplayer_handle_text_decode_path(player, text_selector);
3288         }
3289
3290         MMPLAYER_FLEAVE();
3291
3292 ERROR:
3293         if (srcpad) {
3294                 gst_object_unref(GST_OBJECT(srcpad));
3295                 srcpad = NULL;
3296         }
3297
3298         if (player->gapless.reconfigure) {
3299                 player->gapless.reconfigure = FALSE;
3300                 MMPLAYER_PLAYBACK_UNLOCK(player);
3301         }
3302 }
3303
3304 static void
3305 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data)
3306 {
3307         mm_player_t* player = NULL;
3308         MMHandleType attrs = 0;
3309         GstElement* pipeline = NULL;
3310         GstCaps* caps = NULL;
3311         gchar* caps_str = NULL;
3312         GstStructure* str = NULL;
3313         const gchar* name = NULL;
3314         GstPad* sinkpad = NULL;
3315         GstElement* sinkbin = NULL;
3316         gboolean reusing = FALSE;
3317         GstElement *text_selector = NULL;
3318
3319         /* check handles */
3320         player = (mm_player_t*) data;
3321
3322         MMPLAYER_RETURN_IF_FAIL(elem && pad);
3323         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
3324
3325         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3326
3327         attrs = MMPLAYER_GET_ATTRS(player);
3328         if (!attrs) {
3329                 LOGE("cannot get content attribute\n");
3330                 goto ERROR;
3331         }
3332
3333         /* get mimetype from caps */
3334         caps = gst_pad_query_caps(pad, NULL);
3335         if (!caps) {
3336                 LOGE("cannot get caps from pad.\n");
3337                 goto ERROR;
3338         }
3339         caps_str = gst_caps_to_string(caps);
3340
3341         str = gst_caps_get_structure(caps, 0);
3342         if (!str) {
3343                 LOGE("cannot get structure from caps.\n");
3344                 goto ERROR;
3345         }
3346
3347         name = gst_structure_get_name(str);
3348         if (!name) {
3349                 LOGE("cannot get mimetype from structure.\n");
3350                 goto ERROR;
3351         }
3352
3353         //LOGD("detected mimetype : %s\n", name);
3354
3355         if (strstr(name, "audio")) {
3356                 if (player->pipeline->audiobin == NULL) {
3357                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player)) {
3358                                 LOGE("failed to create audiobin. continuing without audio\n");
3359                                 goto ERROR;
3360                         }
3361
3362                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3363                         LOGD("creating audiosink bin success\n");
3364                 } else {
3365                         reusing = TRUE;
3366                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3367                         LOGD("reusing audiobin\n");
3368                         _mmplayer_update_content_attrs(player, ATTR_AUDIO);
3369                 }
3370
3371                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
3372                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
3373
3374                 player->audiosink_linked  = 1;
3375
3376                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
3377                 if (!sinkpad) {
3378                         LOGE("failed to get pad from sinkbin\n");
3379                         goto ERROR;
3380                 }
3381         } else if (strstr(name, "video")) {
3382                 if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
3383                         strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
3384                         player->set_mode.video_zc = TRUE;
3385
3386                 if (player->pipeline->videobin == NULL) {
3387                         /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
3388                         /* get video surface type */
3389                         int surface_type = 0;
3390                         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
3391                         LOGD("display_surface_type(%d)\n", surface_type);
3392
3393                         if (surface_type == MM_DISPLAY_SURFACE_NULL) {
3394                                 LOGD("not make videobin because it dose not want\n");
3395                                 goto ERROR;
3396                         }
3397
3398                         if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
3399                                 /* mark video overlay for acquire */
3400                                 if (player->video_overlay_resource == NULL) {
3401                                         if (mm_resource_manager_mark_for_acquire(player->resource_manager,
3402                                                         MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
3403                                                         MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
3404                                                         &player->video_overlay_resource)
3405                                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
3406                                                 LOGE("could not mark video_overlay resource for acquire\n");
3407                                                 goto ERROR;
3408                                         }
3409                                 }
3410                         }
3411
3412                         player->interrupted_by_resource = FALSE;
3413                         /* acquire resources for video overlay */
3414                         if (mm_resource_manager_commit(player->resource_manager) !=
3415                                         MM_RESOURCE_MANAGER_ERROR_NONE) {
3416                                 LOGE("could not acquire resources for video playing\n");
3417                                 goto ERROR;
3418                         }
3419
3420                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type)) {
3421                                 LOGE("failed to create videobin. continuing without video\n");
3422                                 goto ERROR;
3423                         }
3424
3425                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3426                         LOGD("creating videosink bin success\n");
3427                 } else {
3428                         reusing = TRUE;
3429                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3430                         LOGD("re-using videobin\n");
3431                         _mmplayer_update_content_attrs(player, ATTR_VIDEO);
3432                 }
3433
3434                 player->videosink_linked  = 1;
3435
3436                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
3437                 if (!sinkpad) {
3438                         LOGE("failed to get pad from sinkbin\n");
3439                         goto ERROR;
3440                 }
3441         } else if (strstr(name, "text")) {
3442                 if (player->pipeline->textbin == NULL) {
3443                         MMPlayerGstElement* mainbin = NULL;
3444
3445                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_sink_bin(player)) {
3446                                 LOGE("failed to create text sink bin. continuing without text\n");
3447                                 goto ERROR;
3448                         }
3449
3450                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3451                         LOGD("creating textsink bin success\n");
3452
3453                         /* FIXIT : track number shouldn't be hardcoded */
3454                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
3455
3456                         player->textsink_linked  = 1;
3457                         LOGI("player->textsink_linked set to 1\n");
3458
3459                         sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "text_sink");
3460                         if (!sinkpad) {
3461                                 LOGE("failed to get pad from sinkbin\n");
3462                                 goto ERROR;
3463                         }
3464
3465                         mainbin = player->pipeline->mainbin;
3466
3467                         if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst) {
3468                                 /* input selector */
3469                                 text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
3470                                 if (!text_selector) {
3471                                         LOGE("failed to create subtitle input selector element\n");
3472                                         goto ERROR;
3473                                 }
3474                                 g_object_set(text_selector, "sync-streams", TRUE, NULL);
3475
3476                                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
3477                                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
3478
3479                                 /* warm up */
3480                                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_READY)) {
3481                                         LOGE("failed to set state(READY) to sinkbin\n");
3482                                         goto ERROR;
3483                                 }
3484
3485                                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector)) {
3486                                         LOGW("failed to add subtitle input selector\n");
3487                                         goto ERROR;
3488                                 }
3489
3490                                 LOGD("created element input-selector");
3491
3492                         } else {
3493                                 LOGD("already having subtitle input selector");
3494                                 text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3495                         }
3496                 } else {
3497                         if (!player->textsink_linked) {
3498                                 LOGD("re-using textbin\n");
3499
3500                                 reusing = TRUE;
3501                                 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3502
3503                                 player->textsink_linked  = 1;
3504                                 LOGI("player->textsink_linked set to 1\n");
3505                         } else
3506                                 LOGD("ignoring internal subtutle since external subtitle is available");
3507                 }
3508         } else {
3509                 LOGW("unknown type of elementary stream!ignoring it...\n");
3510                 goto ERROR;
3511         }
3512
3513         if (sinkbin) {
3514                 if (!reusing) {
3515                         /* warm up */
3516                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_READY)) {
3517                                 LOGE("failed to set state(READY) to sinkbin\n");
3518                                 goto ERROR;
3519                         }
3520
3521                         /* Added for multi audio support to avoid adding audio bin again*/
3522                         /* add */
3523                         if (FALSE == gst_bin_add(GST_BIN(pipeline), sinkbin)) {
3524                                 LOGE("failed to add sinkbin to pipeline\n");
3525                                 goto ERROR;
3526                         }
3527                 }
3528
3529                 /* link */
3530                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
3531                         LOGE("failed to get pad from sinkbin\n");
3532                         goto ERROR;
3533                 }
3534
3535                 if (!reusing) {
3536                         /* run */
3537                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_PAUSED)) {
3538                                 LOGE("failed to set state(PAUSED) to sinkbin\n");
3539                                 goto ERROR;
3540                         }
3541
3542                         if (text_selector) {
3543                                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_PAUSED)) {
3544                                         LOGE("failed to set state(PAUSED) to sinkbin\n");
3545                                         goto ERROR;
3546                                 }
3547                         }
3548                 }
3549
3550                 gst_object_unref(sinkpad);
3551                 sinkpad = NULL;
3552         }
3553
3554         LOGD("[handle: %p] linking sink bin success", player);
3555
3556         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
3557          * streaming task. if the task blocked, then buffer will not flow to the next element
3558          *(autoplugging element). so this is special hack for streaming. please try to remove it
3559          */
3560         /* dec stream count. we can remove fakesink if it's zero */
3561         if (player->num_dynamic_pad)
3562                 player->num_dynamic_pad--;
3563
3564         LOGD("no more pads: %d stream count dec : %d(num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
3565
3566         if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
3567                 __mmplayer_pipeline_complete(NULL, player);
3568
3569 ERROR:
3570
3571         MMPLAYER_FREEIF(caps_str);
3572
3573         if (caps)
3574                 gst_caps_unref(caps);
3575
3576         if (sinkpad)
3577                 gst_object_unref(GST_OBJECT(sinkpad));
3578
3579         /* flusing out new attributes */
3580         if (mmf_attrs_commit(attrs))
3581                 LOGE("failed to comit attributes\n");
3582
3583         return;
3584 }
3585
3586 static gboolean
3587 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
3588 {
3589         int pro_value = 0; // in the case of expection, default will be returned.
3590         int dest_angle = rotation_angle;
3591         int rotation_type = -1;
3592
3593         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
3594         MMPLAYER_RETURN_VAL_IF_FAIL(value, FALSE);
3595         MMPLAYER_RETURN_VAL_IF_FAIL(rotation_angle >= 0, FALSE);
3596
3597         if (rotation_angle >= 360)
3598                 dest_angle = rotation_angle - 360;
3599
3600         /* chech if supported or not */
3601         if (dest_angle % 90) {
3602                 LOGD("not supported rotation angle = %d", rotation_angle);
3603                 return FALSE;
3604         }
3605
3606         /*
3607           * tizenwlsink (A)
3608           * custom_convert - none (B)
3609           * videoflip - none (C)
3610           */
3611         if (player->set_mode.video_zc) {
3612                 if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
3613                         rotation_type = ROTATION_USING_CUSTOM;
3614                 else // A
3615                         rotation_type = ROTATION_USING_SINK;
3616         } else {
3617                 int surface_type = 0;
3618                 rotation_type = ROTATION_USING_FLIP;
3619
3620                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
3621                 LOGD("check display surface type attribute: %d", surface_type);
3622
3623                 if (surface_type == MM_DISPLAY_SURFACE_OVERLAY)
3624                         rotation_type = ROTATION_USING_SINK;
3625                 else
3626                         rotation_type = ROTATION_USING_FLIP; //C
3627
3628                 LOGD("using %d type for rotation", rotation_type);
3629         }
3630
3631         /* get property value for setting */
3632         switch (rotation_type) {
3633         case ROTATION_USING_SINK: // tizenwlsink
3634                 {
3635                         switch (dest_angle) {
3636                         case 0:
3637                                 break;
3638                         case 90:
3639                                 pro_value = 3; // clockwise 90
3640                                 break;
3641                         case 180:
3642                                 pro_value = 2;
3643                                 break;
3644                         case 270:
3645                                 pro_value = 1; // counter-clockwise 90
3646                                 break;
3647                         }
3648                 }
3649                 break;
3650         case ROTATION_USING_CUSTOM:
3651                 {
3652                         gchar *ename = NULL;
3653                         ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
3654
3655                         if (g_strrstr(ename, "fimcconvert")) {
3656                                 switch (dest_angle) {
3657                                 case 0:
3658                                         break;
3659                                 case 90:
3660                                         pro_value = 90; // clockwise 90
3661                                         break;
3662                                 case 180:
3663                                         pro_value = 180;
3664                                         break;
3665                                 case 270:
3666                                         pro_value = 270; // counter-clockwise 90
3667                                         break;
3668                                 }
3669                         }
3670                 }
3671                 break;
3672         case ROTATION_USING_FLIP: // videoflip
3673                 {
3674                                 switch (dest_angle) {
3675                                 case 0:
3676                                         break;
3677                                 case 90:
3678                                         pro_value = 1; // clockwise 90
3679                                         break;
3680                                 case 180:
3681                                         pro_value = 2;
3682                                         break;
3683                                 case 270:
3684                                         pro_value = 3; // counter-clockwise 90
3685                                         break;
3686                                 }
3687                 }
3688                 break;
3689         }
3690
3691         LOGD("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
3692
3693         *value = pro_value;
3694
3695         return TRUE;
3696 }
3697
3698 int
3699 __mmplayer_video_param_check_video_sink_bin(mm_player_t* player)
3700 {
3701         /* check video sinkbin is created */
3702         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
3703                 player->pipeline &&
3704                 player->pipeline->videobin &&
3705                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
3706                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
3707                 MM_ERROR_PLAYER_NOT_INITIALIZED);
3708
3709         return MM_ERROR_NONE;
3710 }
3711
3712 void
3713 __mmplayer_video_param_set_display_rotation(mm_player_t* player)
3714 {
3715         int rotation_value = 0;
3716         int org_angle = 0; // current supported angle values are 0, 90, 180, 270
3717         int user_angle = 0;
3718         MMPLAYER_FENTER();
3719
3720         /* check video sinkbin is created */
3721         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3722                 return;
3723
3724         __mmplayer_get_video_angle(player, &user_angle, &org_angle);
3725
3726         /* get rotation value to set */
3727         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
3728         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "rotate", rotation_value, NULL);
3729         LOGD("set video param : rotate %d", rotation_value);
3730 }
3731
3732 void
3733 __mmplayer_video_param_set_display_visible(mm_player_t* player)
3734 {
3735         MMHandleType attrs = 0;
3736         int visible = 0;
3737         MMPLAYER_FENTER();
3738
3739         /* check video sinkbin is created */
3740         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3741                 return;
3742
3743         attrs = MMPLAYER_GET_ATTRS(player);
3744         MMPLAYER_RETURN_IF_FAIL(attrs);
3745
3746         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
3747         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "visible", visible, NULL);
3748         LOGD("set video param : visible %d", visible);
3749 }
3750
3751 void
3752 __mmplayer_video_param_set_display_method(mm_player_t* player)
3753 {
3754         MMHandleType attrs = 0;
3755         int display_method = 0;
3756         MMPLAYER_FENTER();
3757
3758         /* check video sinkbin is created */
3759         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3760                 return;
3761
3762         attrs = MMPLAYER_GET_ATTRS(player);
3763         MMPLAYER_RETURN_IF_FAIL(attrs);
3764
3765         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
3766         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "display-geometry-method", display_method, NULL);
3767         LOGD("set video param : method %d", display_method);
3768 }
3769
3770 void
3771 __mmplayer_video_param_set_render_rectangle(mm_player_t* player)
3772 {
3773         MMHandleType attrs = 0;
3774         void *handle = NULL;
3775         /*set wl_display*/
3776         int wl_window_x = 0;
3777         int wl_window_y = 0;
3778         int wl_window_width = 0;
3779         int wl_window_height = 0;
3780         MMPLAYER_FENTER();
3781
3782         /* check video sinkbin is created */
3783         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3784                 return;
3785
3786         attrs = MMPLAYER_GET_ATTRS(player);
3787         MMPLAYER_RETURN_IF_FAIL(attrs);
3788
3789         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
3790
3791         if (handle) {
3792                 /*It should be set after setting window*/
3793                 mm_attrs_get_int_by_name(attrs, "wl_window_render_x", &wl_window_x);
3794                 mm_attrs_get_int_by_name(attrs, "wl_window_render_y", &wl_window_y);
3795                 mm_attrs_get_int_by_name(attrs, "wl_window_render_width", &wl_window_width);
3796                 mm_attrs_get_int_by_name(attrs, "wl_window_render_height", &wl_window_height);
3797
3798                 /* After setting window handle, set render      rectangle */
3799                 gst_video_overlay_set_render_rectangle(
3800                          GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
3801                          wl_window_x, wl_window_y, wl_window_width, wl_window_height);
3802                 LOGD("set video param : render rectangle : x(%d) y(%d) width(%d) height(%d)",
3803                         wl_window_x, wl_window_y, wl_window_width, wl_window_height);
3804
3805         }
3806 }
3807 void
3808 __mmplayer_video_param_set_display_overlay(mm_player_t* player)
3809 {
3810         MMHandleType attrs = 0;
3811         void *handle = NULL;
3812
3813         /* check video sinkbin is created */
3814         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3815                 return;
3816
3817         attrs = MMPLAYER_GET_ATTRS(player);
3818         MMPLAYER_RETURN_IF_FAIL(attrs);
3819
3820         /* common case if using overlay surface */
3821         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
3822
3823         if (handle) {
3824                 /* default is using wl_surface_id */
3825                 unsigned int wl_surface_id      = 0;
3826                 wl_surface_id = *(int*)handle;
3827                 LOGD("set video param : wl_surface_id %d %p", wl_surface_id, *(int*)handle);
3828                 gst_video_overlay_set_wl_window_wl_surface_id(
3829                                 GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
3830                                 *(int*)handle);
3831         } else
3832                 /* FIXIT : is it error case? */
3833                 LOGW("still we don't have a window handle on player attribute. create it's own surface.");
3834 }
3835
3836
3837 int
3838 __mmplayer_update_wayland_videosink_video_param(mm_player_t* player, char *param_name)
3839 {
3840         bool update_all_param = FALSE;
3841         MMPLAYER_FENTER();
3842
3843         /* check video sinkbin is created */
3844         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3845                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
3846
3847         if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) {
3848                 LOGE("can not find tizenwlsink");
3849                 return MM_ERROR_PLAYER_INTERNAL;
3850         }
3851
3852         LOGD("param_name : %s", param_name);
3853         if (!g_strcmp0(param_name, "update_all_param"))
3854                 update_all_param = TRUE;
3855
3856         if (update_all_param || !g_strcmp0(param_name, "display_overlay"))
3857                 __mmplayer_video_param_set_display_overlay(player);
3858         if (update_all_param || !g_strcmp0(param_name, "display_method"))
3859                 __mmplayer_video_param_set_display_method(player);
3860         if (update_all_param || !g_strcmp0(param_name, "wl_window_render_x"))
3861                 __mmplayer_video_param_set_render_rectangle(player);
3862         if (update_all_param || !g_strcmp0(param_name, "display_visible"))
3863                 __mmplayer_video_param_set_display_visible(player);
3864         if (update_all_param || !g_strcmp0(param_name, "display_rotation"))
3865                 __mmplayer_video_param_set_display_rotation(player);
3866
3867         return MM_ERROR_NONE;
3868 }
3869
3870 int
3871 _mmplayer_update_video_param(mm_player_t* player, char *param_name)
3872 {
3873         MMHandleType attrs = 0;
3874         int surface_type = 0;
3875         int ret = MM_ERROR_NONE;
3876
3877         MMPLAYER_FENTER();
3878
3879         /* check video sinkbin is created */
3880         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3881                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
3882
3883         attrs = MMPLAYER_GET_ATTRS(player);
3884         if (!attrs) {
3885                 LOGE("cannot get content attribute");
3886                 return MM_ERROR_PLAYER_INTERNAL;
3887         }
3888         LOGD("param_name : %s", param_name);
3889
3890         /* update display surface */
3891         mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
3892         LOGD("check display surface type attribute: %d", surface_type);
3893
3894         /* configuring display */
3895         switch (surface_type) {
3896         case MM_DISPLAY_SURFACE_OVERLAY:
3897                 {
3898                         ret = __mmplayer_update_wayland_videosink_video_param(player, param_name);
3899                         if (ret != MM_ERROR_NONE)
3900                                 return ret;
3901                 }
3902                 break;
3903         }
3904
3905         MMPLAYER_FLEAVE();
3906
3907         return MM_ERROR_NONE;
3908 }
3909
3910 int
3911 _mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
3912 {
3913         gboolean disable_overlay = FALSE;
3914         mm_player_t* player = (mm_player_t*) hplayer;
3915         int ret = MM_ERROR_NONE;
3916
3917         MMPLAYER_FENTER();
3918         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3919         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
3920                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
3921                                                                 MM_ERROR_PLAYER_NO_OP); /* invalid op */
3922
3923         if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
3924                 LOGW("Display control is not supported");
3925                 return MM_ERROR_PLAYER_INTERNAL;
3926         }
3927
3928         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
3929
3930         if (audio_only == (bool)disable_overlay) {
3931                 LOGE("It's the same with current setting: (%d)", audio_only);
3932                 return MM_ERROR_NONE;
3933         }
3934
3935         if (audio_only) {
3936                 LOGE("disable overlay");
3937                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", TRUE, NULL);
3938
3939                 /* release overlay resource */
3940                 if (player->video_overlay_resource != NULL) {
3941                         ret = mm_resource_manager_mark_for_release(player->resource_manager,
3942                                         player->video_overlay_resource);
3943                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3944                                 LOGE("failed to mark overlay resource for release, ret(0x%x)\n", ret);
3945                                 goto ERROR;
3946                         }
3947                         player->video_overlay_resource = NULL;
3948                 }
3949
3950                 ret = mm_resource_manager_commit(player->resource_manager);
3951                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3952                         LOGE("failed to commit acquiring of overlay resource, ret(0x%x)\n", ret);
3953                         goto ERROR;
3954                 }
3955         } else {
3956                 /* mark video overlay for acquire */
3957                 if (player->video_overlay_resource == NULL) {
3958                         ret = mm_resource_manager_mark_for_acquire(player->resource_manager,
3959                                         MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
3960                                         MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
3961                                         &player->video_overlay_resource);
3962                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3963                                 LOGE("could not prepare for video_overlay resource\n");
3964                                 goto ERROR;
3965                         }
3966                 }
3967
3968                 player->interrupted_by_resource = FALSE;
3969                 /* acquire resources for video overlay */
3970                 ret = mm_resource_manager_commit(player->resource_manager);
3971                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3972                         LOGE("could not acquire resources for video playing\n");
3973                         goto ERROR;
3974                 }
3975
3976                 LOGD("enable overlay");
3977                 __mmplayer_video_param_set_display_overlay(player);
3978                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", FALSE, NULL);
3979         }
3980
3981 ERROR:
3982         MMPLAYER_FLEAVE();
3983         return MM_ERROR_NONE;
3984 }
3985
3986 int
3987 _mmplayer_get_audio_only(MMHandleType hplayer, bool *paudio_only)
3988 {
3989         mm_player_t* player = (mm_player_t*) hplayer;
3990         gboolean disable_overlay = FALSE;
3991
3992         MMPLAYER_FENTER();
3993
3994         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3995         MMPLAYER_RETURN_VAL_IF_FAIL(paudio_only, MM_ERROR_INVALID_ARGUMENT);
3996         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
3997                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
3998                                                                 MM_ERROR_PLAYER_NO_OP); /* invalid op */
3999
4000         if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
4001                 LOGW("Display control is not supported");
4002                 return MM_ERROR_PLAYER_INTERNAL;
4003         }
4004
4005         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
4006
4007         *paudio_only = (bool)(disable_overlay);
4008
4009         LOGD("audio_only : %d", *paudio_only);
4010
4011         MMPLAYER_FLEAVE();
4012
4013         return MM_ERROR_NONE;
4014 }
4015
4016 static int
4017 __mmplayer_gst_element_link_bucket(GList* element_bucket)
4018 {
4019         GList* bucket = element_bucket;
4020         MMPlayerGstElement* element = NULL;
4021         MMPlayerGstElement* prv_element = NULL;
4022         gint successful_link_count = 0;
4023
4024         MMPLAYER_FENTER();
4025
4026         MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, -1);
4027
4028         prv_element = (MMPlayerGstElement*)bucket->data;
4029         bucket = bucket->next;
4030
4031         for (; bucket; bucket = bucket->next) {
4032                 element = (MMPlayerGstElement*)bucket->data;
4033
4034                 if (element && element->gst) {
4035                         /* If next element is audio appsrc then make a separate audio pipeline */
4036                         if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "audio_appsrc") ||
4037                                 !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "subtitle_appsrc")) {
4038                                 prv_element = element;
4039                                 continue;
4040                         }
4041
4042                         if (prv_element && prv_element->gst) {
4043                                 if (gst_element_link(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst))) {
4044                                         LOGD("linking [%s] to [%s] success\n",
4045                                                 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4046                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
4047                                         successful_link_count++;
4048                                 } else {
4049                                         LOGD("linking [%s] to [%s] failed\n",
4050                                                 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4051                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
4052                                         return -1;
4053                                 }
4054                         }
4055                 }
4056
4057                 prv_element = element;
4058         }
4059
4060         MMPLAYER_FLEAVE();
4061
4062         return successful_link_count;
4063 }
4064
4065 static int
4066 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket)
4067 {
4068         GList* bucket = element_bucket;
4069         MMPlayerGstElement* element = NULL;
4070         int successful_add_count = 0;
4071
4072         MMPLAYER_FENTER();
4073
4074         MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, 0);
4075         MMPLAYER_RETURN_VAL_IF_FAIL(bin, 0);
4076
4077         for (; bucket; bucket = bucket->next) {
4078                 element = (MMPlayerGstElement*)bucket->data;
4079
4080                 if (element && element->gst) {
4081                         if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
4082                                 LOGD("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
4083                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
4084                                         GST_ELEMENT_NAME(GST_ELEMENT(bin)));
4085                                 return 0;
4086                         }
4087                         successful_add_count++;
4088                 }
4089         }
4090
4091         MMPLAYER_FLEAVE();
4092
4093         return successful_add_count;
4094 }
4095
4096 static void __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data)
4097 {
4098         mm_player_t* player = (mm_player_t*) data;
4099         GstCaps *caps = NULL;
4100         GstStructure *str = NULL;
4101         const char *name;
4102
4103         MMPLAYER_FENTER();
4104
4105         MMPLAYER_RETURN_IF_FAIL(pad)
4106         MMPLAYER_RETURN_IF_FAIL(unused)
4107         MMPLAYER_RETURN_IF_FAIL(data)
4108
4109         caps = gst_pad_get_current_caps(pad);
4110         if (!caps)
4111                 return;
4112
4113         str = gst_caps_get_structure(caps, 0);
4114         if (!str)
4115                 goto ERROR;
4116
4117         name = gst_structure_get_name(str);
4118         if (!name)
4119                 goto ERROR;
4120
4121         LOGD("name = %s\n", name);
4122
4123         if (strstr(name, "audio")) {
4124                 _mmplayer_update_content_attrs(player, ATTR_AUDIO);
4125
4126                 if (player->audio_stream_changed_cb) {
4127                         LOGE("call the audio stream changed cb\n");
4128                         player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
4129                 }
4130         } else if (strstr(name, "video")) {
4131                 if ((name = gst_structure_get_string(str, "format")))
4132                         player->set_mode.video_zc = name[0] == 'S';
4133
4134                 _mmplayer_update_content_attrs(player, ATTR_VIDEO);
4135
4136                 if (player->video_stream_changed_cb) {
4137                         LOGE("call the video stream changed cb\n");
4138                         player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
4139                 }
4140         } else
4141                 goto ERROR;
4142
4143 ERROR:
4144
4145         gst_caps_unref(caps);
4146
4147         MMPLAYER_FLEAVE();
4148
4149         return;
4150 }
4151
4152
4153
4154 /**
4155  * This function is to create audio pipeline for playing.
4156  *
4157  * @param       player          [in]    handle of player
4158  *
4159  * @return      This function returns zero on success.
4160  * @remark
4161  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
4162  */
4163 /* macro for code readability. just for sinkbin-creation functions */
4164 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
4165 do {\
4166         x_bin[x_id].id = x_id;\
4167         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4168         if (!x_bin[x_id].gst) {\
4169                 LOGE("failed to create %s \n", x_factory);\
4170                 goto ERROR;\
4171         } else {\
4172                 if (x_player->ini.set_dump_element_flag)\
4173                         __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
4174         } \
4175         if (x_add_bucket)\
4176                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
4177 } while (0);
4178
4179 static void
4180 __mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all)
4181 {
4182         GList *l = NULL;
4183
4184         MMPLAYER_FENTER();
4185         MMPLAYER_RETURN_IF_FAIL(player);
4186
4187         if (player->audio_stream_buff_list) {
4188                 for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
4189                         mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
4190                         if (tmp) {
4191                                 if (send_all) {
4192                                         LOGD("[%"G_GUINT64_FORMAT"] send remained data.", tmp->channel_mask);
4193                                         __mmplayer_audio_stream_send_data(player, tmp);
4194                                 }
4195                                 if (tmp->pcm_data)
4196                                         g_free(tmp->pcm_data);
4197                                 g_free(tmp);
4198                         }
4199                 }
4200                 g_list_free(player->audio_stream_buff_list);
4201                 player->audio_stream_buff_list = NULL;
4202         }
4203
4204         MMPLAYER_FLEAVE();
4205 }
4206
4207 static void
4208 __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer)
4209 {
4210         MMPlayerAudioStreamDataType audio_stream = { 0, };
4211
4212         MMPLAYER_FENTER();
4213         MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
4214
4215         audio_stream.bitrate = a_buffer->bitrate;
4216         audio_stream.channel = a_buffer->channel;
4217         audio_stream.depth = a_buffer->depth;
4218         audio_stream.is_little_endian = a_buffer->is_little_endian;
4219         audio_stream.channel_mask = a_buffer->channel_mask;
4220         audio_stream.data_size = a_buffer->data_size;
4221         audio_stream.data = a_buffer->pcm_data;
4222
4223         /* LOGD("[%"G_GUINT64_FORMAT"] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_stream_cb_user_param); */
4224         player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param);
4225
4226         MMPLAYER_FLEAVE();
4227 }
4228
4229 static void
4230 __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
4231 {
4232         mm_player_t* player = (mm_player_t*) data;
4233
4234         gint channel = 0;
4235         gint rate = 0;
4236         gint depth = 0;
4237         gint endianness = 0;
4238         guint64 channel_mask = 0;
4239         void *a_data = NULL;
4240         gint a_size = 0;
4241         mm_player_audio_stream_buff_t *a_buffer = NULL;
4242         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
4243         GList *l = NULL;
4244
4245         MMPLAYER_FENTER();
4246         MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
4247
4248         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
4249         a_data = mapinfo.data;
4250         a_size = mapinfo.size;
4251
4252         GstCaps *caps = gst_pad_get_current_caps(pad);
4253         GstStructure *structure = gst_caps_get_structure(caps, 0);
4254
4255         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
4256         gst_structure_get_int(structure, "rate", &rate);
4257         gst_structure_get_int(structure, "channels", &channel);
4258         gst_structure_get_int(structure, "depth", &depth);
4259         gst_structure_get_int(structure, "endianness", &endianness);
4260         gst_structure_get(structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
4261         gst_caps_unref(GST_CAPS(caps));
4262
4263         /* In case of the sync is false, use buffer list.              *
4264          * The num of buffer list depends on the num of audio channels */
4265         if (player->audio_stream_buff_list) {
4266                 for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
4267                         mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
4268                         if (tmp) {
4269                                 if (channel_mask == tmp->channel_mask) {
4270                                         /* LOGD("[%"G_GUINT64_FORMAT"] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size); */
4271                                         if (tmp->data_size + a_size < tmp->buff_size) {
4272                                                 memcpy(tmp->pcm_data + tmp->data_size, a_data, a_size);
4273                                                 tmp->data_size += a_size;
4274                                         } else {
4275                                                 /* send data to client */
4276                                                 __mmplayer_audio_stream_send_data(player, tmp);
4277
4278                                                 if (a_size > tmp->buff_size) {
4279                                                         LOGD("[%"G_GUINT64_FORMAT"] adj buffer size %d -> %d", channel_mask, tmp->buff_size, a_size);
4280                                                         tmp->pcm_data = g_realloc(tmp->pcm_data, a_size);
4281                                                         if (tmp->pcm_data == NULL) {
4282                                                                 LOGE("failed to realloc data.");
4283                                                                 goto DONE;
4284                                                         }
4285                                                         tmp->buff_size = a_size;
4286                                                 }
4287                                                 memset(tmp->pcm_data, 0x00, tmp->buff_size);
4288                                                 memcpy(tmp->pcm_data, a_data, a_size);
4289                                                 tmp->data_size = a_size;
4290                                         }
4291                                         goto DONE;
4292                                 }
4293                         } else {
4294                                 LOGE("data is empty in list.");
4295                                 goto DONE;
4296                         }
4297                 }
4298         }
4299
4300         /* create new audio stream data */
4301         a_buffer = (mm_player_audio_stream_buff_t*)g_malloc0(sizeof(mm_player_audio_stream_buff_t));
4302         if (a_buffer == NULL) {
4303                 LOGE("failed to alloc data.");
4304                 goto DONE;
4305         }
4306         a_buffer->bitrate = rate;
4307         a_buffer->channel = channel;
4308         a_buffer->depth = depth;
4309         a_buffer->is_little_endian = (endianness == 1234 ? 1 : 0);
4310         a_buffer->channel_mask = channel_mask;
4311         a_buffer->data_size = a_size;
4312
4313         if (!player->audio_stream_sink_sync) {
4314                 /* If sync is FALSE, use buffer list to reduce the IPC. */
4315                 a_buffer->buff_size = (a_size > player->ini.pcm_buffer_size) ? (a_size) : (player->ini.pcm_buffer_size);
4316                 a_buffer->pcm_data = g_malloc(a_buffer->buff_size);
4317                 if (a_buffer->pcm_data == NULL) {
4318                         LOGE("failed to alloc data.");
4319                         g_free(a_buffer);
4320                         goto DONE;
4321                 }
4322                 memcpy(a_buffer->pcm_data, a_data, a_size);
4323                 /* LOGD("new [%"G_GUINT64_FORMAT"] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size); */
4324                 player->audio_stream_buff_list = g_list_append(player->audio_stream_buff_list, a_buffer);
4325         } else {
4326                 /* If sync is TRUE, send data directly. */
4327                 a_buffer->pcm_data = a_data;
4328                 __mmplayer_audio_stream_send_data(player, a_buffer);
4329                 g_free(a_buffer);
4330         }
4331
4332 DONE:
4333         gst_buffer_unmap(buffer, &mapinfo);
4334         MMPLAYER_FLEAVE();
4335 }
4336
4337 static void
4338 __mmplayer_gst_audio_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
4339 {
4340         mm_player_t* player = (mm_player_t*)data;
4341         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
4342         GstPad* sinkpad = NULL;
4343         GstElement *queue = NULL, *sink = NULL;
4344
4345         MMPLAYER_FENTER();
4346         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
4347
4348         queue = gst_element_factory_make("queue", NULL);
4349         if (queue == NULL) {
4350                 LOGD("fail make queue\n");
4351                 goto ERROR;
4352         }
4353
4354         sink = gst_element_factory_make("fakesink", NULL);
4355         if (sink == NULL) {
4356                 LOGD("fail make fakesink\n");
4357                 goto ERROR;
4358         }
4359
4360         gst_bin_add_many(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
4361
4362         if (!gst_element_link_pads_full(queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING)) {
4363                 LOGW("failed to link queue & sink\n");
4364                 goto ERROR;
4365         }
4366
4367         sinkpad = gst_element_get_static_pad(queue, "sink");
4368
4369         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
4370                 LOGW("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
4371                 goto ERROR;
4372         }
4373
4374         LOGE("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
4375
4376         gst_object_unref(sinkpad);
4377         g_object_set(sink, "sync", player->audio_stream_sink_sync, NULL);
4378         g_object_set(sink, "signal-handoffs", TRUE, NULL);
4379
4380         gst_element_set_state(sink, GST_STATE_PAUSED);
4381         gst_element_set_state(queue, GST_STATE_PAUSED);
4382
4383         MMPLAYER_SIGNAL_CONNECT(player,
4384                 G_OBJECT(sink),
4385                 MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4386                 "handoff",
4387                 G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
4388                 (gpointer)player);
4389
4390         MMPLAYER_FLEAVE();
4391         return;
4392
4393 ERROR:
4394         LOGE("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
4395         if (queue) {
4396                 gst_object_unref(GST_OBJECT(queue));
4397                 queue = NULL;
4398         }
4399         if (sink) {
4400                 gst_object_unref(GST_OBJECT(sink));
4401                 sink = NULL;
4402         }
4403         if (sinkpad) {
4404                 gst_object_unref(GST_OBJECT(sinkpad));
4405                 sinkpad = NULL;
4406         }
4407
4408         return;
4409 }
4410
4411 void __mmplayer_gst_set_audiosink_property(mm_player_t* player, MMHandleType attrs)
4412 {
4413         #define MAX_PROPS_LEN 128
4414         gint latency_mode = 0;
4415         gchar *stream_type = NULL;
4416         gchar *latency = NULL;
4417         gint stream_id = 0;
4418         gchar stream_props[MAX_PROPS_LEN] = {0,};
4419         GstStructure *props = NULL;
4420
4421         /* set volume table
4422          * It should be set after player creation through attribute.
4423          * But, it can not be changed during playing.
4424          */
4425         MMPLAYER_FENTER();
4426         mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
4427         mm_attrs_get_string_by_name(attrs, "sound_stream_type", &stream_type);
4428
4429         if (!stream_type) {
4430                 LOGE("stream_type is null.\n");
4431         } else {
4432                 if (player->sound.focus_id)
4433                         snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d, media.focus_id=%d",
4434                                         stream_type, stream_id, player->sound.focus_id);
4435                 else
4436                         snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d",
4437                                         stream_type, stream_id);
4438                 props = gst_structure_from_string(stream_props, NULL);
4439                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
4440                 LOGI("stream_type[%s], stream_id[%d], focus_id[%d], result[%s].\n",
4441                         stream_type, stream_id, player->sound.focus_id, stream_props);
4442                 gst_structure_free(props);
4443         }
4444
4445         mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
4446
4447         switch (latency_mode) {
4448         case AUDIO_LATENCY_MODE_LOW:
4449                 latency = g_strndup("low", 3);
4450                 break;
4451         case AUDIO_LATENCY_MODE_MID:
4452                 latency = g_strndup("mid", 3);
4453                 break;
4454         case AUDIO_LATENCY_MODE_HIGH:
4455                 latency = g_strndup("high", 4);
4456                 break;
4457         };
4458
4459         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
4460                         "latency", latency,
4461                         NULL);
4462
4463         LOGD("audiosink property - latency=%s \n", latency);
4464
4465         g_free(latency);
4466
4467         MMPLAYER_FLEAVE();
4468 }
4469
4470 static int
4471 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
4472 {
4473         MMPlayerGstElement* first_element = NULL;
4474         MMPlayerGstElement* audiobin = NULL;
4475         MMHandleType attrs = 0;
4476         GstPad *pad = NULL;
4477         GstPad *ghostpad = NULL;
4478         GList* element_bucket = NULL;
4479         gboolean link_audio_sink_now = TRUE;
4480         int i = 0;
4481         GstCaps *acaps;
4482
4483         MMPLAYER_FENTER();
4484
4485         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4486
4487         /* alloc handles */
4488         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
4489         if (!audiobin) {
4490                 LOGE("failed to allocate memory for audiobin\n");
4491                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
4492         }
4493
4494         attrs = MMPLAYER_GET_ATTRS(player);
4495
4496         /* create bin */
4497         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
4498         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
4499         if (!audiobin[MMPLAYER_A_BIN].gst) {
4500                 LOGE("failed to create audiobin\n");
4501                 goto ERROR;
4502         }
4503
4504         /* take it */
4505         player->pipeline->audiobin = audiobin;
4506
4507         player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
4508
4509         /* Adding audiotp plugin for reverse trickplay feature */
4510 //      MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
4511
4512         /* converter */
4513         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
4514
4515         /* replaygain volume */
4516         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RGVOL, "rgvolume", "audio rgvolume", TRUE, player);
4517         if (player->sound.rg_enable)
4518                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", TRUE, NULL);
4519         else
4520                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", FALSE, NULL);
4521
4522         /* resampler */
4523         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER,  player->ini.audioresampler_element, "audio resampler", TRUE, player);
4524
4525         if (player->set_mode.pcm_extraction) {
4526                 // pcm extraction only and no sound output
4527                 if (player->audio_stream_render_cb_ex) {
4528                         char *caps_str = NULL;
4529                         GstCaps* caps = NULL;
4530                         gchar *format = NULL;
4531
4532                         /* capsfilter */
4533                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4534
4535                         mm_attrs_get_string_by_name(player->attrs, "pcm_audioformat", &format);
4536
4537                         LOGD("contents : format: %s samplerate : %d pcm_channel: %d", format, player->pcm_samplerate, player->pcm_channel);
4538
4539                         caps = gst_caps_new_simple("audio/x-raw",
4540                                         "format", G_TYPE_STRING, format,
4541                                         "rate", G_TYPE_INT, player->pcm_samplerate,
4542                                         "channels", G_TYPE_INT, player->pcm_channel,
4543                                         NULL);
4544                         caps_str = gst_caps_to_string(caps);
4545                         LOGD("new caps : %s\n", caps_str);
4546
4547                         g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4548
4549                         /* clean */
4550                         gst_caps_unref(caps);
4551                         MMPLAYER_FREEIF(caps_str);
4552
4553                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
4554
4555                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
4556                         /* raw pad handling signal */
4557                         MMPLAYER_SIGNAL_CONNECT(player,
4558                                 (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
4559                                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
4560                                                                                                 G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
4561                 } else {
4562                         int dst_samplerate = 0;
4563                         int dst_channels = 0;
4564                         int dst_depth = 0;
4565                         char *caps_str = NULL;
4566                         GstCaps* caps = NULL;
4567
4568                         /* get conf. values */
4569                         mm_attrs_multiple_get(player->attrs,
4570                                                 NULL,
4571                                                 "pcm_extraction_samplerate", &dst_samplerate,
4572                                                 "pcm_extraction_channels", &dst_channels,
4573                                                 "pcm_extraction_depth", &dst_depth,
4574                                                 NULL);
4575
4576                         /* capsfilter */
4577                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4578                         caps = gst_caps_new_simple("audio/x-raw",
4579                                         "rate", G_TYPE_INT, dst_samplerate,
4580                                         "channels", G_TYPE_INT, dst_channels,
4581                                         "depth", G_TYPE_INT, dst_depth,
4582                                         NULL);
4583                         caps_str = gst_caps_to_string(caps);
4584                         LOGD("new caps : %s\n", caps_str);
4585
4586                         g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4587
4588                         /* clean */
4589                         gst_caps_unref(caps);
4590                         MMPLAYER_FREEIF(caps_str);
4591
4592                         /* fake sink */
4593                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
4594
4595                         /* set sync */
4596                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
4597                 }
4598         } else {
4599                 // normal playback
4600                 //GstCaps* caps = NULL;
4601                 gint channels = 0;
4602
4603                 /* for logical volume control */
4604                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
4605                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
4606
4607                 if (player->sound.mute) {
4608                         LOGD("mute enabled\n");
4609                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
4610                 }
4611
4612 #if 0
4613                 /*capsfilter */
4614                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
4615                 caps = gst_caps_from_string("audio/x-raw-int, "
4616                                         "endianness = (int) LITTLE_ENDIAN, "
4617                                         "signed = (boolean) true, "
4618                                         "width = (int) 16, "
4619                                         "depth = (int) 16");
4620                 g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4621                 gst_caps_unref(caps);
4622 #endif
4623
4624                 /* check if multi-channels */
4625                 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) {
4626                         GstPad *srcpad = NULL;
4627                         GstCaps *caps = NULL;
4628
4629                         if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src"))) {
4630                                 if ((caps = gst_pad_query_caps(srcpad, NULL))) {
4631                                         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
4632                                         GstStructure *str = gst_caps_get_structure(caps, 0);
4633                                         if (str)
4634                                                 gst_structure_get_int(str, "channels", &channels);
4635                                         gst_caps_unref(caps);
4636                                 }
4637                                 gst_object_unref(srcpad);
4638                         }
4639                 }
4640
4641                 /* audio effect element. if audio effect is enabled */
4642                 if ((strcmp(player->ini.audioeffect_element, ""))
4643                         && (channels <= 2)
4644                         && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
4645                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.audioeffect_element, "audio effect filter", TRUE, player);
4646
4647                         LOGD("audio effect config. bypass = %d, effect type  = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
4648
4649                         if ((!player->bypass_audio_effect)
4650                                 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
4651                                 if (MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type) {
4652                                         if (!_mmplayer_audio_effect_custom_apply(player))
4653                                                 LOGI("apply audio effect(custom) setting success\n");
4654                                 }
4655                         }
4656
4657                         if ((strcmp(player->ini.audioeffect_element_custom, ""))
4658                                 && (player->set_mode.rich_audio))
4659                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.audioeffect_element_custom, "audio effect filter custom", TRUE, player);
4660                 }
4661
4662                 /* create audio sink */
4663                 LOGD("360 spherical %d, channels %d, ambisonic type %d, format %d, order %d",
4664                                 player->is_content_spherical, channels, player->video360_metadata.ambisonic_type,
4665                                 player->video360_metadata.ambisonic_format, player->video360_metadata.ambisonic_order);
4666
4667                 /* Note: qtdemux converts audio metadata defaults to openalsink defaults. */
4668                 if (player->is_360_feature_enabled &&
4669                         player->is_content_spherical &&
4670                         channels == 4 &&
4671                         player->video360_metadata.ambisonic_type == MMFILE_AMBISONIC_TYPE_PERIPHONIC &&
4672                         player->video360_metadata.ambisonic_format == MMFILE_AMBISONIC_FORMAT_AMB &&
4673                         player->video360_metadata.ambisonic_order == MMFILE_AMBISONIC_ORDER_FOA) {
4674
4675                         strncpy(player->ini.audiosink_element, "openalsink", PLAYER_INI_MAX_STRLEN - 1);
4676
4677                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_BFORMAT, "audioconvert", "audio-converter-bformat", link_audio_sink_now, player);
4678
4679                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_360, "capsfilter", "audio-caps-filter", link_audio_sink_now, player);
4680                         acaps = gst_caps_from_string(SPATIAL_AUDIO_CAPS);
4681                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_CAPS_360].gst), "caps", acaps, NULL);
4682                         gst_caps_unref(acaps);
4683
4684                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "openalsink", "audiosink", link_audio_sink_now, player);
4685                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "source-ambisonics-type", 1, NULL);
4686                         sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info);
4687                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL);
4688
4689                         player->is_openal_plugin_used = TRUE;
4690
4691                         if (player->video360_yaw_radians <= M_PI &&
4692                                         player->video360_yaw_radians >= -M_PI &&
4693                                         player->video360_pitch_radians <= M_PI_2 &&
4694                                         player->video360_pitch_radians >= -M_PI_2) {
4695                                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
4696                                                 "source-orientation-y", (int) (player->video360_yaw_radians * 180.0 / M_PI),
4697                                                 "source-orientation-x", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
4698                         } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
4699                                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
4700                                                 "source-orientation-y", player->video360_metadata.init_view_heading,
4701                                                 "source-orientation-x", player->video360_metadata.init_view_pitch, NULL);
4702                         }
4703                 } else {
4704                         if (player->is_360_feature_enabled && player->is_content_spherical)
4705                                 LOGW("Audio track isn't of the ambisonic type and can't be played back as a spatial sound.\n");
4706                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", link_audio_sink_now, player);
4707                 }
4708
4709                 /* qos on */
4710                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);       /* qos on */
4711                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
4712
4713
4714                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) ||
4715                         (player->videodec_linked && player->ini.use_system_clock)) {
4716                         LOGD("system clock will be used.\n");
4717                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE,  NULL);
4718                 }
4719
4720                 if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
4721                         __mmplayer_gst_set_audiosink_property(player, attrs);
4722         }
4723
4724         if (audiobin[MMPLAYER_A_SINK].gst) {
4725                 GstPad *sink_pad = NULL;
4726                 sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
4727                 MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4728                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
4729                 gst_object_unref(GST_OBJECT(sink_pad));
4730         }
4731
4732         __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
4733
4734         /* adding created elements to bin */
4735         LOGD("adding created elements to bin\n");
4736         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket)) {
4737                 LOGE("failed to add elements\n");
4738                 goto ERROR;
4739         }
4740
4741         /* linking elements in the bucket by added order. */
4742         LOGD("Linking elements in the bucket by added order.\n");
4743         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
4744                 LOGE("failed to link elements\n");
4745                 goto ERROR;
4746         }
4747
4748         /* get first element's sinkpad for creating ghostpad */
4749         first_element = (MMPlayerGstElement *)element_bucket->data;
4750         if (!first_element) {
4751                 LOGE("failed to get first elem\n");
4752                 goto ERROR;
4753         }
4754
4755         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
4756         if (!pad) {
4757                 LOGE("failed to get pad from first element of audiobin\n");
4758                 goto ERROR;
4759         }
4760
4761         ghostpad = gst_ghost_pad_new("sink", pad);
4762         if (!ghostpad) {
4763                 LOGE("failed to create ghostpad\n");
4764                 goto ERROR;
4765         }
4766
4767         if (FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad)) {
4768                 LOGE("failed to add ghostpad to audiobin\n");
4769                 goto ERROR;
4770         }
4771
4772         gst_object_unref(pad);
4773
4774         g_list_free(element_bucket);
4775         MMPLAYER_FLEAVE();
4776
4777         return MM_ERROR_NONE;
4778
4779 ERROR:
4780
4781         LOGD("ERROR : releasing audiobin\n");
4782
4783         if (pad)
4784                 gst_object_unref(GST_OBJECT(pad));
4785
4786         if (ghostpad)
4787                 gst_object_unref(GST_OBJECT(ghostpad));
4788
4789         if (element_bucket)
4790                 g_list_free(element_bucket);
4791
4792         /* release element which are not added to bin */
4793         for (i = 1; i < MMPLAYER_A_NUM; i++) {
4794                 /* NOTE : skip bin */
4795                 if (audiobin[i].gst) {
4796                         GstObject* parent = NULL;
4797                         parent = gst_element_get_parent(audiobin[i].gst);
4798
4799                         if (!parent) {
4800                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
4801                                 audiobin[i].gst = NULL;
4802                         } else
4803                                 gst_object_unref(GST_OBJECT(parent));
4804                 }
4805         }
4806
4807         /* release audiobin with it's childs */
4808         if (audiobin[MMPLAYER_A_BIN].gst)
4809                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
4810
4811         MMPLAYER_FREEIF(audiobin);
4812
4813         player->pipeline->audiobin = NULL;
4814
4815         return MM_ERROR_PLAYER_INTERNAL;
4816 }
4817
4818 static GstPadProbeReturn
4819 __mmplayer_audio_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
4820 {
4821         mm_player_t* player = (mm_player_t*) u_data;
4822         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
4823         GstMapInfo probe_info = GST_MAP_INFO_INIT;
4824
4825         gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
4826
4827         if (player->audio_stream_cb && probe_info.size && probe_info.data)
4828                 player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
4829
4830         return GST_PAD_PROBE_OK;
4831 }
4832
4833 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
4834 {
4835         return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
4836 }
4837
4838 int _mmplayer_video_stream_release_bo(mm_player_t* player, void* bo)
4839 {
4840         int ret = MM_ERROR_NONE;
4841         GList *l = NULL;
4842         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4843         MMPLAYER_RETURN_VAL_IF_FAIL(bo, MM_ERROR_INVALID_ARGUMENT);
4844
4845         MMPLAYER_VIDEO_BO_LOCK(player);
4846
4847         if (player->video_bo_list) {
4848                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4849                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4850                         if (tmp && tmp->bo == bo) {
4851                                 tmp->using = FALSE;
4852                                 LOGD("release bo %p", bo);
4853                                 tbm_bo_unref(tmp->bo);
4854                                 MMPLAYER_VIDEO_BO_UNLOCK(player);
4855                                 MMPLAYER_VIDEO_BO_SIGNAL(player);
4856                                 return ret;
4857                         }
4858                 }
4859         } else {
4860                 /* hw codec is running or the list was reset for DRC. */
4861                 LOGW("there is no bo list.");
4862         }
4863         MMPLAYER_VIDEO_BO_UNLOCK(player);
4864
4865         LOGW("failed to find bo %p", bo);
4866         return ret;
4867 }
4868
4869 static void
4870 __mmplayer_video_stream_destroy_bo_list(mm_player_t* player)
4871 {
4872         GList *l = NULL;
4873
4874         MMPLAYER_FENTER();
4875         MMPLAYER_RETURN_IF_FAIL(player);
4876
4877         MMPLAYER_VIDEO_BO_LOCK(player);
4878         if (player->video_bo_list) {
4879                 LOGD("destroy video_bo_list : %d", g_list_length(player->video_bo_list));
4880                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4881                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4882                         if (tmp) {
4883                                 if (tmp->bo)
4884                                         tbm_bo_unref(tmp->bo);
4885                                 g_free(tmp);
4886                         }
4887                 }
4888                 g_list_free(player->video_bo_list);
4889                 player->video_bo_list = NULL;
4890         }
4891         player->video_bo_size = 0;
4892         MMPLAYER_VIDEO_BO_UNLOCK(player);
4893
4894         MMPLAYER_FLEAVE();
4895         return;
4896 }
4897
4898 static void*
4899 __mmplayer_video_stream_get_bo(mm_player_t* player, int size)
4900 {
4901         GList *l = NULL;
4902         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
4903         gboolean ret = TRUE;
4904
4905         /* check DRC, if it is, destroy the prev bo list to create again */
4906         if (player->video_bo_size != size) {
4907                 LOGD("video size is changed: %d -> %d", player->video_bo_size, size);
4908                 __mmplayer_video_stream_destroy_bo_list(player);
4909                 player->video_bo_size = size;
4910         }
4911
4912         MMPLAYER_VIDEO_BO_LOCK(player);
4913
4914         if ((!player->video_bo_list) ||
4915                 (g_list_length(player->video_bo_list) < player->ini.num_of_video_bo)) {
4916
4917                 /* create bo list */
4918                 int idx = 0;
4919                 LOGD("Create bo list for decoded video stream(num:%d)", player->ini.num_of_video_bo);
4920
4921                 if (player->video_bo_list) {
4922                         /* if bo list did not created all, try it again. */
4923                         idx = g_list_length(player->video_bo_list);
4924                         LOGD("bo list exist(len: %d)", idx);
4925                 }
4926
4927                 for (; idx < player->ini.num_of_video_bo; idx++) {
4928                         mm_player_video_bo_info_t* bo_info = g_new(mm_player_video_bo_info_t, 1);
4929                         if (!bo_info) {
4930                                 LOGE("Fail to alloc bo_info.");
4931                                 break;
4932                         }
4933                         bo_info->bo = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
4934                         if (!bo_info->bo) {
4935                                 LOGE("Fail to tbm_bo_alloc.");
4936                                 g_free(bo_info);
4937                                 break;
4938                         }
4939                         bo_info->using = FALSE;
4940                         player->video_bo_list = g_list_append(player->video_bo_list, bo_info);
4941                 }
4942
4943                 /* update video num buffers */
4944                 player->video_num_buffers = idx;
4945                 if (idx == player->ini.num_of_video_bo)
4946                         player->video_extra_num_buffers = player->ini.num_of_video_bo/2;
4947
4948                 if (idx == 0) {
4949                         MMPLAYER_VIDEO_BO_UNLOCK(player);
4950                         return NULL;
4951                 }
4952
4953                 LOGD("Num of video buffers(%d/%d)", player->video_num_buffers, player->video_extra_num_buffers);
4954         }
4955
4956         while (TRUE) {
4957                 /* get bo from list*/
4958                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4959                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4960                         if (tmp && (tmp->using == FALSE)) {
4961                                 LOGD("found bo %p to use", tmp->bo);
4962                                 tmp->using = TRUE;
4963                                 MMPLAYER_VIDEO_BO_UNLOCK(player);
4964                                 return tbm_bo_ref(tmp->bo);
4965                         }
4966                 }
4967                 if (!ret) {
4968                         LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
4969                         MMPLAYER_VIDEO_BO_UNLOCK(player);
4970                         return NULL;
4971                 }
4972
4973                 if (player->ini.video_bo_timeout <= 0) {
4974                         MMPLAYER_VIDEO_BO_WAIT(player);
4975                 } else {
4976                         gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout*G_TIME_SPAN_SECOND;
4977                         ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, timeout);
4978                 }
4979                 continue;
4980         }
4981 }
4982
4983 static void
4984 __mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
4985 {
4986         mm_player_t* player = (mm_player_t*)data;
4987         MMPLAYER_FENTER();
4988         MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
4989
4990         /* send prerolled pkt */
4991         player->video_stream_prerolled = FALSE;
4992
4993         __mmplayer_video_stream_decoded_render_cb(object, buffer, pad, data);
4994
4995         /* not to send prerolled pkt again */
4996         player->video_stream_prerolled = TRUE;
4997 }
4998
4999 static void
5000 __mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5001 {
5002         mm_player_t* player = (mm_player_t*)data;
5003         GstCaps *caps = NULL;
5004         MMPlayerVideoStreamDataType *stream = NULL;
5005         MMVideoBuffer *video_buffer = NULL;
5006         GstMemory *dataBlock = NULL;
5007         GstMemory *metaBlock = NULL;
5008         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5009         GstStructure *structure = NULL;
5010         const gchar *string_format = NULL;
5011         unsigned int fourcc = 0;
5012
5013         MMPLAYER_FENTER();
5014         MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
5015
5016         if (player->video_stream_prerolled) {
5017                 player->video_stream_prerolled = FALSE;
5018                 LOGD("skip the prerolled pkt not to send it again");
5019                 return;
5020         }
5021
5022         caps = gst_pad_get_current_caps(pad);
5023         if (caps == NULL) {
5024                 LOGE("Caps is NULL.");
5025                 return;
5026         }
5027
5028         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
5029
5030         /* clear stream data structure */
5031         stream = (MMPlayerVideoStreamDataType *)g_malloc0(sizeof(MMPlayerVideoStreamDataType));
5032         if (!stream) {
5033                 LOGE("failed to alloc mem for video data");
5034                 return;
5035         }
5036
5037         structure = gst_caps_get_structure(caps, 0);
5038         gst_structure_get_int(structure, "width", &(stream->width));
5039         gst_structure_get_int(structure, "height", &(stream->height));
5040         string_format = gst_structure_get_string(structure, "format");
5041         if (string_format)
5042                 fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
5043         stream->format = util_get_pixtype(fourcc);
5044         gst_caps_unref(caps);
5045         caps = NULL;
5046
5047         __mmplayer_get_video_angle(player, NULL, &stream->orientation);
5048
5049     /*
5050         LOGD("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
5051                 GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format);
5052     */
5053
5054         if (stream->width == 0 || stream->height == 0 || stream->format == MM_PIXEL_FORMAT_INVALID) {
5055                 LOGE("Wrong condition!!");
5056                 goto ERROR;
5057         }
5058
5059         /* set size and timestamp */
5060         dataBlock = gst_buffer_peek_memory(buffer, 0);
5061         stream->length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
5062         stream->timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/GST_MSECOND); /* nano sec -> mili sec */
5063
5064         /* check zero-copy */
5065         if (player->set_mode.video_zc &&
5066                 player->set_mode.media_packet_video_stream &&
5067                 gst_buffer_n_memory(buffer) > 1) {
5068                 metaBlock = gst_buffer_peek_memory(buffer, 1);
5069                 gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
5070                 video_buffer = (MMVideoBuffer *)mapinfo.data;
5071         }
5072
5073         if (video_buffer) { /* hw codec */
5074                 /* set tbm bo */
5075                 if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
5076                         int i = 0;
5077
5078                         /* copy pointer of tbm bo, stride, elevation */
5079                         while (i < MM_VIDEO_BUFFER_PLANE_MAX && video_buffer->handle.bo[i]) {
5080                                 stream->bo[i] = tbm_bo_ref(video_buffer->handle.bo[i]);
5081                                 i++;
5082                         }
5083                 } else {
5084                         LOGE("Not support video buffer format");
5085                         goto ERROR;
5086                 }
5087                 memcpy(stream->stride, video_buffer->stride_width,
5088                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5089                 memcpy(stream->elevation, video_buffer->stride_height,
5090                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5091
5092                 /* will be released, by calling _mm_player_video_stream_internal_buffer_unref() */
5093                 stream->internal_buffer = gst_buffer_ref(buffer);
5094         } else { /* sw codec */
5095                 int i = 0;
5096                 int j = 0;
5097                 int k = 0;
5098                 int ret = TBM_SURFACE_ERROR_NONE;
5099                 int src_stride[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
5100                 int src_offset[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
5101                 int size = 0;
5102                 unsigned char *src = NULL;
5103                 unsigned char *dest = NULL;
5104                 tbm_bo_handle thandle;
5105                 tbm_surface_h surface;
5106                 tbm_surface_info_s info;
5107                 gboolean gst_ret;
5108
5109                 gst_ret = gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
5110                 if (!gst_ret) {
5111                         LOGE("fail to gst_memory_map");
5112                         goto ERROR;
5113                 }
5114
5115
5116                 if (stream->format == MM_PIXEL_FORMAT_I420) {
5117                         surface = tbm_surface_create(stream->width, stream->height, TBM_FORMAT_YUV420);
5118
5119                         ret = tbm_surface_get_info(surface, &info);
5120
5121                         if (ret != TBM_SURFACE_ERROR_NONE) {
5122                                 tbm_surface_destroy(surface);
5123                                 goto ERROR;
5124                         }
5125                         tbm_surface_destroy(surface);
5126
5127                         src_stride[0] = GST_ROUND_UP_4(stream->width);
5128                         src_stride[1] = src_stride[2] = GST_ROUND_UP_4(stream->width>>1);
5129                         src_offset[1] = src_stride[0] * GST_ROUND_UP_2(stream->height);
5130                         src_offset[2] = src_offset[1] + (src_stride[1] * (GST_ROUND_UP_2(stream->height)>>1));
5131                         stream->stride[0] = info.planes[0].stride;
5132                         stream->elevation[0] = info.planes[0].size / info.planes[0].stride;
5133                         stream->stride[1] = info.planes[1].stride;
5134                         stream->elevation[1] = info.planes[1].size / info.planes[1].stride;
5135                         stream->stride[2] = info.planes[2].stride;
5136                         stream->elevation[2] = info.planes[2].size / info.planes[2].stride;
5137                         size = info.planes[0].size + info.planes[1].size + info.planes[2].size;
5138                 } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
5139                         stream->stride[0] = stream->width * 4;
5140                         stream->elevation[0] = stream->height;
5141                         size = stream->stride[0] * stream->height;
5142                 } else {
5143                         LOGE("Not support format %d", stream->format);
5144                         goto ERROR;
5145                 }
5146
5147                 stream->bo[0] = __mmplayer_video_stream_get_bo(player, size);
5148                 if (!stream->bo[0]) {
5149                         LOGE("Fail to tbm_bo_alloc!!");
5150                         goto ERROR;
5151                 }
5152
5153                 thandle = tbm_bo_map(stream->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
5154                 if (thandle.ptr && mapinfo.data) {
5155                         if (stream->format == MM_PIXEL_FORMAT_I420) {
5156                                 for (i = 0; i < 3; i++) {
5157                                         src = mapinfo.data + src_offset[i];
5158                                         dest = thandle.ptr + info.planes[i].offset;
5159
5160                                         if (i > 0) k = 1;
5161                                         for (j = 0; j < stream->height>>k; j++) {
5162                                                 memcpy(dest, src, stream->width>>k);
5163                                                 src += src_stride[i];
5164                                                 dest += stream->stride[i];
5165                                         }
5166                                 }
5167                         } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
5168                                 memcpy(thandle.ptr, mapinfo.data, size);
5169                         } else {
5170                                 LOGE("Not support format %d", stream->format);
5171                                 goto ERROR;
5172                         }
5173                 } else {
5174                         LOGE("data pointer is wrong. dest : %p, src : %p",
5175                                         thandle.ptr, mapinfo.data);
5176                         goto ERROR;
5177                 }
5178                 tbm_bo_unmap(stream->bo[0]);
5179         }
5180
5181         if (player->video_stream_cb) { /* This has been already checked at the entry */
5182                 if (!player->video_stream_cb(stream, player->video_stream_cb_user_param)) {
5183                         LOGE("failed to send video stream data.");
5184                         goto ERROR;
5185                 }
5186         }
5187
5188         if (metaBlock)
5189                 gst_memory_unmap(metaBlock, &mapinfo);
5190         else
5191                 gst_memory_unmap(dataBlock, &mapinfo);
5192
5193         return;
5194
5195 ERROR:
5196         LOGE("release video stream resource.");
5197         if (metaBlock) {
5198                 int i = 0;
5199                 for (i = 0 ; i < MM_VIDEO_BUFFER_PLANE_MAX ; i++) {
5200                         if (stream->bo[i])
5201                                 tbm_bo_unref(stream->bo[i]);
5202                 }
5203                 gst_memory_unmap(metaBlock, &mapinfo);
5204
5205                 /* unref gst buffer */
5206                 if (stream->internal_buffer)
5207                         gst_buffer_unref(stream->internal_buffer);
5208         } else if (dataBlock) {
5209                 if (stream->bo[0])
5210                         _mmplayer_video_stream_release_bo(player, stream->bo[0]);
5211                 gst_memory_unmap(dataBlock, &mapinfo);
5212         }
5213
5214         g_free(stream);
5215         return;
5216 }
5217
5218 static int
5219 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket)
5220 {
5221         gchar* video_csc = "videoconvert"; /* default colorspace converter */
5222         GList* element_bucket = NULL;
5223
5224         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5225
5226         MMPLAYER_FENTER();
5227
5228         if (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical)) {
5229                 LOGD("do not need to add video filters.");
5230                 return MM_ERROR_NONE;
5231         }
5232
5233         /* in case of sw codec except 360 playback,
5234          * if libav video decoder is selected, videoconvert is required to render the shm wl-buffer which support RGB only via tizenwlsink. */
5235         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5236         LOGD("using video converter: %s", video_csc);
5237
5238         /* set video rotator */
5239         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5240
5241         *bucket = element_bucket;
5242         MMPLAYER_FLEAVE();
5243         return MM_ERROR_NONE;
5244
5245 ERROR: /* refer MMPLAYER_CREATE_ELEMENT */
5246         g_list_free(element_bucket);
5247
5248         *bucket = NULL;
5249         MMPLAYER_FLEAVE();
5250         return MM_ERROR_PLAYER_INTERNAL;
5251 }
5252
5253 /**
5254  * This function is to create video pipeline.
5255  *
5256  * @param       player          [in]    handle of player
5257  *              caps            [in]    src caps of decoder
5258  *              surface_type    [in]    surface type for video rendering
5259  *
5260  * @return      This function returns zero on success.
5261  * @remark
5262  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5263  */
5264 /**
5265   * VIDEO PIPELINE
5266   * - video overlay surface(arm/x86) : tizenwlsink
5267   */
5268 static int
5269 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5270 {
5271         GstPad *pad = NULL;
5272         MMHandleType attrs;
5273         GList*element_bucket = NULL;
5274         MMPlayerGstElement* first_element = NULL;
5275         MMPlayerGstElement* videobin = NULL;
5276         gchar *videosink_element = NULL;
5277
5278         MMPLAYER_FENTER();
5279
5280         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5281
5282         /* alloc handles */
5283         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5284         if (!videobin)
5285                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5286
5287         player->pipeline->videobin = videobin;
5288
5289         attrs = MMPLAYER_GET_ATTRS(player);
5290         if (!attrs) {
5291                 LOGE("cannot get content attribute");
5292                 return MM_ERROR_PLAYER_INTERNAL;
5293         }
5294
5295         /* create bin */
5296         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
5297         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
5298         if (!videobin[MMPLAYER_V_BIN].gst) {
5299                 LOGE("failed to create videobin");
5300                 goto ERROR;
5301         }
5302
5303         int enable_video_decoded_cb = 0;
5304         mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable_video_decoded_cb);
5305
5306         if (player->is_360_feature_enabled && player->is_content_spherical) {
5307                 LOGD("video360 elem will be added.");
5308
5309                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_360, "video360",
5310                                 "video-360", TRUE, player);
5311
5312                 /* Set spatial media metadata and/or user settings to the element.
5313                  * */
5314                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5315                                 "projection-type", player->video360_metadata.projection_type, NULL);
5316
5317                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5318                                 "stereo-mode", player->video360_metadata.stereo_mode, NULL);
5319
5320                 if (player->video360_metadata.full_pano_width_pixels &&
5321                                 player->video360_metadata.full_pano_height_pixels &&
5322                                 player->video360_metadata.cropped_area_image_width &&
5323                                 player->video360_metadata.cropped_area_image_height) {
5324                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5325                                         "projection-bounds-top", player->video360_metadata.cropped_area_top,
5326                                         "projection-bounds-bottom", player->video360_metadata.full_pano_height_pixels -
5327                                                         player->video360_metadata.cropped_area_top - player->video360_metadata.cropped_area_image_height,
5328                                         "projection-bounds-left", player->video360_metadata.cropped_area_left,
5329                                         "projection-bounds-right", player->video360_metadata.full_pano_width_pixels -
5330                                                         player->video360_metadata.cropped_area_left - player->video360_metadata.cropped_area_image_width,
5331                                         NULL);
5332                 }
5333
5334                 if (player->video360_horizontal_fov && player->video360_vertical_fov) {
5335                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5336                                         "horizontal-fov", player->video360_horizontal_fov,
5337                                         "vertical-fov", player->video360_vertical_fov, NULL);
5338                 }
5339
5340                 if (player->video360_zoom <= VIDEO360_MAX_ZOOM && player->video360_zoom > 1.0f) {
5341                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5342                                         "zoom", 1.0f / player->video360_zoom, NULL);
5343                 }
5344
5345                 if (player->video360_yaw_radians <= M_PI &&
5346                                 player->video360_yaw_radians >= -M_PI &&
5347                                 player->video360_pitch_radians <= M_PI_2 &&
5348                                 player->video360_pitch_radians >= -M_PI_2) {
5349                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5350                                         "pose-yaw", (int) (player->video360_yaw_radians * 180.0 / M_PI),
5351                                         "pose-pitch", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
5352                 } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
5353                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5354                                         "pose-yaw", player->video360_metadata.init_view_heading,
5355                                         "pose-pitch", player->video360_metadata.init_view_pitch, NULL);
5356                 }
5357
5358                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5359                                 "passthrough", !player->is_video360_enabled, NULL);
5360         }
5361
5362         /* set video sink */
5363         switch (surface_type) {
5364         case MM_DISPLAY_SURFACE_OVERLAY:
5365                 if (__mmplayer_gst_create_video_filters(player, &element_bucket) != MM_ERROR_NONE)
5366                         goto ERROR;
5367                 if (strlen(player->ini.videosink_element_overlay) > 0)
5368                         videosink_element = player->ini.videosink_element_overlay;
5369                 else
5370                         goto ERROR;
5371                 break;
5372         case MM_DISPLAY_SURFACE_NULL:
5373                 if (strlen(player->ini.videosink_element_fake) > 0)
5374                         videosink_element = player->ini.videosink_element_fake;
5375                 else
5376                         goto ERROR;
5377                 break;
5378         case MM_DISPLAY_SURFACE_REMOTE:
5379                 if (strlen(player->ini.videosink_element_fake) > 0)
5380                         videosink_element = player->ini.videosink_element_fake;
5381                 else
5382                         goto ERROR;
5383                 break;
5384         default:
5385                 LOGE("unidentified surface type");
5386                 goto ERROR;
5387         }
5388         LOGD("surface_type %d, selected videosink name: %s", surface_type, videosink_element);
5389
5390         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, "videosink", TRUE, player);
5391
5392         /* additional setting for sink plug-in */
5393         switch (surface_type) {
5394         case MM_DISPLAY_SURFACE_OVERLAY:
5395         {
5396                 bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical));
5397                 if (!use_tbm) {
5398                         LOGD("selected videosink name: %s", videosink_element);
5399
5400                         /* support shard memory with S/W codec on HawkP */
5401                         if (strncmp(videosink_element, "tizenwlsink", strlen(videosink_element)) == 0) {
5402                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5403                                         "use-tbm", use_tbm, NULL);
5404                         }
5405                 } else {
5406                         if (attrs) {
5407                                 int gapless = 0;
5408
5409                                 mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
5410
5411                                 if (gapless > 0) {
5412                                         LOGD("disable last-sample");
5413                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
5414                                 }
5415                         }
5416                 }
5417                 if (player->set_mode.media_packet_video_stream) {
5418                         int enable = 0;
5419                         mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable);
5420                         if (enable)
5421                                 g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "signal-handoffs", TRUE, NULL);
5422
5423                         MMPLAYER_SIGNAL_CONNECT(player,
5424                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5425                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5426                                                                         "handoff",
5427                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
5428                                                                         (gpointer)player);
5429
5430                         MMPLAYER_SIGNAL_CONNECT(player,
5431                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5432                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5433                                                                         "preroll-handoff",
5434                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
5435                                                                         (gpointer)player);
5436                 }
5437                 break;
5438         }
5439         case MM_DISPLAY_SURFACE_REMOTE:
5440         {
5441                 if (player->set_mode.media_packet_video_stream) {
5442                         LOGE("add data probe at videosink");
5443                         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5444                                                                                         "sync", TRUE, "signal-handoffs", TRUE, NULL);
5445
5446                         MMPLAYER_SIGNAL_CONNECT(player,
5447                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5448                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5449                                                                         "handoff",
5450                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
5451                                                                         (gpointer)player);
5452
5453                         MMPLAYER_SIGNAL_CONNECT(player,
5454                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5455                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5456                                                                         "preroll-handoff",
5457                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
5458                                                                         (gpointer)player);
5459                         if (attrs) {
5460                                 int gapless = 0;
5461
5462                                 mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
5463
5464                                 if (gapless > 0) {
5465                                         LOGD("disable last-sample");
5466                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
5467                                 }
5468                         }
5469                 }
5470                 break;
5471         }
5472         default:
5473                 break;
5474         }
5475
5476         if (_mmplayer_update_video_param(player, "update_all_param") != MM_ERROR_NONE)
5477                 goto ERROR;
5478
5479         if (videobin[MMPLAYER_V_SINK].gst) {
5480                 GstPad *sink_pad = NULL;
5481                 sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
5482                 if (sink_pad) {
5483                         MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5484                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
5485                         gst_object_unref(GST_OBJECT(sink_pad));
5486                 } else
5487                         LOGW("failed to get sink pad from videosink\n");
5488         }
5489
5490         /* store it as it's sink element */
5491         __mmplayer_add_sink(player, videobin[MMPLAYER_V_SINK].gst);
5492
5493         /* adding created elements to bin */
5494         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket)) {
5495                 LOGE("failed to add elements\n");
5496                 goto ERROR;
5497         }
5498
5499         /* Linking elements in the bucket by added order */
5500         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
5501                 LOGE("failed to link elements\n");
5502                 goto ERROR;
5503         }
5504
5505         /* get first element's sinkpad for creating ghostpad */
5506         if (element_bucket)
5507                 first_element = (MMPlayerGstElement *)element_bucket->data;
5508         if (!first_element) {
5509                 LOGE("failed to get first element from bucket\n");
5510                 goto ERROR;
5511         }
5512
5513         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5514         if (!pad) {
5515                 LOGE("failed to get pad from first element\n");
5516                 goto ERROR;
5517         }
5518
5519         /* create ghostpad */
5520         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
5521         if (FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
5522                 LOGE("failed to add ghostpad to videobin\n");
5523                 goto ERROR;
5524         }
5525         gst_object_unref(pad);
5526
5527         /* done. free allocated variables */
5528         if (element_bucket)
5529                 g_list_free(element_bucket);
5530
5531         MMPLAYER_FLEAVE();
5532
5533         return MM_ERROR_NONE;
5534
5535 ERROR:
5536         LOGE("ERROR : releasing videobin\n");
5537
5538         g_list_free(element_bucket);
5539
5540         if (pad)
5541                 gst_object_unref(GST_OBJECT(pad));
5542
5543         /* release videobin with it's childs */
5544         if (videobin[MMPLAYER_V_BIN].gst)
5545                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
5546
5547
5548         MMPLAYER_FREEIF(videobin);
5549
5550         player->pipeline->videobin = NULL;
5551
5552         return MM_ERROR_PLAYER_INTERNAL;
5553 }
5554
5555 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
5556 {
5557         GList *element_bucket = NULL;
5558         MMPlayerGstElement *textbin = player->pipeline->textbin;
5559
5560         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", TRUE, player);
5561         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", TRUE, player);
5562         g_object_set(G_OBJECT(textbin[MMPLAYER_T_IDENTITY].gst),
5563                                                         "signal-handoffs", FALSE,
5564                                                         NULL);
5565
5566         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
5567         MMPLAYER_SIGNAL_CONNECT(player,
5568                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
5569                                                         MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
5570                                                         "handoff",
5571                                                         G_CALLBACK(__mmplayer_update_subtitle),
5572                                                         (gpointer)player);
5573
5574         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
5575         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
5576         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
5577
5578         if (!player->play_subtitle) {
5579                 LOGD("add textbin sink as sink element of whole pipeline.\n");
5580                 __mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
5581         }
5582
5583         /* adding created elements to bin */
5584         LOGD("adding created elements to bin\n");
5585         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) {
5586                 LOGE("failed to add elements\n");
5587                 goto ERROR;
5588         }
5589
5590         /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
5591         GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
5592         GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
5593
5594         /* linking elements in the bucket by added order. */
5595         LOGD("Linking elements in the bucket by added order.\n");
5596         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
5597                 LOGE("failed to link elements\n");
5598                 goto ERROR;
5599         }
5600
5601         /* done. free allocated variables */
5602         g_list_free(element_bucket);
5603
5604         if (textbin[MMPLAYER_T_QUEUE].gst) {
5605                 GstPad *pad = NULL;
5606                 GstPad *ghostpad = NULL;
5607
5608                 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_QUEUE].gst), "sink");
5609                 if (!pad) {
5610                         LOGE("failed to get sink pad of text queue");
5611                         goto ERROR;
5612                 }
5613
5614                 ghostpad = gst_ghost_pad_new("text_sink", pad);
5615                 gst_object_unref(pad);
5616
5617                 if (!ghostpad) {
5618                         LOGE("failed to create ghostpad of textbin\n");
5619                         goto ERROR;
5620                 }
5621
5622                 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad)) {
5623                         LOGE("failed to add ghostpad to textbin\n");
5624                         gst_object_unref(ghostpad);
5625                         goto ERROR;
5626                 }
5627         }
5628
5629         return MM_ERROR_NONE;
5630
5631 ERROR:
5632         g_list_free(element_bucket);
5633
5634         if (!player->play_subtitle && textbin[MMPLAYER_T_FAKE_SINK].gst) {
5635                 LOGE("remove textbin sink from sink list");
5636                 __mmplayer_del_sink(player, textbin[MMPLAYER_T_FAKE_SINK].gst);
5637         }
5638
5639         /* release element at __mmplayer_gst_create_text_sink_bin */
5640         return MM_ERROR_PLAYER_INTERNAL;
5641 }
5642
5643 static int __mmplayer_gst_create_text_sink_bin(mm_player_t* player)
5644 {
5645         MMPlayerGstElement *textbin = NULL;
5646         GList *element_bucket = NULL;
5647         int surface_type = 0;
5648         gint i = 0;
5649
5650         MMPLAYER_FENTER();
5651
5652         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5653
5654         /* alloc handles */
5655         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
5656         if (!textbin) {
5657                 LOGE("failed to allocate memory for textbin\n");
5658                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5659         }
5660
5661         /* create bin */
5662         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
5663         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
5664         if (!textbin[MMPLAYER_T_BIN].gst) {
5665                 LOGE("failed to create textbin\n");
5666                 goto ERROR;
5667         }
5668
5669         /* take it */
5670         player->pipeline->textbin = textbin;
5671
5672         /* fakesink */
5673         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
5674         LOGD("surface type for subtitle : %d", surface_type);
5675         switch (surface_type) {
5676         case MM_DISPLAY_SURFACE_OVERLAY:
5677         case MM_DISPLAY_SURFACE_NULL:
5678         case MM_DISPLAY_SURFACE_REMOTE:
5679                 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE) {
5680                         LOGE("failed to make plain text elements\n");
5681                         goto ERROR;
5682                 }
5683                 break;
5684         default:
5685                 goto ERROR;
5686                 break;
5687         }
5688
5689         MMPLAYER_FLEAVE();
5690
5691         return MM_ERROR_NONE;
5692
5693 ERROR:
5694
5695         LOGD("ERROR : releasing textbin\n");
5696
5697         g_list_free(element_bucket);
5698
5699         /* release signal */
5700         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
5701
5702         /* release element which are not added to bin */
5703         for (i = 1; i < MMPLAYER_T_NUM; i++) {
5704                 /* NOTE : skip bin */
5705                 if (textbin[i].gst) {
5706                         GstObject* parent = NULL;
5707                         parent = gst_element_get_parent(textbin[i].gst);
5708
5709                         if (!parent) {
5710                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
5711                                 textbin[i].gst = NULL;
5712                         } else {
5713                                 gst_object_unref(GST_OBJECT(parent));
5714                         }
5715                 }
5716         }
5717
5718         /* release textbin with it's childs */
5719         if (textbin[MMPLAYER_T_BIN].gst)
5720                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
5721
5722         MMPLAYER_FREEIF(player->pipeline->textbin);
5723         player->pipeline->textbin = NULL;
5724
5725         MMPLAYER_FLEAVE();
5726         return MM_ERROR_PLAYER_INTERNAL;
5727 }
5728
5729
5730 static int
5731 __mmplayer_gst_create_text_pipeline(mm_player_t* player)
5732 {
5733         MMPlayerGstElement* mainbin = NULL;
5734         MMPlayerGstElement* textbin = NULL;
5735         MMHandleType attrs = 0;
5736         GstElement *subsrc = NULL;
5737         GstElement *subparse = NULL;
5738         gchar *subtitle_uri = NULL;
5739         const gchar *charset = NULL;
5740         GstPad *pad = NULL;
5741
5742         MMPLAYER_FENTER();
5743
5744         /* get mainbin */
5745         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
5746                                                                 player->pipeline &&
5747                                                                 player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5748
5749         mainbin = player->pipeline->mainbin;
5750
5751         attrs = MMPLAYER_GET_ATTRS(player);
5752         if (!attrs) {
5753                 LOGE("cannot get content attribute\n");
5754                 return MM_ERROR_PLAYER_INTERNAL;
5755         }
5756
5757         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
5758         if (!subtitle_uri || strlen(subtitle_uri) < 1) {
5759                 LOGE("subtitle uri is not proper filepath.\n");
5760                 return MM_ERROR_PLAYER_INVALID_URI;
5761         }
5762
5763         if (!util_get_storage_info(subtitle_uri, &player->storage_info[MMPLAYER_PATH_TEXT])) {
5764                 LOGE("failed to get storage info of subtitle path");
5765                 return MM_ERROR_PLAYER_INVALID_URI;
5766         }
5767
5768         SECURE_LOGD("subtitle file path is [%s].\n", subtitle_uri);
5769
5770         MMPLAYER_SUBTITLE_INFO_LOCK(player);
5771         player->subtitle_language_list = NULL;
5772         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
5773
5774         /* create the subtitle source */
5775         subsrc = gst_element_factory_make("filesrc", "subtitle_source");
5776         if (!subsrc) {
5777                 LOGE("failed to create filesrc element\n");
5778                 goto ERROR;
5779         }
5780         g_object_set(G_OBJECT(subsrc), "location", subtitle_uri, NULL);
5781
5782         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
5783         mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
5784
5785         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc)) {
5786                 LOGW("failed to add queue\n");
5787                 gst_object_unref(mainbin[MMPLAYER_M_SUBSRC].gst);
5788                 mainbin[MMPLAYER_M_SUBSRC].gst = NULL;
5789                 mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_NUM;
5790                 goto ERROR;
5791         }
5792
5793         /* subparse */
5794         subparse = gst_element_factory_make("subparse", "subtitle_parser");
5795         if (!subparse) {
5796                 LOGE("failed to create subparse element\n");
5797                 goto ERROR;
5798         }
5799
5800         charset = util_get_charset(subtitle_uri);
5801         if (charset) {
5802                 LOGD("detected charset is %s\n", charset);
5803                 g_object_set(G_OBJECT(subparse), "subtitle-encoding", charset, NULL);
5804         }
5805
5806         mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE;
5807         mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
5808
5809         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse)) {
5810                 LOGW("failed to add subparse\n");
5811                 gst_object_unref(mainbin[MMPLAYER_M_SUBPARSE].gst);
5812                 mainbin[MMPLAYER_M_SUBPARSE].gst = NULL;
5813                 mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_NUM;
5814                 goto ERROR;
5815         }
5816
5817         if (!gst_element_link_pads(subsrc, "src", subparse, "sink")) {
5818                 LOGW("failed to link subsrc and subparse\n");
5819                 goto ERROR;
5820         }
5821
5822         player->play_subtitle = TRUE;
5823         player->adjust_subtitle_pos = 0;
5824
5825         LOGD("play subtitle using subtitle file\n");
5826
5827         if (player->pipeline->textbin == NULL) {
5828                 if (MM_ERROR_NONE != __mmplayer_gst_create_text_sink_bin(player)) {
5829                         LOGE("failed to create text sink bin. continuing without text\n");
5830                         goto ERROR;
5831                 }
5832
5833                 textbin = player->pipeline->textbin;
5834
5835                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(textbin[MMPLAYER_T_BIN].gst))) {
5836                         LOGW("failed to add textbin\n");
5837
5838                         /* release signal */
5839                         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
5840
5841                         /* release textbin with it's childs */
5842                         gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
5843                         MMPLAYER_FREEIF(player->pipeline->textbin);
5844                         player->pipeline->textbin = textbin = NULL;
5845                         goto ERROR;
5846                 }
5847
5848                 LOGD("link text input selector and textbin ghost pad");
5849
5850                 player->textsink_linked = 1;
5851                 player->external_text_idx = 0;
5852                 LOGI("player->textsink_linked set to 1\n");
5853         } else {
5854                 textbin = player->pipeline->textbin;
5855                 LOGD("text bin has been created. reuse it.");
5856                 player->external_text_idx = 1;
5857         }
5858
5859         if (!gst_element_link_pads(subparse, "src", textbin[MMPLAYER_T_BIN].gst, "text_sink")) {
5860                 LOGW("failed to link subparse and textbin\n");
5861                 goto ERROR;
5862         }
5863
5864         pad = gst_element_get_static_pad(textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
5865         if (!pad) {
5866                 LOGE("failed to get sink pad from textsink to probe data");
5867                 goto ERROR;
5868         }
5869
5870         gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
5871                                 __mmplayer_subtitle_adjust_position_probe, player, NULL);
5872
5873         gst_object_unref(pad);
5874         pad = NULL;
5875
5876         /* create dot. for debugging */
5877         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-with-subtitle");
5878         MMPLAYER_FLEAVE();
5879
5880         return MM_ERROR_NONE;
5881
5882 ERROR:
5883         /* release text pipeline resource */
5884         player->textsink_linked = 0;
5885
5886         /* release signal */
5887         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
5888
5889         if (player->pipeline->textbin) {
5890                 LOGE("remove textbin");
5891
5892                 /* release textbin with it's childs */
5893                 MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN);
5894                 MMPLAYER_FREEIF(player->pipeline->textbin);
5895                 player->pipeline->textbin = NULL;
5896
5897         }
5898
5899         /* release subtitle elem */
5900         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBSRC);
5901         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBPARSE);
5902
5903         return MM_ERROR_PLAYER_INTERNAL;
5904 }
5905
5906 gboolean
5907 __mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5908 {
5909         mm_player_t* player = (mm_player_t*) data;
5910         MMMessageParamType msg = {0, };
5911         GstClockTime duration = 0;
5912         gpointer text = NULL;
5913         guint text_size = 0;
5914         gboolean ret = TRUE;
5915         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5916
5917         MMPLAYER_FENTER();
5918
5919         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
5920         MMPLAYER_RETURN_VAL_IF_FAIL(buffer, FALSE);
5921
5922         if (player->is_subtitle_force_drop) {
5923                 LOGW("subtitle is dropped forcedly.");
5924                 return ret;
5925         }
5926
5927         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
5928         text = mapinfo.data;
5929         text_size = mapinfo.size;
5930         duration = GST_BUFFER_DURATION(buffer);
5931
5932         if (player->set_mode.subtitle_off) {
5933                 LOGD("subtitle is OFF.\n");
5934                 return TRUE;
5935         }
5936
5937         if (!text || (text_size == 0)) {
5938                 LOGD("There is no subtitle to be displayed.\n");
5939                 return TRUE;
5940         }
5941
5942         msg.data = (void *) text;
5943         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
5944
5945         LOGD("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data);
5946
5947         MMPLAYER_POST_MSG(player, MM_MESSAGE_UPDATE_SUBTITLE, &msg);
5948         gst_buffer_unmap(buffer, &mapinfo);
5949
5950         MMPLAYER_FLEAVE();
5951
5952         return ret;
5953 }
5954
5955 static GstPadProbeReturn
5956 __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
5957 {
5958         mm_player_t *player = (mm_player_t *) u_data;
5959         GstClockTime cur_timestamp = 0;
5960         gint64 adjusted_timestamp = 0;
5961         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
5962
5963         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
5964
5965         if (player->set_mode.subtitle_off) {
5966                 LOGD("subtitle is OFF.\n");
5967                 return TRUE;
5968         }
5969
5970         if (player->adjust_subtitle_pos == 0) {
5971                 LOGD("nothing to do");
5972                 return TRUE;
5973         }
5974
5975         cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
5976         adjusted_timestamp = (gint64) cur_timestamp +((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
5977
5978         if (adjusted_timestamp < 0) {
5979                 LOGD("adjusted_timestamp under zero");
5980                 MMPLAYER_FLEAVE();
5981                 return FALSE;
5982         }
5983
5984         GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
5985         LOGD("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
5986                                 GST_TIME_ARGS(cur_timestamp),
5987                                 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
5988
5989         return GST_PAD_PROBE_OK;
5990 }
5991 static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
5992 {
5993         MMPLAYER_FENTER();
5994
5995         /* check player and subtitlebin are created */
5996         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5997         MMPLAYER_RETURN_VAL_IF_FAIL(player->play_subtitle, MM_ERROR_NOT_SUPPORT_API);
5998
5999         if (position == 0) {
6000                 LOGD("nothing to do\n");
6001                 MMPLAYER_FLEAVE();
6002                 return MM_ERROR_NONE;
6003         }
6004
6005         switch (format) {
6006         case MM_PLAYER_POS_FORMAT_TIME:
6007                 {
6008                         /* check current postion */
6009                         player->adjust_subtitle_pos = position;
6010
6011                         LOGD("save adjust_subtitle_pos in player") ;
6012                 }
6013                 break;
6014
6015         default:
6016                 {
6017                         LOGW("invalid format.\n");
6018                         MMPLAYER_FLEAVE();
6019                         return MM_ERROR_INVALID_ARGUMENT;
6020                 }
6021         }
6022
6023         MMPLAYER_FLEAVE();
6024
6025         return MM_ERROR_NONE;
6026 }
6027
6028 static void
6029 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data)
6030 {
6031         GstElement *appsrc = element;
6032         MMPlayerInputBuffer *buf = (MMPlayerInputBuffer *)user_data;
6033         GstBuffer *buffer = NULL;
6034         GstFlowReturn ret = GST_FLOW_OK;
6035         gint len = size;
6036
6037         MMPLAYER_RETURN_IF_FAIL(element);
6038         MMPLAYER_RETURN_IF_FAIL(buf);
6039
6040         buffer = gst_buffer_new();
6041
6042         if (buf->offset >= buf->len) {
6043                 LOGD("call eos appsrc\n");
6044                 g_signal_emit_by_name(appsrc, "end-of-stream", &ret);
6045                 return;
6046         }
6047
6048         if (buf->len - buf->offset < size)
6049                 len = buf->len - buf->offset;
6050
6051         gst_buffer_insert_memory(buffer, -1, gst_memory_new_wrapped(0, (guint8 *)(buf->buf + buf->offset), len, 0, len, NULL, NULL));
6052         GST_BUFFER_OFFSET(buffer) = (guint64)buf->offset;
6053         GST_BUFFER_OFFSET_END(buffer) = (guint64)(buf->offset + len);
6054
6055         //LOGD("feed buffer %p, offset %u-%u length %u", buffer, buf->offset, (buf->offset+len), len);
6056         g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
6057
6058         buf->offset += len;
6059 }
6060
6061 static gboolean
6062 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data)
6063 {
6064         MMPlayerInputBuffer *buf = (MMPlayerInputBuffer *)user_data;
6065
6066         MMPLAYER_RETURN_VAL_IF_FAIL(buf, FALSE);
6067
6068         buf->offset  = (int)size;
6069
6070         return TRUE;
6071 }
6072
6073 static GstBusSyncReply
6074 __mmplayer_bus_sync_callback(GstBus * bus, GstMessage * message, gpointer data)
6075 {
6076         mm_player_t *player = (mm_player_t *)data;
6077         GstBusSyncReply reply = GST_BUS_DROP;
6078
6079         if (!(player->pipeline && player->pipeline->mainbin)) {
6080                 LOGE("player pipeline handle is null");
6081                 return GST_BUS_PASS;
6082         }
6083
6084         if (!__mmplayer_check_useful_message(player, message)) {
6085                 gst_message_unref(message);
6086                 return GST_BUS_DROP;
6087         }
6088
6089         switch (GST_MESSAGE_TYPE(message)) {
6090         case GST_MESSAGE_STATE_CHANGED:
6091                 /* post directly for fast launch */
6092                 if (player->sync_handler) {
6093                         __mmplayer_gst_callback(message, player);
6094                         reply = GST_BUS_DROP;
6095                 } else
6096                         reply = GST_BUS_PASS;
6097                 break;
6098         case GST_MESSAGE_TAG:
6099                 __mmplayer_gst_extract_tag_from_msg(player, message);
6100
6101                 #if 0 // debug
6102                 {
6103                         GstTagList *tags = NULL;
6104
6105                         gst_message_parse_tag(message, &tags);
6106                         if (tags) {
6107                                 LOGE("TAGS received from element \"%s\".\n",
6108                                 GST_STR_NULL(GST_ELEMENT_NAME(GST_MESSAGE_SRC(message))));
6109
6110                                 gst_tag_list_foreach(tags, print_tag, NULL);
6111                                 gst_tag_list_free(tags);
6112                                 tags = NULL;
6113                         }
6114                         break;
6115                 }
6116                 #endif
6117                 break;
6118
6119         case GST_MESSAGE_DURATION_CHANGED:
6120                 __mmplayer_gst_handle_duration(player, message);
6121                 break;
6122         case GST_MESSAGE_ASYNC_DONE:
6123                 /* NOTE:Don't call gst_callback directly
6124                  * because previous frame can be showed even though this message is received for seek.
6125                  */
6126         default:
6127                 reply = GST_BUS_PASS;
6128                 break;
6129         }
6130
6131         if (reply == GST_BUS_DROP)
6132                 gst_message_unref(message);
6133
6134         return reply;
6135 }
6136
6137 static gboolean
6138 __mmplayer_gst_create_decoder(mm_player_t *player,
6139                                                                 MMPlayerTrackType track,
6140                                                                 GstPad* srcpad,
6141                                                                 enum MainElementID elemId,
6142                                                                 const gchar* name)
6143 {
6144         gboolean ret = TRUE;
6145         GstPad *sinkpad = NULL;
6146
6147         MMPLAYER_FENTER();
6148
6149         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
6150                                                 player->pipeline &&
6151                                                 player->pipeline->mainbin, FALSE);
6152         MMPLAYER_RETURN_VAL_IF_FAIL((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE);
6153         MMPLAYER_RETURN_VAL_IF_FAIL(srcpad, FALSE);
6154         MMPLAYER_RETURN_VAL_IF_FAIL((player->pipeline->mainbin[elemId].gst == NULL), FALSE);
6155
6156         GstElement *decodebin = NULL;
6157         GstCaps *dec_caps = NULL;
6158
6159         /* create decodebin */
6160         decodebin = gst_element_factory_make("decodebin", name);
6161
6162         if (!decodebin) {
6163                 LOGE("error : fail to create decodebin for %d decoder\n", track);
6164                 ret = FALSE;
6165                 goto ERROR;
6166         }
6167
6168         /* raw pad handling signal */
6169         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6170                                                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
6171
6172         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
6173         before looking for any elements that can handle that stream.*/
6174         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
6175                                                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
6176
6177         /* This signal is emitted when a element is added to the bin.*/
6178         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
6179                                                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
6180
6181         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
6182                 LOGE("failed to add new decodebin\n");
6183                 ret = FALSE;
6184                 goto ERROR;
6185         }
6186
6187         dec_caps = gst_pad_query_caps(srcpad, NULL);
6188         if (dec_caps) {
6189                 //LOGD("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
6190                 g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
6191                 gst_caps_unref(dec_caps);
6192         }
6193
6194         player->pipeline->mainbin[elemId].id = elemId;
6195         player->pipeline->mainbin[elemId].gst = decodebin;
6196
6197         sinkpad = gst_element_get_static_pad(decodebin, "sink");
6198
6199         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
6200                 LOGW("failed to link [%s:%s] to decoder\n", GST_DEBUG_PAD_NAME(srcpad));
6201                 gst_object_unref(GST_OBJECT(decodebin));
6202         }
6203
6204         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin))
6205                 LOGE("failed to sync second level decodebin state with parent\n");
6206
6207         LOGD("Total num of %d tracks = %d \n", track, player->selector[track].total_track_num);
6208
6209 ERROR:
6210         if (sinkpad) {
6211                 gst_object_unref(GST_OBJECT(sinkpad));
6212                 sinkpad = NULL;
6213         }
6214         MMPLAYER_FLEAVE();
6215
6216         return ret;
6217 }
6218
6219 /**
6220  * This function is to create  audio or video pipeline for playing.
6221  *
6222  * @param       player          [in]    handle of player
6223  *
6224  * @return      This function returns zero on success.
6225  * @remark
6226  * @see
6227  */
6228 static int
6229 __mmplayer_gst_create_pipeline(mm_player_t* player)
6230 {
6231         GstBus  *bus = NULL;
6232         MMPlayerGstElement *mainbin = NULL;
6233         MMHandleType attrs = 0;
6234         GstElement* element = NULL;
6235         GstElement* elem_src_audio = NULL;
6236         GstElement* elem_src_subtitle = NULL;
6237         GstElement* es_video_queue = NULL;
6238         GstElement* es_audio_queue = NULL;
6239         GstElement* es_subtitle_queue = NULL;
6240         GList* element_bucket = NULL;
6241         gboolean need_state_holder = TRUE;
6242         gint i = 0;
6243 #ifdef SW_CODEC_ONLY
6244         int surface_type = 0;
6245 #endif
6246         MMPLAYER_FENTER();
6247
6248         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6249
6250         /* get profile attribute */
6251         attrs = MMPLAYER_GET_ATTRS(player);
6252         if (!attrs) {
6253                 LOGE("cannot get content attribute\n");
6254                 goto INIT_ERROR;
6255         }
6256
6257         /* create pipeline handles */
6258         if (player->pipeline) {
6259                 LOGW("pipeline should be released before create new one\n");
6260                 goto INIT_ERROR;
6261         }
6262
6263         player->video360_metadata.is_spherical = -1;
6264         player->is_openal_plugin_used = FALSE;
6265
6266         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0(sizeof(MMPlayerGstPipelineInfo));
6267         if (player->pipeline == NULL)
6268                 goto INIT_ERROR;
6269
6270         memset(player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo)); /* g_malloc0 did this job already */
6271
6272         /* create mainbin */
6273         mainbin = (MMPlayerGstElement*) g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
6274         if (mainbin == NULL)
6275                 goto INIT_ERROR;
6276
6277         memset(mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM); /* g_malloc0 did this job already */
6278
6279         /* create pipeline */
6280         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
6281         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
6282         if (!mainbin[MMPLAYER_M_PIPE].gst) {
6283                 LOGE("failed to create pipeline\n");
6284                 goto INIT_ERROR;
6285         }
6286         player->demux_pad_index = 0;
6287         player->subtitle_language_list = NULL;
6288
6289         player->is_subtitle_force_drop = FALSE;
6290         player->last_multiwin_status = FALSE;
6291
6292         _mmplayer_track_initialize(player);
6293         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
6294
6295         /* create source element */
6296         switch (player->profile.uri_type) {
6297         /* rtsp streamming */
6298         case MM_PLAYER_URI_TYPE_URL_RTSP:
6299                 {
6300                         gchar *user_agent;
6301
6302                         element = gst_element_factory_make("rtspsrc", "rtsp source");
6303
6304                         if (!element) {
6305                                 LOGE("failed to create streaming source element\n");
6306                                 break;
6307                         }
6308
6309                         /* make it zero */
6310                         user_agent = NULL;
6311
6312                         /* get attribute */
6313                         mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
6314
6315                         SECURE_LOGD("user_agent : %s\n", user_agent);
6316
6317                         /* setting property to streaming source */
6318                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6319                         if (user_agent)
6320                                 g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6321
6322                         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6323                                 G_CALLBACK(__mmplayer_gst_rtp_dynamic_pad), player);
6324                         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
6325                                 G_CALLBACK(__mmplayer_gst_rtp_no_more_pads), player);
6326                 }
6327                 break;
6328
6329         /* http streaming*/
6330         case MM_PLAYER_URI_TYPE_URL_HTTP:
6331                 {
6332                         gchar *user_agent, *cookies, **cookie_list;
6333                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6334                         user_agent = cookies = NULL;
6335                         cookie_list = NULL;
6336                         gint mode = MM_PLAYER_PD_MODE_NONE;
6337
6338                         mm_attrs_get_int_by_name(attrs, "pd_mode", &mode);
6339
6340                         player->pd_mode = mode;
6341
6342                         LOGD("http playback, PD mode : %d\n", player->pd_mode);
6343
6344                         if (!MMPLAYER_IS_HTTP_PD(player)) {
6345                                 element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
6346                                 if (!element) {
6347                                         LOGE("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
6348                                         break;
6349                                 }
6350                                 LOGD("using http streamming source [%s].\n", player->ini.httpsrc_element);
6351
6352                                 /* get attribute */
6353                                 mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
6354                                 mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
6355
6356                                 if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
6357                                         LOGD("get timeout from ini\n");
6358                                         http_timeout = player->ini.http_timeout;
6359                                 }
6360
6361                                 /* get attribute */
6362                                 SECURE_LOGD("location : %s\n", player->profile.uri);
6363                                 SECURE_LOGD("cookies : %s\n", cookies);
6364                                 SECURE_LOGD("user_agent :  %s\n",  user_agent);
6365                                 LOGD("timeout : %d\n",  http_timeout);
6366
6367                                 /* setting property to streaming source */
6368                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6369                                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6370                                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
6371
6372                                 /* parsing cookies */
6373                                 if ((cookie_list = util_get_cookie_list((const char*)cookies))) {
6374                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
6375                                         g_strfreev(cookie_list);
6376                                 }
6377                                 if (user_agent)
6378                                         g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6379
6380                                 if (MMPLAYER_URL_HAS_DASH_SUFFIX(player))
6381                                         LOGW("it's dash. and it's still experimental feature.");
6382                         } else {
6383                                 // progressive download
6384                                 gchar* location = NULL;
6385
6386                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI) {
6387                                         gchar *path = NULL;
6388
6389                                         mm_attrs_get_string_by_name(attrs, "pd_location", &path);
6390
6391                                         MMPLAYER_FREEIF(player->pd_file_save_path);
6392
6393                                         LOGD("PD Location : %s\n", path);
6394
6395                                         if (path) {
6396                                                 if (!util_get_storage_info(path, &player->storage_info[MMPLAYER_PATH_VOD])) {
6397                                                         LOGE("failed to get storage info");
6398                                                         break;
6399                                                 }
6400                                                 player->pd_file_save_path = g_strdup(path);
6401                                         } else {
6402                                                 LOGE("can't find pd location so, it should be set \n");
6403                                                 break;
6404                                         }
6405                                 }
6406
6407                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
6408                                 if (!element) {
6409                                         LOGE("failed to create PD push source element[%s].\n", "pdpushsrc");
6410                                         break;
6411                                 }
6412
6413                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
6414                                         g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
6415                                 else
6416                                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6417                                 g_object_get(element, "location", &location, NULL);
6418                                 LOGD("PD_LOCATION [%s].\n", location);
6419                                 if (location)
6420                                         g_free(location);
6421                         }
6422                 }
6423                 break;
6424
6425         /* file source */
6426         case MM_PLAYER_URI_TYPE_FILE:
6427                 {
6428                         LOGD("using filesrc for 'file://' handler.\n");
6429                         if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
6430                                 LOGE("failed to get storage info");
6431                                 break;
6432                         }
6433
6434                         element = gst_element_factory_make("filesrc", "source");
6435                         if (!element) {
6436                                 LOGE("failed to create filesrc\n");
6437                                 break;
6438                         }
6439
6440                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
6441                 }
6442                 break;
6443
6444         case MM_PLAYER_URI_TYPE_SS:
6445                 {
6446                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6447                         element = gst_element_factory_make("souphttpsrc", "http streaming source");
6448                         if (!element) {
6449                                 LOGE("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
6450                                 break;
6451                         }
6452
6453                         if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
6454                                 LOGD("get timeout from ini\n");
6455                                 http_timeout = player->ini.http_timeout;
6456                         }
6457
6458                         /* setting property to streaming source */
6459                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6460                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6461                 }
6462                 break;
6463         case MM_PLAYER_URI_TYPE_MS_BUFF:
6464                 {
6465                         LOGD("MS buff src is selected\n");
6466
6467                         if (player->v_stream_caps) {
6468                                 element = gst_element_factory_make("appsrc", "video_appsrc");
6469                                 if (!element) {
6470                                         LOGF("failed to create video app source element[appsrc].\n");
6471                                         break;
6472                                 }
6473
6474                                 if (player->a_stream_caps) {
6475                                         elem_src_audio = gst_element_factory_make("appsrc", "audio_appsrc");
6476                                         if (!elem_src_audio) {
6477                                                 LOGF("failed to create audio app source element[appsrc].\n");
6478                                                 break;
6479                                         }
6480                                 }
6481                         } else if (player->a_stream_caps) {
6482                                 /* no video, only audio pipeline*/
6483                                 element = gst_element_factory_make("appsrc", "audio_appsrc");
6484                                 if (!element) {
6485                                         LOGF("failed to create audio app source element[appsrc].\n");
6486                                         break;
6487                                 }
6488                         }
6489
6490                         if (player->s_stream_caps) {
6491                                 elem_src_subtitle = gst_element_factory_make("appsrc", "subtitle_appsrc");
6492                                 if (!elem_src_subtitle) {
6493                                         LOGF("failed to create subtitle app source element[appsrc].\n");
6494                                         break;
6495                                 }
6496                         }
6497
6498                         LOGD("setting app sources properties.\n");
6499                         LOGD("location : %s\n", player->profile.uri);
6500
6501                         if (player->v_stream_caps && element) {
6502                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6503                                                                                             "blocksize", (guint)1048576,        /* size of many video frames are larger than default blocksize as 4096 */
6504                                                                                                 "caps", player->v_stream_caps, NULL);
6505
6506                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6507                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6508                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6509                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6510
6511                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6512                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6513                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6514                                                                                                                 G_CALLBACK(__gst_seek_video_data), player);
6515
6516                                 if (player->a_stream_caps && elem_src_audio) {
6517                                         g_object_set(G_OBJECT(elem_src_audio), "format", GST_FORMAT_TIME,
6518                                                                                                                         "caps", player->a_stream_caps, NULL);
6519
6520                                         if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6521                                                 g_object_set(G_OBJECT(elem_src_audio), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6522                                         if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6523                                                 g_object_set(G_OBJECT(elem_src_audio), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6524
6525                                         /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6526                                         gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_audio), GST_APP_STREAM_TYPE_SEEKABLE);
6527                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6528                                                                                                                 G_CALLBACK(__gst_seek_audio_data), player);
6529                                 }
6530                         } else if (player->a_stream_caps && element) {
6531                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6532                                                                                                 "caps", player->a_stream_caps, NULL);
6533
6534                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6535                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6536                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6537                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6538
6539                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6540                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6541                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6542                                                                                                                         G_CALLBACK(__gst_seek_audio_data), player);
6543                         }
6544
6545                         if (player->s_stream_caps && elem_src_subtitle) {
6546                                 g_object_set(G_OBJECT(elem_src_subtitle), "format", GST_FORMAT_TIME,
6547                                                                                                                  "caps", player->s_stream_caps, NULL);
6548
6549                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6550                                         g_object_set(G_OBJECT(elem_src_subtitle), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6551                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6552                                         g_object_set(G_OBJECT(elem_src_subtitle), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6553
6554                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_subtitle), GST_APP_STREAM_TYPE_SEEKABLE);
6555
6556                                 MMPLAYER_SIGNAL_CONNECT(player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6557                                                                                                                                 G_CALLBACK(__gst_seek_subtitle_data), player);
6558                         }
6559
6560                         if (player->v_stream_caps && element) {
6561                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6562                                                                                                                 G_CALLBACK(__gst_appsrc_feed_video_data), player);
6563                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6564                                                                                                                 G_CALLBACK(__gst_appsrc_enough_video_data), player);
6565
6566                                 if (player->a_stream_caps && elem_src_audio) {
6567                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6568                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6569                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6570                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6571                                 }
6572                         } else if (player->a_stream_caps && element) {
6573                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6574                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6575                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6576                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6577                         }
6578
6579                         if (player->s_stream_caps && elem_src_subtitle)
6580                                 MMPLAYER_SIGNAL_CONNECT(player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6581                                                                                                                 G_CALLBACK(__gst_appsrc_feed_subtitle_data), player);
6582
6583                         need_state_holder = FALSE;
6584
6585                         mm_attrs_set_int_by_name(attrs, "profile_prepare_async", TRUE);
6586                         if (mmf_attrs_commit(attrs)) /* return -1 if error */
6587                                 LOGE("failed to commit\n");
6588                 }
6589                 break;
6590         /* appsrc */
6591         case MM_PLAYER_URI_TYPE_MEM:
6592                 {
6593                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
6594
6595                         LOGD("mem src is selected\n");
6596
6597                         element = gst_element_factory_make("appsrc", "mem-source");
6598                         if (!element) {
6599                                 LOGE("failed to create appsrc element\n");
6600                                 break;
6601                         }
6602
6603                         g_object_set(element, "stream-type", stream_type, NULL);
6604                         g_object_set(element, "size", player->profile.input_mem.len, NULL);
6605                         g_object_set(element, "blocksize", (guint64)20480, NULL);
6606
6607                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6608                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->profile.input_mem);
6609                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6610                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->profile.input_mem);
6611                 }
6612                 break;
6613         case MM_PLAYER_URI_TYPE_URL:
6614                 break;
6615
6616         case MM_PLAYER_URI_TYPE_TEMP:
6617                 break;
6618
6619         case MM_PLAYER_URI_TYPE_NONE:
6620         default:
6621                 break;
6622         }
6623
6624         /* check source element is OK */
6625         if (!element) {
6626                 LOGE("no source element was created.\n");
6627                 goto INIT_ERROR;
6628         }
6629
6630         /* take source element */
6631         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
6632         mainbin[MMPLAYER_M_SRC].gst = element;
6633         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
6634
6635         if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL)) {
6636                 player->streamer = __mm_player_streaming_create();
6637                 __mm_player_streaming_initialize(player->streamer);
6638         }
6639
6640         if (MMPLAYER_IS_HTTP_PD(player)) {
6641                 gint pre_buffering_time = player->streamer->buffering_req.prebuffer_time;
6642
6643                 LOGD("Picked queue2 element(pre buffer : %d ms)....\n", pre_buffering_time);
6644                 element = gst_element_factory_make("queue2", "queue2");
6645                 if (!element) {
6646                         LOGE("failed to create http streaming buffer element\n");
6647                         goto INIT_ERROR;
6648                 }
6649
6650                 /* take it */
6651                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
6652                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
6653                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
6654
6655                 pre_buffering_time = (pre_buffering_time > 0) ? (pre_buffering_time) : (player->ini.http_buffering_time);
6656
6657                 player->streamer->is_pd_mode = TRUE;
6658
6659                 __mm_player_streaming_set_queue2(player->streamer,
6660                                 element,
6661                                 TRUE,
6662                                 player->ini.http_max_size_bytes, // + PLAYER_PD_EXT_MAX_SIZE_BYTE,
6663                                 pre_buffering_time,
6664                                 1.0,
6665                                 player->ini.http_buffering_limit,
6666                                 MUXED_BUFFER_TYPE_MEM_QUEUE,
6667                                 NULL,
6668                                 0);
6669         }
6670         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
6671                 if (player->v_stream_caps) {
6672                         es_video_queue = gst_element_factory_make("queue2", "video_queue");
6673                         if (!es_video_queue) {
6674                                 LOGE("create es_video_queue for es player failed\n");
6675                                 goto INIT_ERROR;
6676                         }
6677                         g_object_set(G_OBJECT(es_video_queue), "max-size-buffers", 2, NULL);
6678                         mainbin[MMPLAYER_M_V_BUFFER].id = MMPLAYER_M_V_BUFFER;
6679                         mainbin[MMPLAYER_M_V_BUFFER].gst = es_video_queue;
6680                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_V_BUFFER]);
6681
6682                         /* Adding audio appsrc to bucket */
6683                         if (player->a_stream_caps && elem_src_audio) {
6684                                 mainbin[MMPLAYER_M_2ND_SRC].id = MMPLAYER_M_2ND_SRC;
6685                                 mainbin[MMPLAYER_M_2ND_SRC].gst = elem_src_audio;
6686                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_2ND_SRC]);
6687
6688                                 es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6689                                 if (!es_audio_queue) {
6690                                         LOGE("create es_audio_queue for es player failed\n");
6691                                         goto INIT_ERROR;
6692                                 }
6693                                 g_object_set(G_OBJECT(es_audio_queue), "max-size-buffers", 2, NULL);
6694
6695                                 mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6696                                 mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6697                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6698                         }
6699                 } else if (player->a_stream_caps) {
6700                         /* Only audio stream, no video */
6701                         es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6702                         if (!es_audio_queue) {
6703                                 LOGE("create es_audio_queue for es player failed\n");
6704                                 goto INIT_ERROR;
6705                         }
6706                         mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6707                         mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6708                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6709                 }
6710
6711                 if (player->s_stream_caps && elem_src_subtitle) {
6712                         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6713                         mainbin[MMPLAYER_M_SUBSRC].gst = elem_src_subtitle;
6714                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SUBSRC]);
6715
6716                         es_subtitle_queue = gst_element_factory_make("queue2", "subtitle_queue");
6717                         if (!es_subtitle_queue) {
6718                                 LOGE("create es_subtitle_queue for es player failed\n");
6719                                 goto INIT_ERROR;
6720                         }
6721                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_V_BUFFER;
6722                         mainbin[MMPLAYER_M_S_BUFFER].gst = es_subtitle_queue;
6723                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
6724                 }
6725         }
6726
6727         /* create autoplugging element if src element is not a rtsp src */
6728         if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
6729                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_MS_BUFF)) {
6730                 element = NULL;
6731                 enum MainElementID elemId = MMPLAYER_M_NUM;
6732
6733                 if (((MMPLAYER_IS_HTTP_PD(player)) ||
6734                         (!MMPLAYER_IS_HTTP_STREAMING(player)))) {
6735                         elemId = MMPLAYER_M_AUTOPLUG;
6736                         element = __mmplayer_create_decodebin(player);
6737                         if (element) {
6738                                 /* default size of mq in decodebin is 2M
6739                                  * but it can cause blocking issue during seeking depends on content. */
6740                                 g_object_set(G_OBJECT(element), "max-size-bytes", (5*1024*1024), NULL);
6741                         }
6742                         need_state_holder = FALSE;
6743                 } else {
6744                         elemId = MMPLAYER_M_TYPEFIND;
6745                         element = gst_element_factory_make("typefind", "typefinder");
6746                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
6747                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
6748                 }
6749
6750
6751                 /* check autoplug element is OK */
6752                 if (!element) {
6753                         LOGE("can not create element(%d)\n", elemId);
6754                         goto INIT_ERROR;
6755                 }
6756
6757                 mainbin[elemId].id = elemId;
6758                 mainbin[elemId].gst = element;
6759
6760                 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
6761         }
6762
6763         /* add elements to pipeline */
6764         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket)) {
6765                 LOGE("Failed to add elements to pipeline\n");
6766                 goto INIT_ERROR;
6767         }
6768
6769
6770         /* linking elements in the bucket by added order. */
6771         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
6772                 LOGE("Failed to link some elements\n");
6773                 goto INIT_ERROR;
6774         }
6775
6776
6777         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
6778         if (need_state_holder) {
6779                 /* create */
6780                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
6781                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
6782
6783                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst) {
6784                         LOGE("fakesink element could not be created\n");
6785                         goto INIT_ERROR;
6786                 }
6787                 GST_OBJECT_FLAG_UNSET(mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
6788
6789                 /* take ownership of fakesink. we are reusing it */
6790                 gst_object_ref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
6791
6792                 /* add */
6793                 if (FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
6794                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst)) {
6795                         LOGE("failed to add fakesink to bin\n");
6796                         goto INIT_ERROR;
6797                 }
6798         }
6799
6800         /* now we have completed mainbin. take it */
6801         player->pipeline->mainbin = mainbin;
6802
6803         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
6804                 GstPad *srcpad = NULL;
6805
6806                 if (mainbin[MMPLAYER_M_V_BUFFER].gst) {
6807                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_V_BUFFER].gst, "src");
6808                         if (srcpad) {
6809                                 __mmplayer_gst_create_decoder(player,
6810                                                                                                 MM_PLAYER_TRACK_TYPE_VIDEO,
6811                                                                                                 srcpad,
6812                                                                                                 MMPLAYER_M_AUTOPLUG_V_DEC,
6813                                                                                                 "video_decodebin");
6814
6815                                 gst_object_unref(GST_OBJECT(srcpad));
6816                                 srcpad = NULL;
6817                         }
6818                 }
6819
6820                 if ((player->a_stream_caps) && (mainbin[MMPLAYER_M_A_BUFFER].gst)) {
6821                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_BUFFER].gst, "src");
6822                         if (srcpad) {
6823                                 __mmplayer_gst_create_decoder(player,
6824                                                                                                 MM_PLAYER_TRACK_TYPE_AUDIO,
6825                                                                                                 srcpad,
6826                                                                                                 MMPLAYER_M_AUTOPLUG_A_DEC,
6827                                                                                                 "audio_decodebin");
6828
6829                                 gst_object_unref(GST_OBJECT(srcpad));
6830                                 srcpad = NULL;
6831                         } // else error
6832                 } //  else error
6833
6834                 if (mainbin[MMPLAYER_M_S_BUFFER].gst)
6835                         __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
6836         }
6837
6838         /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
6839         if (__mmplayer_check_subtitle(player)) {
6840                 if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player))
6841                         LOGE("fail to create text pipeline");
6842         }
6843
6844         /* connect bus callback */
6845         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
6846         if (!bus) {
6847                 LOGE("cannot get bus from pipeline.\n");
6848                 goto INIT_ERROR;
6849         }
6850
6851         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_msg_push, player);
6852
6853         player->context.thread_default = g_main_context_get_thread_default();
6854
6855         if (player->context.thread_default == NULL) {
6856                 player->context.thread_default = g_main_context_default();
6857                 LOGD("thread-default context is the global default context");
6858         }
6859         LOGW("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
6860
6861         /* set sync handler to get tag synchronously */
6862         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL);
6863
6864         /* finished */
6865         gst_object_unref(GST_OBJECT(bus));
6866         g_list_free(element_bucket);
6867
6868         /* create gst bus_msb_cb thread */
6869         g_mutex_init(&player->bus_msg_thread_mutex);
6870         g_cond_init(&player->bus_msg_thread_cond);
6871         player->bus_msg_thread_exit = FALSE;
6872         player->bus_msg_timeout = PLAYER_BUS_MSG_DEFAULT_TIMEOUT;
6873         player->bus_msg_thread =
6874                 g_thread_try_new("gst_bus_msg_thread", __mmplayer_gst_bus_msg_thread, (gpointer)player, NULL);
6875         if (!player->bus_msg_thread) {
6876                 LOGE("failed to create gst BUS msg thread");
6877                 g_mutex_clear(&player->bus_msg_thread_mutex);
6878                 g_cond_clear(&player->bus_msg_thread_cond);
6879                 goto INIT_ERROR;
6880         }
6881
6882         MMPLAYER_FLEAVE();
6883
6884         return MM_ERROR_NONE;
6885
6886 INIT_ERROR:
6887         __mmplayer_gst_destroy_pipeline(player);
6888         g_list_free(element_bucket);
6889
6890         if (mainbin) {
6891                 /* release element which are not added to bin */
6892                 for (i = 1; i < MMPLAYER_M_NUM; i++) {
6893                         /* NOTE : skip pipeline */
6894                         if (mainbin[i].gst) {
6895                                 GstObject* parent = NULL;
6896                                 parent = gst_element_get_parent(mainbin[i].gst);
6897
6898                                 if (!parent) {
6899                                         gst_object_unref(GST_OBJECT(mainbin[i].gst));
6900                                         mainbin[i].gst = NULL;
6901                                 } else
6902                                         gst_object_unref(GST_OBJECT(parent));
6903                         }
6904                 }
6905
6906                 /* release pipeline with it's childs */
6907                 if (mainbin[MMPLAYER_M_PIPE].gst)
6908                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
6909
6910                 MMPLAYER_FREEIF(mainbin);
6911         }
6912
6913         MMPLAYER_FREEIF(player->pipeline);
6914         return MM_ERROR_PLAYER_INTERNAL;
6915 }
6916
6917 static void
6918 __mmplayer_reset_gapless_state(mm_player_t* player)
6919 {
6920         MMPLAYER_FENTER();
6921         MMPLAYER_RETURN_IF_FAIL(player
6922                 && player->pipeline
6923                 && player->pipeline->audiobin
6924                 && player->pipeline->audiobin[MMPLAYER_A_BIN].gst);
6925
6926         memset(&player->gapless, 0, sizeof(mm_player_gapless_t));
6927
6928         MMPLAYER_FLEAVE();
6929         return;
6930 }
6931
6932 static int
6933 __mmplayer_gst_destroy_pipeline(mm_player_t* player)
6934 {
6935         gint timeout = 0;
6936         int ret = MM_ERROR_NONE;
6937
6938         MMPLAYER_FENTER();
6939
6940         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_INVALID_HANDLE);
6941
6942         /* cleanup stuffs */
6943         MMPLAYER_FREEIF(player->type);
6944         player->have_dynamic_pad = FALSE;
6945         player->no_more_pad = FALSE;
6946         player->num_dynamic_pad = 0;
6947         player->demux_pad_index = 0;
6948         player->use_deinterleave = FALSE;
6949         player->max_audio_channels = 0;
6950         player->video_share_api_delta = 0;
6951         player->video_share_clock_delta = 0;
6952         player->video_hub_download_mode = 0;
6953
6954         MMPLAYER_SUBTITLE_INFO_LOCK(player);
6955         player->subtitle_language_list = NULL;
6956         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
6957
6958         __mmplayer_reset_gapless_state(player);
6959
6960         if (player->streamer) {
6961                 __mm_player_streaming_deinitialize(player->streamer);
6962                 __mm_player_streaming_destroy(player->streamer);
6963                 player->streamer = NULL;
6964         }
6965
6966         /* cleanup unlinked mime type */
6967         MMPLAYER_FREEIF(player->unlinked_audio_mime);
6968         MMPLAYER_FREEIF(player->unlinked_video_mime);
6969         MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
6970
6971         /* cleanup running stuffs */
6972         __mmplayer_cancel_eos_timer(player);
6973
6974         /* cleanup gst stuffs */
6975         if (player->pipeline) {
6976                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
6977                 GstTagList* tag_list = player->pipeline->tag_list;
6978
6979                 /* first we need to disconnect all signal hander */
6980                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_ALL);
6981
6982                 if (player->bus_watcher)
6983                         __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
6984                 player->bus_watcher = 0;
6985
6986                 if (mainbin) {
6987                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
6988                         MMPlayerGstElement* videobin = player->pipeline->videobin;
6989                         MMPlayerGstElement* textbin = player->pipeline->textbin;
6990                         GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
6991                         gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
6992                         gst_object_unref(bus);
6993
6994                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
6995                         ret = __mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout);
6996                         if (ret != MM_ERROR_NONE) {
6997                                 LOGE("fail to change state to NULL\n");
6998                                 return MM_ERROR_PLAYER_INTERNAL;
6999                         }
7000
7001                         LOGW("succeeded in chaning state to NULL\n");
7002
7003                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7004
7005                         /* free fakesink */
7006                         if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
7007                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
7008
7009                         /* free avsysaudiosink
7010                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
7011                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
7012                         */
7013                         MMPLAYER_FREEIF(audiobin);
7014                         MMPLAYER_FREEIF(videobin);
7015                         MMPLAYER_FREEIF(textbin);
7016                         MMPLAYER_FREEIF(mainbin);
7017                 }
7018
7019                 if (tag_list)
7020                         gst_tag_list_free(tag_list);
7021
7022                 MMPLAYER_FREEIF(player->pipeline);
7023         }
7024         MMPLAYER_FREEIF(player->album_art);
7025
7026         if (player->v_stream_caps) {
7027                 gst_caps_unref(player->v_stream_caps);
7028                 player->v_stream_caps = NULL;
7029         }
7030         if (player->a_stream_caps) {
7031                 gst_caps_unref(player->a_stream_caps);
7032                 player->a_stream_caps = NULL;
7033         }
7034
7035         if (player->s_stream_caps) {
7036                 gst_caps_unref(player->s_stream_caps);
7037                 player->s_stream_caps = NULL;
7038         }
7039         _mmplayer_track_destroy(player);
7040
7041         if (player->sink_elements)
7042                 g_list_free(player->sink_elements);
7043         player->sink_elements = NULL;
7044
7045         if (player->bufmgr) {
7046                 tbm_bufmgr_deinit(player->bufmgr);
7047                 player->bufmgr = NULL;
7048         }
7049
7050         LOGW("finished destroy pipeline\n");
7051
7052         MMPLAYER_FLEAVE();
7053
7054         return ret;
7055 }
7056
7057 static int __gst_realize(mm_player_t* player)
7058 {
7059         gint timeout = 0;
7060         int ret = MM_ERROR_NONE;
7061
7062         MMPLAYER_FENTER();
7063
7064         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7065
7066         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7067
7068         ret = __mmplayer_gst_create_pipeline(player);
7069         if (ret) {
7070                 LOGE("failed to create pipeline\n");
7071                 return ret;
7072         }
7073
7074         /* set pipeline state to READY */
7075         /* NOTE : state change to READY must be performed sync. */
7076         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7077         ret = __mmplayer_gst_set_state(player,
7078                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
7079
7080         if (ret != MM_ERROR_NONE) {
7081                 /* return error if failed to set state */
7082                 LOGE("failed to set READY state");
7083                 return ret;
7084         }
7085
7086         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
7087
7088         /* create dot before error-return. for debugging */
7089         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-realize");
7090
7091         MMPLAYER_FLEAVE();
7092
7093         return ret;
7094 }
7095
7096 static int __gst_unrealize(mm_player_t* player)
7097 {
7098         int ret = MM_ERROR_NONE;
7099
7100         MMPLAYER_FENTER();
7101
7102         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7103
7104         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
7105         MMPLAYER_PRINT_STATE(player);
7106
7107         /* release miscellaneous information */
7108         __mmplayer_release_misc(player);
7109
7110         /* destroy pipeline */
7111         ret = __mmplayer_gst_destroy_pipeline(player);
7112         if (ret != MM_ERROR_NONE) {
7113                 LOGE("failed to destory pipeline\n");
7114                 return ret;
7115         }
7116
7117         /* release miscellaneous information.
7118            these info needs to be released after pipeline is destroyed. */
7119         __mmplayer_release_misc_post(player);
7120
7121         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
7122
7123         MMPLAYER_FLEAVE();
7124
7125         return ret;
7126 }
7127
7128 static int __gst_pending_seek(mm_player_t* player)
7129 {
7130         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7131         int ret = MM_ERROR_NONE;
7132
7133         MMPLAYER_FENTER();
7134
7135         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7136
7137         if (!player->pending_seek.is_pending) {
7138                 LOGD("pending seek is not reserved. nothing to do.\n");
7139                 return ret;
7140         }
7141
7142         /* check player state if player could pending seek or not. */
7143         current_state = MMPLAYER_CURRENT_STATE(player);
7144
7145         if (current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING) {
7146                 LOGW("try to pending seek in %s state, try next time. \n",
7147                         MMPLAYER_STATE_GET_NAME(current_state));
7148                 return ret;
7149         }
7150
7151         LOGD("trying to play from(%"G_GINT64_FORMAT") pending position\n", player->pending_seek.pos);
7152
7153         ret = __gst_set_position(player, player->pending_seek.format, player->pending_seek.pos, FALSE);
7154
7155         if (MM_ERROR_NONE != ret)
7156                 LOGE("failed to seek pending postion. just keep staying current position.\n");
7157
7158         player->pending_seek.is_pending = FALSE;
7159
7160         MMPLAYER_FLEAVE();
7161
7162         return ret;
7163 }
7164
7165 static int __gst_start(mm_player_t* player)
7166 {
7167         gboolean sound_extraction = 0;
7168         int ret = MM_ERROR_NONE;
7169         gboolean async = FALSE;
7170
7171         MMPLAYER_FENTER();
7172
7173         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7174
7175         /* get sound_extraction property */
7176         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
7177
7178         /* NOTE : if SetPosition was called before Start. do it now */
7179         /* streaming doesn't support it. so it should be always sync */
7180         /* !!create one more api to check if there is pending seek rather than checking variables */
7181         if ((player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player)) {
7182                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
7183                 ret = __gst_pause(player, FALSE);
7184                 if (ret != MM_ERROR_NONE) {
7185                         LOGE("failed to set state to PAUSED for pending seek\n");
7186                         return ret;
7187                 }
7188
7189                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
7190
7191                 if (sound_extraction) {
7192                         LOGD("setting pcm extraction\n");
7193
7194                         ret = __mmplayer_set_pcm_extraction(player);
7195                         if (MM_ERROR_NONE != ret) {
7196                                 LOGW("failed to set pcm extraction\n");
7197                                 return ret;
7198                         }
7199                 } else {
7200                         if (MM_ERROR_NONE != __gst_pending_seek(player))
7201                                 LOGW("failed to seek pending postion. starting from the begin of content.\n");
7202                 }
7203         }
7204
7205         LOGD("current state before doing transition");
7206         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7207         MMPLAYER_PRINT_STATE(player);
7208
7209         /* set pipeline state to PLAYING  */
7210         if (player->es_player_push_mode)
7211                 async = TRUE;
7212         /* set pipeline state to PLAYING  */
7213         ret = __mmplayer_gst_set_state(player,
7214                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
7215
7216         if (ret == MM_ERROR_NONE) {
7217                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7218         } else {
7219                 LOGE("failed to set state to PLAYING");
7220                 return ret;
7221         }
7222
7223         /* generating debug info before returning error */
7224         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-start");
7225
7226         MMPLAYER_FLEAVE();
7227
7228         return ret;
7229 }
7230
7231 static int __gst_stop(mm_player_t* player)
7232 {
7233         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
7234         MMHandleType attrs = 0;
7235         gboolean rewind = FALSE;
7236         gint timeout = 0;
7237         int ret = MM_ERROR_NONE;
7238         gboolean async = FALSE;
7239
7240         MMPLAYER_FENTER();
7241
7242         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7243         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7244
7245         LOGD("current state before doing transition");
7246         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7247         MMPLAYER_PRINT_STATE(player);
7248
7249         attrs = MMPLAYER_GET_ATTRS(player);
7250         if (!attrs) {
7251                 LOGE("cannot get content attribute\n");
7252                 return MM_ERROR_PLAYER_INTERNAL;
7253         }
7254
7255         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
7256         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7257
7258         if ((!MMPLAYER_IS_STREAMING(player) && !MMPLAYER_IS_MS_BUFF_SRC(player)) ||
7259                 (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked))
7260                 rewind = TRUE;
7261
7262         if (player->es_player_push_mode)
7263                 async = TRUE;
7264         /* set gst state */
7265         ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, timeout);
7266
7267         /* return if set_state has failed */
7268         if (ret != MM_ERROR_NONE) {
7269                 LOGE("failed to set state.\n");
7270                 return ret;
7271         }
7272
7273         /* rewind */
7274         if (rewind) {
7275                 if (!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7276                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
7277                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
7278                         LOGW("failed to rewind\n");
7279                         ret = MM_ERROR_PLAYER_SEEK;
7280                 }
7281         }
7282
7283         /* initialize */
7284         player->sent_bos = FALSE;
7285
7286         if (player->es_player_push_mode) //for cloudgame
7287                 timeout = 0;
7288
7289         /* wait for seek to complete */
7290         change_ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
7291         if (change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL) {
7292                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
7293         } else {
7294                 LOGE("fail to stop player.\n");
7295                 ret = MM_ERROR_PLAYER_INTERNAL;
7296                 __mmplayer_dump_pipeline_state(player);
7297         }
7298
7299         /* generate dot file if enabled */
7300         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-stop");
7301
7302         MMPLAYER_FLEAVE();
7303
7304         return ret;
7305 }
7306
7307 int __gst_pause(mm_player_t* player, gboolean async)
7308 {
7309         int ret = MM_ERROR_NONE;
7310
7311         MMPLAYER_FENTER();
7312
7313         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7314         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7315
7316         LOGD("current state before doing transition");
7317         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
7318         MMPLAYER_PRINT_STATE(player);
7319
7320         /* set pipeline status to PAUSED */
7321         ret = __mmplayer_gst_set_state(player,
7322                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
7323
7324         if (FALSE == async) {
7325                 if (ret != MM_ERROR_NONE) {
7326                         GstMessage *msg = NULL;
7327                         GTimer *timer = NULL;
7328                         gdouble MAX_TIMEOUT_SEC = 3;
7329
7330                         LOGE("failed to set state to PAUSED");
7331
7332                         if (player->msg_posted) {
7333                                 LOGE("error msg is already posted.");
7334                                 return ret;
7335                         }
7336
7337                         timer = g_timer_new();
7338                         g_timer_start(timer);
7339
7340                         GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
7341
7342                         do {
7343                                 msg = gst_bus_timed_pop(bus, 100 * GST_MSECOND);
7344                                 if (msg) {
7345                                         if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
7346                                                 GError *error = NULL;
7347
7348                                                 /* parse error code */
7349                                                 gst_message_parse_error(msg, &error, NULL);
7350
7351                                                 if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
7352                                                         /* Note : the streaming error from the streaming source is handled
7353                                                          *   using __mmplayer_handle_streaming_error.
7354                                                          */
7355                                                         __mmplayer_handle_streaming_error(player, msg);
7356
7357                                                 } else if (error) {
7358                                                         LOGE("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
7359
7360                                                         if (error->domain == GST_STREAM_ERROR)
7361                                                                 ret = __gst_handle_stream_error(player, error, msg);
7362                                                         else if (error->domain == GST_RESOURCE_ERROR)
7363                                                                 ret = __gst_handle_resource_error(player, error->code, NULL);
7364                                                         else if (error->domain == GST_LIBRARY_ERROR)
7365                                                                 ret = __gst_handle_library_error(player, error->code);
7366                                                         else if (error->domain == GST_CORE_ERROR)
7367                                                                 ret = __gst_handle_core_error(player, error->code);
7368
7369                                                         g_error_free(error);
7370                                                 }
7371                                                 player->msg_posted = TRUE;
7372                                         }
7373                                         gst_message_unref(msg);
7374                                 }
7375                         } while (!player->msg_posted && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
7376                         /* clean */
7377                         gst_object_unref(bus);
7378                         g_timer_stop(timer);
7379                         g_timer_destroy(timer);
7380
7381                         return ret;
7382
7383                 } else if ((!MMPLAYER_IS_RTSP_STREAMING(player)) && (!player->video_stream_cb) &&
7384                                    (!player->pipeline->videobin) && (!player->pipeline->audiobin)) {
7385
7386                         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
7387
7388                 } else if (ret == MM_ERROR_NONE) {
7389
7390                         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
7391                 }
7392         }
7393
7394         /* generate dot file before returning error */
7395         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-pause");
7396
7397         MMPLAYER_FLEAVE();
7398
7399         return ret;
7400 }
7401
7402 int __gst_resume(mm_player_t* player, gboolean async)
7403 {
7404         int ret = MM_ERROR_NONE;
7405         gint timeout = 0;
7406
7407         MMPLAYER_FENTER();
7408
7409         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline,
7410                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7411
7412         LOGD("current state before doing transition");
7413         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7414         MMPLAYER_PRINT_STATE(player);
7415
7416         /* generate dot file before returning error */
7417         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-resume");
7418
7419         if (async)
7420                 LOGD("do async state transition to PLAYING.\n");
7421
7422         /* set pipeline state to PLAYING */
7423         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7424
7425         ret = __mmplayer_gst_set_state(player,
7426                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout);
7427         if (ret != MM_ERROR_NONE) {
7428                 LOGE("failed to set state to PLAYING\n");
7429                 return ret;
7430         } else {
7431                 if (async == FALSE) {
7432                         // MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7433                         LOGD("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
7434                         ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
7435                 }
7436         }
7437
7438         /* generate dot file before returning error */
7439         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-resume");
7440
7441         MMPLAYER_FLEAVE();
7442
7443         return ret;
7444 }
7445
7446 static int
7447 __gst_set_position(mm_player_t* player, int format, gint64 position, gboolean internal_called)
7448 {
7449         gint64 dur_nsec = 0;
7450         gint64 pos_nsec = 0;
7451         gboolean ret = TRUE;
7452         gboolean accurated = FALSE;
7453         GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
7454
7455         MMPLAYER_FENTER();
7456         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7457         MMPLAYER_RETURN_VAL_IF_FAIL(!MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP);
7458
7459         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
7460                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
7461                 goto PENDING;
7462
7463         if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
7464                 /* check duration */
7465                 /* NOTE : duration cannot be zero except live streaming.
7466                  *              Since some element could have some timing problemn with quering duration, try again.
7467                  */
7468                 if (player->duration == 0) {
7469                         if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
7470                                 /* For RTSP Streaming , duration is not returned in READY state. So seek to the previous position does not work properly.
7471                                  * Added a patch to postpone the actual seek when state changes to PLAY. Sending a fake SEEK_COMPLETED event to finish the current request. */
7472                                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) && (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
7473                                         player->pending_seek.is_pending = TRUE;
7474                                         player->pending_seek.format = format;
7475                                         player->pending_seek.pos = position;
7476                                         player->doing_seek = FALSE;
7477                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
7478                                         return MM_ERROR_NONE;
7479                                 } else {
7480                                         goto SEEK_ERROR;
7481                                 }
7482                         }
7483                         player->duration = dur_nsec;
7484                 }
7485         }
7486         LOGD("playback rate: %f\n", player->playback_rate);
7487
7488         mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
7489         if (accurated)
7490                 seek_flags |= GST_SEEK_FLAG_ACCURATE;
7491         else
7492                 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
7493
7494         /* do seek */
7495         switch (format) {
7496         case MM_PLAYER_POS_FORMAT_TIME:
7497         {
7498                 if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
7499                         GstQuery *query = NULL;
7500                         gboolean seekable = FALSE;
7501
7502                         /* check position is valid or not */
7503                         if (position > player->duration)
7504                                 goto INVALID_ARGS;
7505
7506                         query = gst_query_new_seeking(GST_FORMAT_TIME);
7507                         if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, query)) {
7508                                 gst_query_parse_seeking(query, NULL, &seekable, NULL, NULL);
7509                                 gst_query_unref(query);
7510
7511                                 if (!seekable) {
7512                                         LOGW("non-seekable content");
7513                                         player->doing_seek = FALSE;
7514                                         return MM_ERROR_PLAYER_NO_OP;
7515                                 }
7516                         } else {
7517                                 LOGW("failed to get seeking query");
7518                                 gst_query_unref(query); /* keep seeking operation */
7519                         }
7520
7521                         LOGD("seeking to(%"G_GINT64_FORMAT") nsec, duration is %"G_GINT64_FORMAT" nsec\n", position, player->duration);
7522
7523                         /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
7524                            But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
7525                            This causes problem is position calculation during normal pause resume scenarios also.
7526                            Currently during seek , we are sending the current position to rtspsrc module for position saving for later use. */
7527                         if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
7528                                 (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
7529                                 if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
7530                                         LOGW("getting current position failed in seek\n");
7531
7532                                 player->last_position = pos_nsec;
7533                                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
7534                         }
7535
7536                         if (player->doing_seek) {
7537                                 LOGD("not completed seek");
7538                                 return MM_ERROR_PLAYER_DOING_SEEK;
7539                         }
7540                 }
7541
7542                 if (!internal_called)
7543                         player->doing_seek = TRUE;
7544
7545                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked)) {
7546                         gint64 cur_time = 0;
7547
7548                         /* get current position */
7549                         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
7550
7551                         /* flush */
7552                         GstEvent *event = gst_event_new_seek(1.0,
7553                                                         GST_FORMAT_TIME,
7554                                                         (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
7555                                                         GST_SEEK_TYPE_SET, cur_time,
7556                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7557                         if (event)
7558                                 __gst_send_event_to_sink(player, event);
7559
7560                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
7561                                 __gst_pause(player, FALSE);
7562                 }
7563
7564                 pos_nsec = position;
7565
7566                 /* rtsp streaming case, there is no sink after READY TO PAUSE state(no preroll state change).
7567                         that's why set position through property. */
7568                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
7569                         (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) &&
7570                         (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY) &&
7571                         (!player->videodec_linked) && (!player->audiodec_linked)) {
7572
7573                         g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "pending-start-position", pos_nsec, NULL);
7574                         LOGD("[%s] set position =%"GST_TIME_FORMAT,
7575                                         GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), GST_TIME_ARGS(pos_nsec));
7576                         player->doing_seek = FALSE;
7577                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
7578                 } else {
7579                         ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7580                                                         GST_FORMAT_TIME, seek_flags,
7581                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7582                 }
7583
7584                 if (!ret) {
7585                         LOGE("failed to set position.");
7586                         goto SEEK_ERROR;
7587                 }
7588         }
7589         break;
7590
7591         case MM_PLAYER_POS_FORMAT_PERCENT:
7592         {
7593                 LOGD("seeking to %"G_GINT64_FORMAT"%%", position);
7594
7595                 if (player->doing_seek) {
7596                         LOGD("not completed seek");
7597                         return MM_ERROR_PLAYER_DOING_SEEK;
7598                 }
7599
7600                 if (!internal_called)
7601                         player->doing_seek = TRUE;
7602
7603                 /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
7604                 pos_nsec = (gint64)((position * player->duration) / 100);
7605                 ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7606                                                 GST_FORMAT_TIME, seek_flags,
7607                                                 GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7608                 if (!ret) {
7609                         LOGE("failed to set position. pos[%"G_GINT64_FORMAT"] dur[%"G_GINT64_FORMAT"] ", pos_nsec, player->duration);
7610                         goto SEEK_ERROR;
7611                 }
7612         }
7613         break;
7614
7615         default:
7616                 goto INVALID_ARGS;
7617         }
7618
7619         /* NOTE : store last seeking point to overcome some bad operation
7620           *     (returning zero when getting current position) of some elements
7621           */
7622         player->last_position = pos_nsec;
7623
7624         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
7625         if (player->playback_rate > 1.0)
7626                 _mmplayer_set_playspeed((MMHandleType)player, player->playback_rate, FALSE);
7627
7628         MMPLAYER_FLEAVE();
7629         return MM_ERROR_NONE;
7630
7631 PENDING:
7632         player->pending_seek.is_pending = TRUE;
7633         player->pending_seek.format = format;
7634         player->pending_seek.pos = position;
7635
7636         LOGW("player current-state : %s, pending-state : %s, just preserve pending position(%"G_GINT64_FORMAT").\n",
7637                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)),
7638                 MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)),
7639                 player->pending_seek.pos);
7640
7641         return MM_ERROR_NONE;
7642
7643 INVALID_ARGS:
7644         LOGE("invalid arguments, position: %"G_GINT64_FORMAT" dur : %"G_GINT64_FORMAT" format : %d \n", position, player->duration, format);
7645         return MM_ERROR_INVALID_ARGUMENT;
7646
7647 SEEK_ERROR:
7648         player->doing_seek = FALSE;
7649         return MM_ERROR_PLAYER_SEEK;
7650 }
7651
7652 #define TRICKPLAY_OFFSET GST_MSECOND
7653
7654 static int
7655 __gst_get_position(mm_player_t* player, int format, gint64* position)
7656 {
7657         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7658         gint64 pos_nsec = 0;
7659         gboolean ret = TRUE;
7660
7661         MMPLAYER_RETURN_VAL_IF_FAIL(player && position && player->pipeline && player->pipeline->mainbin,
7662                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7663
7664         current_state = MMPLAYER_CURRENT_STATE(player);
7665
7666         /* NOTE : query position except paused state to overcome some bad operation
7667          * please refer to below comments in details
7668          */
7669         if (current_state != MM_PLAYER_STATE_PAUSED)
7670                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec);
7671
7672         /* NOTE : get last point to overcome some bad operation of some elements
7673          *(returning zero when getting current position in paused state
7674          * and when failed to get postion during seeking
7675          */
7676         if ((current_state == MM_PLAYER_STATE_PAUSED) || (!ret)) {
7677                 LOGD("pos_nsec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_nsec), ret, current_state);
7678
7679                 if (player->playback_rate < 0.0)
7680                         pos_nsec = player->last_position - TRICKPLAY_OFFSET;
7681                 else
7682                         pos_nsec = player->last_position;
7683
7684                 if (!ret)
7685                         pos_nsec = player->last_position;
7686                 else
7687                         player->last_position = pos_nsec;
7688
7689                 LOGD("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_nsec));
7690
7691         } else {
7692                 if (player->duration > 0 && pos_nsec > player->duration)
7693                         pos_nsec = player->duration;
7694
7695                 player->last_position = pos_nsec;
7696         }
7697
7698         switch (format) {
7699         case MM_PLAYER_POS_FORMAT_TIME:
7700                 *position = pos_nsec;
7701                 break;
7702
7703         case MM_PLAYER_POS_FORMAT_PERCENT:
7704         {
7705                 if (player->duration <= 0) {
7706                         LOGD("duration is [%"G_GINT64_FORMAT"], so returning position 0\n", player->duration);
7707                         *position = 0;
7708                 } else {
7709                         LOGD("position is [%"G_GINT64_FORMAT"] nsec , duration is [%"G_GINT64_FORMAT"] nsec", pos_nsec, player->duration);
7710                         *position = (gint64)(pos_nsec * 100 / player->duration);
7711                 }
7712                 break;
7713         }
7714         default:
7715                 return MM_ERROR_PLAYER_INTERNAL;
7716         }
7717
7718         return MM_ERROR_NONE;
7719 }
7720
7721
7722 static int __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
7723 {
7724 #define STREAMING_IS_FINISHED   0
7725 #define BUFFERING_MAX_PER       100
7726 #define DEFAULT_PER_VALUE       -1
7727 #define CHECK_PERCENT_VALUE(a, min, max)(((a) > (min)) ? (((a) < (max)) ? (a) : (max)) : (min))
7728
7729         MMPlayerGstElement *mainbin = NULL;
7730         gint start_per = DEFAULT_PER_VALUE, stop_per = DEFAULT_PER_VALUE;
7731         gint64 buffered_total = 0;
7732         gint64 position = 0;
7733         gint buffered_sec = -1;
7734         GstBufferingMode mode = GST_BUFFERING_STREAM;
7735         gint64 content_size_time = player->duration;
7736         guint64 content_size_bytes = player->http_content_size;
7737
7738         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
7739                                                 player->pipeline &&
7740                                                 player->pipeline->mainbin,
7741                                                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7742
7743         MMPLAYER_RETURN_VAL_IF_FAIL(start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT);
7744
7745         *start_pos = 0;
7746         *stop_pos = 0;
7747
7748         if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
7749                 /* and rtsp is not ready yet. */
7750                 LOGW("it's only used for http streaming case.\n");
7751                 return MM_ERROR_PLAYER_NO_OP;
7752         }
7753
7754         if (format != MM_PLAYER_POS_FORMAT_PERCENT) {
7755                 LOGW("Time format is not supported yet.\n");
7756                 return MM_ERROR_INVALID_ARGUMENT;
7757         }
7758
7759         if (content_size_time <= 0 || content_size_bytes <= 0) {
7760                 LOGW("there is no content size.");
7761                 return MM_ERROR_NONE;
7762         }
7763
7764         if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position) != MM_ERROR_NONE) {
7765                 LOGW("fail to get current position.");
7766                 return MM_ERROR_NONE;
7767         }
7768
7769         LOGD("pos %"G_GINT64_FORMAT" msec, dur %d sec, len %"G_GUINT64_FORMAT" bytes",
7770                 GST_TIME_AS_MSECONDS(position), (guint)GST_TIME_AS_SECONDS(content_size_time), content_size_bytes);
7771
7772         mainbin = player->pipeline->mainbin;
7773         start_per = (gint)(floor(100 *(gdouble)position / (gdouble)content_size_time));
7774
7775         if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
7776                 GstQuery *query = NULL;
7777                 gint byte_in_rate = 0, byte_out_rate = 0;
7778                 gint64 estimated_total = 0;
7779
7780                 query = gst_query_new_buffering(GST_FORMAT_BYTES);
7781                 if (!query || !gst_element_query(mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query)) {
7782                         LOGW("fail to get buffering query from queue2");
7783                         if (query)
7784                                 gst_query_unref(query);
7785                         return MM_ERROR_NONE;
7786                 }
7787
7788                 gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, NULL);
7789                 LOGD("mode %d, in_rate %d, out_rate %d", mode, byte_in_rate, byte_out_rate);
7790
7791                 if (mode == GST_BUFFERING_STREAM) {
7792                         /* using only queue in case of push mode(ts / mp3) */
7793                         if (gst_element_query_position(mainbin[MMPLAYER_M_SRC].gst,
7794                                 GST_FORMAT_BYTES, &buffered_total)) {
7795                                 LOGD("buffered_total %"G_GINT64_FORMAT, buffered_total);
7796                                 stop_per = 100 * buffered_total / content_size_bytes;
7797                         }
7798                 } else {
7799                         /* GST_BUFFERING_TIMESHIFT or GST_BUFFERING_DOWNLOAD */
7800                         guint idx = 0;
7801                         guint num_of_ranges = 0;
7802                         gint64 start_byte = 0, stop_byte = 0;
7803
7804                         gst_query_parse_buffering_range(query, NULL, NULL, NULL, &estimated_total);
7805                         if (estimated_total != STREAMING_IS_FINISHED) {
7806                                 /* buffered size info from queue2 */
7807                                 num_of_ranges = gst_query_get_n_buffering_ranges(query);
7808                                 for (idx = 0; idx < num_of_ranges; idx++) {
7809                                         gst_query_parse_nth_buffering_range(query, idx, &start_byte, &stop_byte);
7810                                         LOGD("range %d, %"G_GINT64_FORMAT" ~ %"G_GUINT64_FORMAT, idx, start_byte, stop_byte);
7811
7812                                         buffered_total += (stop_byte - start_byte);
7813                                 }
7814                         } else
7815                                 stop_per = BUFFERING_MAX_PER;
7816                 }
7817                 gst_query_unref(query);
7818         }
7819
7820         if (stop_per == DEFAULT_PER_VALUE) {
7821                 guint dur_sec = (guint)(content_size_time/GST_SECOND);
7822                 if (dur_sec > 0) {
7823                         guint avg_byterate = (guint)(content_size_bytes/dur_sec);
7824
7825                         /* buffered size info from multiqueue */
7826                         if (mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) {
7827                                 guint curr_size_bytes = 0;
7828                                 g_object_get(G_OBJECT(mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst),
7829                                         "curr-size-bytes", &curr_size_bytes, NULL);
7830                                 LOGD("curr_size_bytes of multiqueue = %d", curr_size_bytes);
7831                                 buffered_total += curr_size_bytes;
7832                         }
7833
7834                         if (avg_byterate > 0)
7835                                 buffered_sec = (gint)(ceil((gdouble)buffered_total/(gdouble)avg_byterate));
7836                         else if (player->total_maximum_bitrate > 0)
7837                                 buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total)/(gdouble)player->total_maximum_bitrate));
7838                         else if (player->total_bitrate > 0)
7839                                 buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total)/(gdouble)player->total_bitrate));
7840
7841                         if (buffered_sec >= 0)
7842                                 stop_per = start_per +(gint)(ceil)(100*(gdouble)buffered_sec/(gdouble)dur_sec);
7843                 }
7844         }
7845
7846         *start_pos = CHECK_PERCENT_VALUE(start_per, 0, 100);
7847         *stop_pos = CHECK_PERCENT_VALUE(stop_per, *start_pos, 100);
7848
7849         LOGD("buffered info: %"G_GINT64_FORMAT" bytes, %d sec, per %lu~%lu\n",
7850                 buffered_total, buffered_sec, *start_pos, *stop_pos);
7851
7852         return MM_ERROR_NONE;
7853 }
7854
7855 static int
7856 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param)
7857 {
7858         MMPLAYER_FENTER();
7859
7860         if (!player) {
7861                 LOGW("set_message_callback is called with invalid player handle\n");
7862                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
7863         }
7864
7865         player->msg_cb = callback;
7866         player->msg_cb_param = user_param;
7867
7868         LOGD("msg_cb : %p     msg_cb_param : %p\n", callback, user_param);
7869
7870         MMPLAYER_FLEAVE();
7871
7872         return MM_ERROR_NONE;
7873 }
7874
7875 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data)
7876 {
7877         int ret = MM_ERROR_PLAYER_INVALID_URI;
7878         char *path = NULL;
7879
7880         MMPLAYER_FENTER();
7881
7882         MMPLAYER_RETURN_VAL_IF_FAIL(uri , FALSE);
7883         MMPLAYER_RETURN_VAL_IF_FAIL(data , FALSE);
7884         MMPLAYER_RETURN_VAL_IF_FAIL((strlen(uri) <= MM_MAX_URL_LEN), FALSE);
7885
7886         memset(data, 0, sizeof(MMPlayerParseProfile));
7887
7888         if ((path = strstr(uri, "es_buff://"))) {
7889                 if (strlen(path)) {
7890                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7891                         data->uri_type = MM_PLAYER_URI_TYPE_MS_BUFF;
7892                         ret = MM_ERROR_NONE;
7893                 }
7894         } else if ((path = strstr(uri, "rtsp://")) || (path = strstr(uri, "rtsps://"))) {
7895                 if (strlen(path)) {
7896                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7897                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7898                         ret = MM_ERROR_NONE;
7899                 }
7900         } else if ((path = strstr(uri, "http://")) || (path = strstr(uri, "https://"))) {
7901                 if (strlen(path)) {
7902                         gchar *tmp = NULL;
7903                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7904                         tmp = g_ascii_strdown(uri, strlen(uri));
7905
7906                         if (tmp && (g_str_has_suffix(tmp, ".ism/manifest") || g_str_has_suffix(tmp, ".isml/manifest")))
7907                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
7908                         else
7909                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
7910
7911                         ret = MM_ERROR_NONE;
7912                         g_free(tmp);
7913                 }
7914         } else if ((path = strstr(uri, "rtspu://"))) {
7915                 if (strlen(path)) {
7916                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7917                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7918                         ret = MM_ERROR_NONE;
7919                 }
7920         } else if ((path = strstr(uri, "rtspr://"))) {
7921                 strncpy(data->uri, path, MM_MAX_URL_LEN-1);
7922                 char *separater = strstr(path, "*");
7923
7924                 if (separater) {
7925                         int urgent_len = 0;
7926                         char *urgent = separater + strlen("*");
7927
7928                         if ((urgent_len = strlen(urgent))) {
7929                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
7930                                 strncpy(data->urgent, urgent, MM_MAX_FILENAME_LEN-1);
7931                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7932                                 ret = MM_ERROR_NONE;
7933                         }
7934                 }
7935         } else if ((path = strstr(uri, "mms://"))) {
7936                 if (strlen(path)) {
7937                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7938                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
7939                         ret = MM_ERROR_NONE;
7940                 }
7941         } else if ((path = strstr(uri, "mem://"))) {
7942                 if (strlen(path)) {
7943                         int mem_size = 0;
7944                         char *buffer = NULL;
7945                         char *seperator = strchr(path, ',');
7946                         char ext[100] = {0,}, size[100] = {0,};
7947
7948                         if (seperator) {
7949                                 if ((buffer = strstr(path, "ext="))) {
7950                                         buffer += strlen("ext=");
7951
7952                                         if (strlen(buffer)) {
7953                                                 strncpy(ext, buffer, 99);
7954
7955                                                 if ((seperator = strchr(ext, ','))
7956                                                         || (seperator = strchr(ext, ' '))
7957                                                         || (seperator = strchr(ext, '\0'))) {
7958                                                         seperator[0] = '\0';
7959                                                 }
7960                                         }
7961                                 }
7962
7963                                 if ((buffer = strstr(path, "size="))) {
7964                                         buffer += strlen("size=");
7965
7966                                         if (strlen(buffer) > 0) {
7967                                                 strncpy(size, buffer, 99);
7968
7969                                                 if ((seperator = strchr(size, ','))
7970                                                         || (seperator = strchr(size, ' '))
7971                                                         || (seperator = strchr(size, '\0'))) {
7972                                                         seperator[0] = '\0';
7973                                                 }
7974
7975                                                 mem_size = atoi(size);
7976                                         }
7977                                 }
7978                         }
7979
7980                         LOGD("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
7981                         if (mem_size && param) {
7982                                 if (data->input_mem.buf)
7983                                         free(data->input_mem.buf);
7984                                 data->input_mem.buf = malloc(mem_size);
7985
7986                                 if (data->input_mem.buf) {
7987                                         memcpy(data->input_mem.buf, param, mem_size);
7988                                         data->input_mem.len = mem_size;
7989                                         ret = MM_ERROR_NONE;
7990                                 } else {
7991                                         LOGE("failed to alloc mem %d", mem_size);
7992                                         ret = MM_ERROR_PLAYER_INTERNAL;
7993                                 }
7994
7995                                 data->input_mem.offset = 0;
7996                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
7997                         }
7998                 }
7999         } else {
8000                 gchar *location = NULL;
8001                 GError *err = NULL;
8002
8003                 if ((path = strstr(uri, "file://"))) {
8004
8005                         location = g_filename_from_uri(uri, NULL, &err);
8006
8007                         if (!location || (err != NULL)) {
8008                           LOGE("Invalid URI '%s' for filesrc: %s", path,
8009                                  (err != NULL) ? err->message : "unknown error");
8010
8011                           if (err) g_error_free(err);
8012                           if (location) g_free(location);
8013
8014                           data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8015                           goto exit;
8016                         }
8017
8018                         LOGD("path from uri: %s", location);
8019                 }
8020
8021                 path = (location != NULL) ? (location) : ((char*)uri);
8022                 int file_stat = MM_ERROR_NONE;
8023
8024                 file_stat = util_exist_file_path(path);
8025
8026                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
8027                 if (file_stat == MM_ERROR_NONE) {
8028                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", path);
8029
8030                         if (util_is_sdp_file(path)) {
8031                                 LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8032                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8033                         } else {
8034                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8035                         }
8036                         ret = MM_ERROR_NONE;
8037                 } else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED) {
8038                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8039                 } else {
8040                         LOGE("invalid uri, could not play..\n");
8041                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8042                 }
8043
8044                 if (location) g_free(location);
8045         }
8046
8047 exit:
8048         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE)
8049                 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
8050         else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION)
8051                 ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
8052
8053         /* dump parse result */
8054         SECURE_LOGW("incomming uri : %s\n", uri);
8055         LOGD("uri_type : %d, mem : %p, mem_size : %d, urgent : %s\n",
8056                 data->uri_type, data->input_mem.buf, data->input_mem.len, data->urgent);
8057
8058         MMPLAYER_FLEAVE();
8059
8060         return ret;
8061 }
8062
8063 gboolean
8064 __mmplayer_can_do_interrupt(mm_player_t *player)
8065 {
8066         if (!player || !player->pipeline || !player->attrs) {
8067                 LOGW("not initialized");
8068                 goto FAILED;
8069         }
8070
8071         if (player->set_mode.pcm_extraction) {
8072                 LOGW("leave right now, %d", player->set_mode.pcm_extraction);
8073                 goto FAILED;
8074         }
8075
8076         /* check if seeking */
8077         if (player->doing_seek) {
8078                 MMMessageParamType msg_param;
8079                 memset(&msg_param, 0, sizeof(MMMessageParamType));
8080                 msg_param.code = MM_ERROR_PLAYER_SEEK;
8081                 player->doing_seek = FALSE;
8082                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
8083                 goto FAILED;
8084         }
8085
8086         /* check other thread */
8087         if (!MMPLAYER_CMD_TRYLOCK(player)) {
8088                 LOGW("locked already, cmd state : %d", player->cmd);
8089
8090                 /* check application command */
8091                 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) {
8092                         LOGW("playing.. should wait cmd lock then, will be interrupted");
8093
8094                         /* lock will be released at mrp_resource_release_cb() */
8095                         MMPLAYER_CMD_LOCK(player);
8096                         goto INTERRUPT;
8097                 }
8098                 LOGW("nothing to do");
8099                 goto FAILED;
8100         } else {
8101                 LOGW("can interrupt immediately");
8102                 goto INTERRUPT;
8103         }
8104
8105 FAILED:    /* with CMD UNLOCKED */
8106         return FALSE;
8107
8108 INTERRUPT: /* with CMD LOCKED, released at mrp_resource_release_cb() */
8109         return TRUE;
8110 }
8111
8112 static int
8113 __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res,
8114                 void *user_data)
8115 {
8116         mm_player_t *player = NULL;
8117
8118         MMPLAYER_FENTER();
8119
8120         if (user_data == NULL) {
8121                 LOGE("- user_data is null\n");
8122                 return FALSE;
8123         }
8124         player = (mm_player_t *)user_data;
8125
8126         /* do something to release resource here.
8127          * player stop and interrupt forwarding */
8128         if (!__mmplayer_can_do_interrupt(player)) {
8129                 LOGW("no need to interrupt, so leave");
8130         } else {
8131                 MMMessageParamType msg = {0, };
8132                 gint64 pos = 0;
8133
8134                 player->interrupted_by_resource = TRUE;
8135
8136                 /* get last play position */
8137                 if (_mmplayer_get_position((MMHandleType)player, MM_PLAYER_POS_FORMAT_TIME, &pos) != MM_ERROR_NONE) {
8138                         LOGW("failed to get play position.");
8139                 } else {
8140                         msg.union_type = MM_MSG_UNION_TIME;
8141                         msg.time.elapsed = pos;
8142                         MMPLAYER_POST_MSG(player, MM_MESSAGE_PLAY_POSITION, &msg);
8143                 }
8144                 LOGD("video resource conflict so, resource will be freed by unrealizing");
8145                 if (_mmplayer_unrealize((MMHandleType)player))
8146                         LOGW("failed to unrealize");
8147
8148                 /* lock is called in __mmplayer_can_do_interrupt() */
8149                 MMPLAYER_CMD_UNLOCK(player);
8150         }
8151
8152         if (res == player->video_overlay_resource)
8153                 player->video_overlay_resource = FALSE;
8154         else
8155                 player->video_decoder_resource = FALSE;
8156
8157         MMPLAYER_FLEAVE();
8158
8159         return FALSE;
8160 }
8161
8162 int
8163 _mmplayer_create_player(MMHandleType handle)
8164 {
8165         int ret = MM_ERROR_PLAYER_INTERNAL;
8166         bool enabled = false;
8167
8168         mm_player_t* player = MM_PLAYER_CAST(handle);
8169
8170         MMPLAYER_FENTER();
8171
8172         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8173
8174         /* initialize player state */
8175         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
8176         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
8177         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
8178         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
8179
8180         /* check current state */
8181         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_CREATE);
8182
8183         /* construct attributes */
8184         player->attrs = _mmplayer_construct_attribute(handle);
8185
8186         if (!player->attrs) {
8187                 LOGE("Failed to construct attributes\n");
8188                 return ret;
8189         }
8190
8191         /* initialize gstreamer with configured parameter */
8192         if (!__mmplayer_init_gstreamer(player)) {
8193                 LOGE("Initializing gstreamer failed\n");
8194                 _mmplayer_deconstruct_attribute(handle);
8195                 return ret;
8196         }
8197
8198         /* create lock. note that g_tread_init() has already called in gst_init() */
8199         g_mutex_init(&player->fsink_lock);
8200
8201         /* create update tag lock */
8202         g_mutex_init(&player->update_tag_lock);
8203
8204         /* create next play mutex */
8205         g_mutex_init(&player->next_play_thread_mutex);
8206
8207         /* create next play cond */
8208         g_cond_init(&player->next_play_thread_cond);
8209
8210         /* create next play thread */
8211         player->next_play_thread =
8212                 g_thread_try_new("next_play_thread", __mmplayer_next_play_thread, (gpointer)player, NULL);
8213         if (!player->next_play_thread) {
8214                 LOGE("failed to create next play thread");
8215                 ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
8216                 g_mutex_clear(&player->next_play_thread_mutex);
8217                 g_cond_clear(&player->next_play_thread_cond);
8218                 goto ERROR;
8219         }
8220
8221         player->bus_msg_q = g_queue_new();
8222         if (!player->bus_msg_q) {
8223                 LOGE("failed to create queue for bus_msg");
8224                 ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
8225                 goto ERROR;
8226         }
8227
8228         ret = _mmplayer_initialize_video_capture(player);
8229         if (ret != MM_ERROR_NONE) {
8230                 LOGE("failed to initialize video capture\n");
8231                 goto ERROR;
8232         }
8233
8234         /* initialize resource manager */
8235         if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_create(
8236                         MM_RESOURCE_MANAGER_APP_CLASS_MEDIA, __resource_release_cb, player,
8237                         &player->resource_manager)) {
8238                 LOGE("failed to initialize resource manager\n");
8239                 goto ERROR;
8240         }
8241
8242         if (MMPLAYER_IS_HTTP_PD(player)) {
8243                 player->pd_downloader = NULL;
8244                 player->pd_file_save_path = NULL;
8245         }
8246
8247         /* create video bo lock and cond */
8248         g_mutex_init(&player->video_bo_mutex);
8249         g_cond_init(&player->video_bo_cond);
8250
8251         /* create media stream callback mutex */
8252         g_mutex_init(&player->media_stream_cb_lock);
8253
8254         /* create subtitle info lock and cond */
8255         g_mutex_init(&player->subtitle_info_mutex);
8256         g_cond_init(&player->subtitle_info_cond);
8257
8258         player->streaming_type = STREAMING_SERVICE_NONE;
8259
8260         /* give default value of audio effect setting */
8261         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
8262         player->sound.rg_enable = false;
8263         player->playback_rate = DEFAULT_PLAYBACK_RATE;
8264
8265         player->play_subtitle = FALSE;
8266         player->use_deinterleave = FALSE;
8267         player->max_audio_channels = 0;
8268         player->video_share_api_delta = 0;
8269         player->video_share_clock_delta = 0;
8270         player->has_closed_caption = FALSE;
8271         player->video_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
8272         player->video_extra_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
8273         player->pending_resume = FALSE;
8274         if (player->ini.dump_element_keyword[0][0] == '\0')
8275                 player->ini.set_dump_element_flag = FALSE;
8276         else
8277                 player->ini.set_dump_element_flag = TRUE;
8278
8279         player->adaptive_info.limit.bandwidth = ADAPTIVE_VARIANT_DEFAULT_VALUE;
8280         player->adaptive_info.limit.width = ADAPTIVE_VARIANT_DEFAULT_VALUE;
8281         player->adaptive_info.limit.height = ADAPTIVE_VARIANT_DEFAULT_VALUE;
8282
8283         /* Set video360 settings to their defaults for just-created player.
8284          * */
8285
8286         player->is_360_feature_enabled = FALSE;
8287         if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(FEATURE_NAME_SPHERICAL_VIDEO, &enabled)) {
8288                 LOGI("spherical feature info: %d", enabled);
8289                 if (enabled)
8290                         player->is_360_feature_enabled = TRUE;
8291         } else {
8292                 LOGE("failed to get spherical feature info");
8293         }
8294
8295         player->is_content_spherical = FALSE;
8296         player->is_video360_enabled = TRUE;
8297         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
8298         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
8299         player->video360_yaw_radians = PLAYER_SPHERICAL_DEFAULT_YAW;
8300         player->video360_pitch_radians = PLAYER_SPHERICAL_DEFAULT_PITCH;
8301         player->video360_zoom = 1.0f;
8302         player->video360_horizontal_fov = PLAYER_SPHERICAL_DEFAULT_H_FOV;
8303         player->video360_vertical_fov = PLAYER_SPHERICAL_DEFAULT_V_FOV;
8304
8305         /* set player state to null */
8306         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
8307         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
8308
8309         return MM_ERROR_NONE;
8310
8311 ERROR:
8312         /* free lock */
8313         g_mutex_clear(&player->fsink_lock);
8314
8315         /* free update tag lock */
8316         g_mutex_clear(&player->update_tag_lock);
8317
8318         g_queue_free(player->bus_msg_q);
8319
8320         /* free next play thread */
8321         if (player->next_play_thread) {
8322                 MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
8323                 player->next_play_thread_exit = TRUE;
8324                 MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
8325                 MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
8326
8327                 g_thread_join(player->next_play_thread);
8328                 player->next_play_thread = NULL;
8329
8330                 g_mutex_clear(&player->next_play_thread_mutex);
8331                 g_cond_clear(&player->next_play_thread_cond);
8332         }
8333
8334         /* release attributes */
8335         _mmplayer_deconstruct_attribute(handle);
8336
8337         MMPLAYER_FLEAVE();
8338
8339         return ret;
8340 }
8341
8342 static gboolean
8343 __mmplayer_init_gstreamer(mm_player_t* player)
8344 {
8345         static gboolean initialized = FALSE;
8346         static const int max_argc = 50;
8347         gint* argc = NULL;
8348         gchar** argv = NULL;
8349         gchar** argv2 = NULL;
8350         GError *err = NULL;
8351         int i = 0;
8352         int arg_count = 0;
8353
8354         if (initialized) {
8355                 LOGD("gstreamer already initialized.\n");
8356                 return TRUE;
8357         }
8358
8359         /* alloc */
8360         argc = malloc(sizeof(int));
8361         argv = malloc(sizeof(gchar*) * max_argc);
8362         argv2 = malloc(sizeof(gchar*) * max_argc);
8363
8364         if (!argc || !argv || !argv2)
8365                 goto ERROR;
8366
8367         memset(argv, 0, sizeof(gchar*) * max_argc);
8368         memset(argv2, 0, sizeof(gchar*) * max_argc);
8369
8370         /* add initial */
8371         *argc = 1;
8372         argv[0] = g_strdup("mmplayer");
8373
8374         /* add gst_param */
8375         for (i = 0; i < 5; i++) {
8376                 /* FIXIT : num of param is now fixed to 5. make it dynamic */
8377                 if (strlen(player->ini.gst_param[i]) > 0) {
8378                         argv[*argc] = g_strdup(player->ini.gst_param[i]);
8379                         (*argc)++;
8380                 }
8381         }
8382
8383         /* we would not do fork for scanning plugins */
8384         argv[*argc] = g_strdup("--gst-disable-registry-fork");
8385         (*argc)++;
8386
8387         /* check disable registry scan */
8388         if (player->ini.skip_rescan) {
8389                 argv[*argc] = g_strdup("--gst-disable-registry-update");
8390                 (*argc)++;
8391         }
8392
8393         /* check disable segtrap */
8394         if (player->ini.disable_segtrap) {
8395                 argv[*argc] = g_strdup("--gst-disable-segtrap");
8396                 (*argc)++;
8397         }
8398
8399         LOGD("initializing gstreamer with following parameter\n");
8400         LOGD("argc : %d\n", *argc);
8401         arg_count = *argc;
8402
8403         for (i = 0; i < arg_count; i++) {
8404                 argv2[i] = argv[i];
8405                 LOGD("argv[%d] : %s\n", i, argv2[i]);
8406         }
8407
8408         /* initializing gstreamer */
8409         if (!gst_init_check(argc, &argv, &err)) {
8410                 LOGE("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
8411                 if (err)
8412                         g_error_free(err);
8413
8414                 goto ERROR;
8415         }
8416         /* release */
8417         for (i = 0; i < arg_count; i++) {
8418                 //LOGD("release - argv[%d] : %s\n", i, argv2[i]);
8419                 MMPLAYER_FREEIF(argv2[i]);
8420         }
8421
8422         MMPLAYER_FREEIF(argv);
8423         MMPLAYER_FREEIF(argv2);
8424         MMPLAYER_FREEIF(argc);
8425
8426         /* done */
8427         initialized = TRUE;
8428
8429         return TRUE;
8430
8431 ERROR:
8432
8433         /* release */
8434         for (i = 0; i < arg_count; i++) {
8435                 LOGD("free[%d] : %s\n", i, argv2[i]);
8436                 MMPLAYER_FREEIF(argv2[i]);
8437         }
8438
8439         MMPLAYER_FREEIF(argv);
8440         MMPLAYER_FREEIF(argv2);
8441         MMPLAYER_FREEIF(argc);
8442
8443         return FALSE;
8444 }
8445
8446 int
8447 __mmplayer_destroy_streaming_ext(mm_player_t* player)
8448 {
8449         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8450
8451         if (player->pd_downloader || MMPLAYER_IS_HTTP_PD(player)) {
8452                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
8453                 MMPLAYER_FREEIF(player->pd_file_save_path);
8454         }
8455
8456         return MM_ERROR_NONE;
8457 }
8458
8459 static void
8460 __mmplayer_check_async_state_transition(mm_player_t* player)
8461 {
8462         GstState element_state = GST_STATE_VOID_PENDING;
8463         GstState element_pending_state = GST_STATE_VOID_PENDING;
8464         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
8465         GstElement * element = NULL;
8466         gboolean async = FALSE;
8467
8468         /* check player handle */
8469         MMPLAYER_RETURN_IF_FAIL(player &&
8470                                                 player->pipeline &&
8471                                                 player->pipeline->mainbin &&
8472                                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
8473
8474         if (player->attrs)
8475                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
8476
8477         if (!MMPLAYER_IS_MS_BUFF_SRC(player) && (async == FALSE)) {
8478                 LOGD("don't need to check the pipeline state");
8479                 return;
8480         }
8481
8482         MMPLAYER_PRINT_STATE(player);
8483
8484         /* wait for state transition */
8485         element = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
8486         ret = gst_element_get_state(element, &element_state, &element_pending_state, 1*GST_SECOND);
8487
8488         if (ret == GST_STATE_CHANGE_FAILURE) {
8489                 LOGE(" [%s] state : %s   pending : %s \n",
8490                         GST_ELEMENT_NAME(element),
8491                         gst_element_state_get_name(element_state),
8492                         gst_element_state_get_name(element_pending_state));
8493
8494                 /* dump state of all element */
8495                 __mmplayer_dump_pipeline_state(player);
8496
8497                 return;
8498         }
8499
8500         LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
8501         return;
8502 }
8503
8504 int
8505 _mmplayer_destroy(MMHandleType handle)
8506 {
8507         mm_player_t* player = MM_PLAYER_CAST(handle);
8508
8509         MMPLAYER_FENTER();
8510
8511         /* check player handle */
8512         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8513
8514         /* destroy can called at anytime */
8515         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_DESTROY);
8516
8517         /* check async state transition */
8518         __mmplayer_check_async_state_transition(player);
8519
8520         __mmplayer_destroy_streaming_ext(player);
8521
8522         /* release next play thread */
8523         if (player->next_play_thread) {
8524                 MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
8525                 player->next_play_thread_exit = TRUE;
8526                 MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
8527                 MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
8528
8529                 LOGD("waitting for next play thread exit\n");
8530                 g_thread_join(player->next_play_thread);
8531                 g_mutex_clear(&player->next_play_thread_mutex);
8532                 g_cond_clear(&player->next_play_thread_cond);
8533                 LOGD("next play thread released\n");
8534         }
8535
8536         _mmplayer_release_video_capture(player);
8537
8538         /* de-initialize resource manager */
8539         if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_destroy(
8540                         player->resource_manager))
8541                 LOGE("failed to deinitialize resource manager\n");
8542
8543         /* release pipeline */
8544         if (MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline(player)) {
8545                 LOGE("failed to destory pipeline\n");
8546                 return MM_ERROR_PLAYER_INTERNAL;
8547         }
8548
8549         g_queue_free(player->bus_msg_q);
8550
8551         /* release subtitle info lock and cond */
8552         g_mutex_clear(&player->subtitle_info_mutex);
8553         g_cond_clear(&player->subtitle_info_cond);
8554
8555         __mmplayer_release_dump_list(player->dump_list);
8556
8557         /* release miscellaneous information */
8558         __mmplayer_release_misc(player);
8559
8560         /* release miscellaneous information.
8561            these info needs to be released after pipeline is destroyed. */
8562         __mmplayer_release_misc_post(player);
8563
8564         /* release attributes */
8565         _mmplayer_deconstruct_attribute(handle);
8566
8567         /* release lock */
8568         g_mutex_clear(&player->fsink_lock);
8569
8570         /* release lock */
8571         g_mutex_clear(&player->update_tag_lock);
8572
8573         /* release video bo lock and cond */
8574         g_mutex_clear(&player->video_bo_mutex);
8575         g_cond_clear(&player->video_bo_cond);
8576
8577         /* release media stream callback lock */
8578         g_mutex_clear(&player->media_stream_cb_lock);
8579
8580         MMPLAYER_FLEAVE();
8581
8582         return MM_ERROR_NONE;
8583 }
8584
8585 int
8586 __mmplayer_realize_streaming_ext(mm_player_t* player)
8587 {
8588         int ret = MM_ERROR_NONE;
8589
8590         MMPLAYER_FENTER();
8591         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8592
8593         if (MMPLAYER_IS_HTTP_PD(player)) {
8594                 gboolean bret = FALSE;
8595
8596                 player->pd_downloader = _mmplayer_create_pd_downloader();
8597                 if (!player->pd_downloader) {
8598                         LOGE("Unable to create PD Downloader...");
8599                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
8600                 }
8601
8602                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
8603
8604                 if (FALSE == bret) {
8605                         LOGE("Unable to create PD Downloader...");
8606                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
8607                 }
8608         }
8609
8610         MMPLAYER_FLEAVE();
8611         return ret;
8612 }
8613
8614 int
8615 _mmplayer_realize(MMHandleType hplayer)
8616 {
8617         mm_player_t* player = (mm_player_t*)hplayer;
8618         char *uri = NULL;
8619         void *param = NULL;
8620         MMHandleType attrs = 0;
8621         int ret = MM_ERROR_NONE;
8622
8623         MMPLAYER_FENTER();
8624
8625         /* check player handle */
8626         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED)
8627
8628         /* check current state */
8629         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_REALIZE);
8630
8631         attrs = MMPLAYER_GET_ATTRS(player);
8632         if (!attrs) {
8633                 LOGE("fail to get attributes.\n");
8634                 return MM_ERROR_PLAYER_INTERNAL;
8635         }
8636         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
8637         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
8638
8639         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_NONE) {
8640                 ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
8641
8642                 if (ret != MM_ERROR_NONE) {
8643                         LOGE("failed to parse profile\n");
8644                         return ret;
8645                 }
8646         }
8647
8648         if (uri && (strstr(uri, "es_buff://"))) {
8649                 if (strstr(uri, "es_buff://push_mode"))
8650                         player->es_player_push_mode = TRUE;
8651                 else
8652                         player->es_player_push_mode = FALSE;
8653         }
8654
8655         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS) {
8656                 LOGW("mms protocol is not supported format.\n");
8657                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
8658         }
8659
8660         if (MMPLAYER_IS_STREAMING(player))
8661                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
8662         else
8663                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
8664
8665         player->smooth_streaming = FALSE;
8666         player->videodec_linked  = 0;
8667         player->videosink_linked = 0;
8668         player->audiodec_linked  = 0;
8669         player->audiosink_linked = 0;
8670         player->textsink_linked = 0;
8671         player->is_external_subtitle_present = FALSE;
8672         player->is_external_subtitle_added_now = FALSE;
8673         /* set the subtitle ON default */
8674         player->is_subtitle_off = FALSE;
8675
8676         /* realize pipeline */
8677         ret = __gst_realize(player);
8678         if (ret != MM_ERROR_NONE)
8679                 LOGE("fail to realize the player.\n");
8680         else
8681                 ret = __mmplayer_realize_streaming_ext(player);
8682
8683         player->bus_msg_timeout = PLAYER_BUS_MSG_PREPARE_TIMEOUT;
8684         MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
8685
8686         MMPLAYER_FLEAVE();
8687
8688         return ret;
8689 }
8690
8691 int
8692 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
8693 {
8694         MMPLAYER_FENTER();
8695         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8696
8697         /* destroy can called at anytime */
8698         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
8699                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
8700
8701         MMPLAYER_FLEAVE();
8702         return MM_ERROR_NONE;
8703 }
8704
8705 int
8706 _mmplayer_unrealize(MMHandleType hplayer)
8707 {
8708         mm_player_t* player = (mm_player_t*)hplayer;
8709         int ret = MM_ERROR_NONE;
8710
8711         MMPLAYER_FENTER();
8712
8713         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8714
8715         MMPLAYER_CMD_UNLOCK(player);
8716         /* destroy the gst bus msg thread which is created during realize.
8717            this funct have to be called before getting cmd lock. */
8718         _mmplayer_bus_msg_thread_destroy(player);
8719         MMPLAYER_CMD_LOCK(player);
8720
8721         /* check current state */
8722         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_UNREALIZE);
8723
8724         /* check async state transition */
8725         __mmplayer_check_async_state_transition(player);
8726
8727         __mmplayer_unrealize_streaming_ext(player);
8728
8729         /* unrealize pipeline */
8730         ret = __gst_unrealize(player);
8731
8732         /* set asm stop if success */
8733         if (MM_ERROR_NONE == ret) {
8734                 if (!player->interrupted_by_resource) {
8735                         if (player->video_decoder_resource != NULL) {
8736                                 ret = mm_resource_manager_mark_for_release(player->resource_manager,
8737                                                 player->video_decoder_resource);
8738                                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
8739                                         LOGE("failed to mark decoder resource for release, ret(0x%x)\n", ret);
8740                                 else
8741                                         player->video_decoder_resource = NULL;
8742                         }
8743
8744                         if (player->video_overlay_resource != NULL) {
8745                                 ret = mm_resource_manager_mark_for_release(player->resource_manager,
8746                                                 player->video_overlay_resource);
8747                                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
8748                                         LOGE("failed to mark overlay resource for release, ret(0x%x)\n", ret);
8749                                 else
8750                                         player->video_overlay_resource = NULL;
8751                         }
8752
8753                         ret = mm_resource_manager_commit(player->resource_manager);
8754                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
8755                                 LOGE("failed to commit resource releases, ret(0x%x)\n", ret);
8756                 }
8757         } else
8758                 LOGE("failed and don't change asm state to stop");
8759
8760         MMPLAYER_FLEAVE();
8761
8762         return ret;
8763 }
8764
8765 int
8766 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param)
8767 {
8768         mm_player_t* player = (mm_player_t*)hplayer;
8769
8770         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8771
8772         return __gst_set_message_callback(player, callback, user_param);
8773 }
8774
8775 int
8776 _mmplayer_get_state(MMHandleType hplayer, int* state)
8777 {
8778         mm_player_t *player = (mm_player_t*)hplayer;
8779
8780         MMPLAYER_RETURN_VAL_IF_FAIL(state, MM_ERROR_INVALID_ARGUMENT);
8781
8782         *state = MMPLAYER_CURRENT_STATE(player);
8783
8784         return MM_ERROR_NONE;
8785 }
8786
8787
8788 int
8789 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume)
8790 {
8791         mm_player_t* player = (mm_player_t*) hplayer;
8792         GstElement* vol_element = NULL;
8793         int i = 0;
8794
8795         MMPLAYER_FENTER();
8796
8797         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8798
8799         LOGD("volume [L]=%f:[R]=%f\n",
8800                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
8801
8802         /* invalid factor range or not */
8803         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++) {
8804                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
8805                         LOGE("Invalid factor!(valid factor:0~1.0)\n");
8806                         return MM_ERROR_INVALID_ARGUMENT;
8807                 }
8808         }
8809
8810         /* not support to set other value into each channel */
8811         if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
8812                 return MM_ERROR_INVALID_ARGUMENT;
8813
8814         /* Save volume to handle. Currently the first array element will be saved. */
8815         player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
8816
8817         /* check pipeline handle */
8818         if (!player->pipeline || !player->pipeline->audiobin) {
8819                 LOGD("audiobin is not created yet\n");
8820                 LOGD("but, current stored volume will be set when it's created.\n");
8821
8822                 /* NOTE : stored volume will be used in create_audiobin
8823                  * returning MM_ERROR_NONE here makes application to able to
8824                  * set volume at anytime.
8825                  */
8826                 return MM_ERROR_NONE;
8827         }
8828
8829         /* setting volume to volume element */
8830         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
8831
8832         if (vol_element) {
8833                 LOGD("volume is set [%f]\n", player->sound.volume);
8834                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
8835         }
8836
8837         MMPLAYER_FLEAVE();
8838
8839         return MM_ERROR_NONE;
8840 }
8841
8842
8843 int
8844 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
8845 {
8846         mm_player_t* player = (mm_player_t*) hplayer;
8847         int i = 0;
8848
8849         MMPLAYER_FENTER();
8850
8851         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8852         MMPLAYER_RETURN_VAL_IF_FAIL(volume, MM_ERROR_INVALID_ARGUMENT);
8853
8854         /* returning stored volume */
8855         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
8856                 volume->level[i] = player->sound.volume;
8857
8858         MMPLAYER_FLEAVE();
8859
8860         return MM_ERROR_NONE;
8861 }
8862
8863 int
8864 _mmplayer_set_mute(MMHandleType hplayer, int mute)
8865 {
8866         mm_player_t* player = (mm_player_t*) hplayer;
8867         GstElement* vol_element = NULL;
8868
8869         MMPLAYER_FENTER();
8870
8871         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8872
8873         /* mute value shoud 0 or 1 */
8874         if (mute != 0 && mute != 1) {
8875                 LOGE("bad mute value\n");
8876
8877                 /* FIXIT : definitly, we need _BAD_PARAM error code */
8878                 return MM_ERROR_INVALID_ARGUMENT;
8879         }
8880
8881         player->sound.mute = mute;
8882
8883         /* just hold mute value if pipeline is not ready */
8884         if (!player->pipeline || !player->pipeline->audiobin) {
8885                 LOGD("pipeline is not ready. holding mute value\n");
8886                 return MM_ERROR_NONE;
8887         }
8888
8889         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
8890
8891         /* NOTE : volume will only created when the bt is enabled */
8892         if (vol_element) {
8893                 LOGD("mute : %d\n", mute);
8894                 g_object_set(vol_element, "mute", mute, NULL);
8895         } else
8896                 LOGD("volume elemnet is not created. using volume in audiosink\n");
8897
8898         MMPLAYER_FLEAVE();
8899
8900         return MM_ERROR_NONE;
8901 }
8902
8903 int
8904 _mmplayer_get_mute(MMHandleType hplayer, int* pmute)
8905 {
8906         mm_player_t* player = (mm_player_t*) hplayer;
8907
8908         MMPLAYER_FENTER();
8909
8910         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8911         MMPLAYER_RETURN_VAL_IF_FAIL(pmute, MM_ERROR_INVALID_ARGUMENT);
8912
8913         /* just hold mute value if pipeline is not ready */
8914         if (!player->pipeline || !player->pipeline->audiobin) {
8915                 LOGD("pipeline is not ready. returning stored value\n");
8916                 *pmute = player->sound.mute;
8917                 return MM_ERROR_NONE;
8918         }
8919
8920         *pmute = player->sound.mute;
8921
8922         MMPLAYER_FLEAVE();
8923
8924         return MM_ERROR_NONE;
8925 }
8926
8927 int
8928 _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
8929 {
8930         mm_player_t* player = (mm_player_t*) hplayer;
8931
8932         MMPLAYER_FENTER();
8933
8934         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8935
8936         player->video_stream_changed_cb = callback;
8937         player->video_stream_changed_cb_user_param = user_param;
8938         LOGD("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
8939
8940         MMPLAYER_FLEAVE();
8941
8942         return MM_ERROR_NONE;
8943 }
8944
8945 int
8946 _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
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
8954         player->audio_stream_changed_cb = callback;
8955         player->audio_stream_changed_cb_user_param = user_param;
8956         LOGD("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
8957
8958         MMPLAYER_FLEAVE();
8959
8960         return MM_ERROR_NONE;
8961 }
8962
8963 int
8964 _mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param)
8965 {
8966         mm_player_t* player = (mm_player_t*) hplayer;
8967
8968         MMPLAYER_FENTER();
8969
8970         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8971
8972         player->audio_stream_render_cb_ex = callback;
8973         player->audio_stream_cb_user_param = user_param;
8974         player->audio_stream_sink_sync = sync;
8975         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);
8976
8977         MMPLAYER_FLEAVE();
8978
8979         return MM_ERROR_NONE;
8980 }
8981
8982 int
8983 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param)
8984 {
8985         mm_player_t* player = (mm_player_t*) hplayer;
8986
8987         MMPLAYER_FENTER();
8988
8989         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8990
8991         if (callback && !player->bufmgr)
8992                 player->bufmgr = tbm_bufmgr_init(-1);
8993
8994         player->set_mode.media_packet_video_stream = (callback) ? TRUE : FALSE;
8995         player->video_stream_cb = callback;
8996         player->video_stream_cb_user_param = user_param;
8997
8998         LOGD("Stream cb Handle value is %p : %p, enable:%d\n", player, player->video_stream_cb, player->set_mode.media_packet_video_stream);
8999
9000         MMPLAYER_FLEAVE();
9001
9002         return MM_ERROR_NONE;
9003 }
9004
9005 int
9006 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback 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_cb = callback;
9015         player->audio_stream_cb_user_param = user_param;
9016         LOGD("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
9017
9018         MMPLAYER_FLEAVE();
9019
9020         return MM_ERROR_NONE;
9021 }
9022
9023 static int
9024 __mmplayer_start_streaming_ext(mm_player_t *player)
9025 {
9026         gint ret = MM_ERROR_NONE;
9027
9028         MMPLAYER_FENTER();
9029         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9030
9031         if (MMPLAYER_IS_HTTP_PD(player)) {
9032                 if (!player->pd_downloader) {
9033                         ret = __mmplayer_realize_streaming_ext(player);
9034
9035                         if (ret != MM_ERROR_NONE) {
9036                                 LOGE("failed to realize streaming ext\n");
9037                                 return ret;
9038                         }
9039                 }
9040
9041                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI) {
9042                         ret = _mmplayer_start_pd_downloader((MMHandleType)player);
9043                         if (!ret) {
9044                                 LOGE("ERROR while starting PD...\n");
9045                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
9046                         }
9047                         ret = MM_ERROR_NONE;
9048                 }
9049         }
9050
9051         MMPLAYER_FLEAVE();
9052         return ret;
9053 }
9054
9055 int
9056 _mmplayer_start(MMHandleType hplayer)
9057 {
9058         mm_player_t* player = (mm_player_t*) hplayer;
9059         gint ret = MM_ERROR_NONE;
9060
9061         MMPLAYER_FENTER();
9062
9063         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9064
9065         /* check current state */
9066         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_START);
9067
9068         /* NOTE : we should check and create pipeline again if not created as we destroy
9069          * whole pipeline when stopping in streamming playback
9070          */
9071         if (!player->pipeline) {
9072                 ret = __gst_realize(player);
9073                 if (MM_ERROR_NONE != ret) {
9074                         LOGE("failed to realize before starting. only in streamming\n");
9075                         /* unlock */
9076                         return ret;
9077                 }
9078         }
9079
9080         ret = __mmplayer_start_streaming_ext(player);
9081         if (ret != MM_ERROR_NONE) {
9082                 LOGE("failed to start streaming ext 0x%X", ret);
9083                 return ret;
9084         }
9085
9086         /* start pipeline */
9087         ret = __gst_start(player);
9088         if (ret != MM_ERROR_NONE)
9089                 LOGE("failed to start player.\n");
9090
9091         MMPLAYER_FLEAVE();
9092
9093         return ret;
9094 }
9095
9096 /* NOTE: post "not supported codec message" to application
9097  * when one codec is not found during AUTOPLUGGING in MSL.
9098  * So, it's separated with error of __mmplayer_gst_callback().
9099  * And, if any codec is not found, don't send message here.
9100  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
9101  */
9102 int
9103 __mmplayer_handle_missed_plugin(mm_player_t* player)
9104 {
9105         MMMessageParamType msg_param;
9106         memset(&msg_param, 0, sizeof(MMMessageParamType));
9107         gboolean post_msg_direct = FALSE;
9108
9109         MMPLAYER_FENTER();
9110
9111         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9112
9113         LOGD("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
9114                         player->not_supported_codec, player->can_support_codec);
9115
9116         if (player->not_found_demuxer) {
9117                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9118                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
9119
9120                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9121                 MMPLAYER_FREEIF(msg_param.data);
9122
9123                 return MM_ERROR_NONE;
9124         }
9125
9126         if (player->not_supported_codec) {
9127                 if (player->can_support_codec) {
9128                         // There is one codec to play
9129                         post_msg_direct = TRUE;
9130                 } else {
9131                         if (player->pipeline->audiobin) // Some content has only PCM data in container.
9132                                 post_msg_direct = TRUE;
9133                 }
9134
9135                 if (post_msg_direct) {
9136                         MMMessageParamType msg_param;
9137                         memset(&msg_param, 0, sizeof(MMMessageParamType));
9138
9139                         if (player->not_supported_codec ==  MISSING_PLUGIN_AUDIO) {
9140                                 LOGW("not found AUDIO codec, posting error code to application.\n");
9141
9142                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9143                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9144                         } else if (player->not_supported_codec ==  MISSING_PLUGIN_VIDEO) {
9145                                 LOGW("not found VIDEO codec, posting error code to application.\n");
9146
9147                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9148                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
9149                         }
9150
9151                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9152
9153                         MMPLAYER_FREEIF(msg_param.data);
9154
9155                         return MM_ERROR_NONE;
9156                 } else {
9157                         // no any supported codec case
9158                         LOGW("not found any codec, posting error code to application.\n");
9159
9160                         if (player->not_supported_codec ==  MISSING_PLUGIN_AUDIO) {
9161                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9162                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9163                         } else {
9164                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9165                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
9166                         }
9167
9168                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9169
9170                         MMPLAYER_FREEIF(msg_param.data);
9171                 }
9172         }
9173
9174         MMPLAYER_FLEAVE();
9175
9176         return MM_ERROR_NONE;
9177 }
9178
9179 static void __mmplayer_check_pipeline(mm_player_t* player)
9180 {
9181         GstState element_state = GST_STATE_VOID_PENDING;
9182         GstState element_pending_state = GST_STATE_VOID_PENDING;
9183         gint timeout = 0;
9184         int ret = MM_ERROR_NONE;
9185
9186         if (player->gapless.reconfigure) {
9187                 LOGW("pipeline is under construction.\n");
9188
9189                 MMPLAYER_PLAYBACK_LOCK(player);
9190                 MMPLAYER_PLAYBACK_UNLOCK(player);
9191
9192                 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
9193
9194                 /* wait for state transition */
9195                 ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND);
9196
9197                 if (ret == GST_STATE_CHANGE_FAILURE)
9198                         LOGE("failed to change pipeline state within %d sec\n", timeout);
9199         }
9200 }
9201
9202 /* NOTE : it should be able to call 'stop' anytime*/
9203 int
9204 _mmplayer_stop(MMHandleType hplayer)
9205 {
9206         mm_player_t* player = (mm_player_t*)hplayer;
9207         int ret = MM_ERROR_NONE;
9208
9209         MMPLAYER_FENTER();
9210
9211         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9212
9213         /* check current state */
9214         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_STOP);
9215
9216         /* check pipline building state */
9217         __mmplayer_check_pipeline(player);
9218         __mmplayer_reset_gapless_state(player);
9219
9220         /* NOTE : application should not wait for EOS after calling STOP */
9221         __mmplayer_cancel_eos_timer(player);
9222
9223         __mmplayer_unrealize_streaming_ext(player);
9224
9225         /* reset */
9226         player->doing_seek = FALSE;
9227
9228         /* stop pipeline */
9229         ret = __gst_stop(player);
9230
9231         if (ret != MM_ERROR_NONE)
9232                 LOGE("failed to stop player.\n");
9233
9234         MMPLAYER_FLEAVE();
9235
9236         return ret;
9237 }
9238
9239 int
9240 _mmplayer_pause(MMHandleType hplayer)
9241 {
9242         mm_player_t* player = (mm_player_t*)hplayer;
9243         gint64 pos_nsec = 0;
9244         gboolean async = FALSE;
9245         gint ret = MM_ERROR_NONE;
9246
9247         MMPLAYER_FENTER();
9248
9249         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9250
9251         /* check current state */
9252         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_PAUSE);
9253
9254         /* check pipline building state */
9255         __mmplayer_check_pipeline(player);
9256
9257         switch (MMPLAYER_CURRENT_STATE(player)) {
9258         case MM_PLAYER_STATE_READY:
9259                 {
9260                         /* check prepare async or not.
9261                          * In the case of streaming playback, it's recommned to avoid blocking wait.
9262                          */
9263                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
9264                         LOGD("prepare working mode : %s", (async ? "async" : "sync"));
9265
9266                         /* Changing back sync of rtspsrc to async */
9267                         if (MMPLAYER_IS_RTSP_STREAMING(player)) {
9268                                 LOGD("async prepare working mode for rtsp");
9269                                 async = TRUE;
9270                         }
9271                 }
9272                 break;
9273
9274         case MM_PLAYER_STATE_PLAYING:
9275                 {
9276                         /* NOTE : store current point to overcome some bad operation
9277                         *(returning zero when getting current position in paused state) of some
9278                         * elements
9279                         */
9280                         if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
9281                                 LOGW("getting current position failed in paused\n");
9282
9283                         player->last_position = pos_nsec;
9284
9285                         /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
9286                            But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
9287                            This causes problem is position calculation during normal pause resume scenarios also.
9288                            Currently during pause , we are sending the current position to rtspsrc module for position saving. */
9289                         if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
9290                                 (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
9291                                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
9292                         }
9293                 }
9294                 break;
9295         }
9296
9297         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
9298                 LOGD("doing async pause in case of ms buff src");
9299                 async = TRUE;
9300         }
9301
9302         /* pause pipeline */
9303         ret = __gst_pause(player, async);
9304
9305         if (ret != MM_ERROR_NONE)
9306                 LOGE("failed to pause player. ret : 0x%x\n", ret);
9307
9308         if (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) {
9309                 if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "display_rotation"))
9310                         LOGE("failed to update display_rotation");
9311         }
9312
9313         MMPLAYER_FLEAVE();
9314
9315         return ret;
9316 }
9317
9318 int
9319 _mmplayer_resume(MMHandleType hplayer)
9320 {
9321         mm_player_t* player = (mm_player_t*)hplayer;
9322         int ret = MM_ERROR_NONE;
9323         gboolean async = FALSE;
9324
9325         MMPLAYER_FENTER();
9326
9327         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9328
9329         /* Changing back sync mode rtspsrc to async */
9330         if ((MMPLAYER_IS_RTSP_STREAMING(player))) {
9331                 LOGD("async resume for rtsp case");
9332                 async = TRUE;
9333         }
9334
9335         /* check current state */
9336         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_RESUME);
9337
9338         ret = __gst_resume(player, async);
9339
9340         if (ret != MM_ERROR_NONE)
9341                 LOGE("failed to resume player.\n");
9342
9343         MMPLAYER_FLEAVE();
9344
9345         return ret;
9346 }
9347
9348 static int
9349 __mmplayer_set_pcm_extraction(mm_player_t* player)
9350 {
9351         gint64 start_nsec = 0;
9352         gint64 end_nsec = 0;
9353         gint64 dur_nsec = 0;
9354         gint64 dur_msec = 0;
9355         int required_start = 0;
9356         int required_end = 0;
9357         int ret = 0;
9358
9359         MMPLAYER_FENTER();
9360
9361         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
9362
9363         mm_attrs_multiple_get(player->attrs,
9364                 NULL,
9365                 "pcm_extraction_start_msec", &required_start,
9366                 "pcm_extraction_end_msec", &required_end,
9367                 NULL);
9368
9369         LOGD("pcm extraction required position is from [%d] to [%d](msec)\n", required_start, required_end);
9370
9371         if (required_start == 0 && required_end == 0) {
9372                 LOGD("extracting entire stream");
9373                 return MM_ERROR_NONE;
9374         } else if (required_start < 0 || required_start > required_end || required_end < 0) {
9375                 LOGD("invalid range for pcm extraction");
9376                 return MM_ERROR_INVALID_ARGUMENT;
9377         }
9378
9379         /* get duration */
9380         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
9381         if (!ret) {
9382                 LOGE("failed to get duration");
9383                 return MM_ERROR_PLAYER_INTERNAL;
9384         }
9385         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
9386
9387         if (dur_msec < required_end) {
9388                 // FIXME
9389                 LOGD("invalid end pos for pcm extraction");
9390                 return MM_ERROR_INVALID_ARGUMENT;
9391         }
9392
9393         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
9394         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
9395
9396         if ((!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
9397                                         1.0,
9398                                         GST_FORMAT_TIME,
9399                                         (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
9400                                         GST_SEEK_TYPE_SET, start_nsec,
9401                                         GST_SEEK_TYPE_SET, end_nsec))) {
9402                 LOGE("failed to seek for pcm extraction\n");
9403
9404                 return MM_ERROR_PLAYER_SEEK;
9405         }
9406
9407         LOGD("succeeded to set up segment extraction from [%llu] to [%llu](nsec)\n", start_nsec, end_nsec);
9408
9409         MMPLAYER_FLEAVE();
9410
9411         return MM_ERROR_NONE;
9412 }
9413
9414 int
9415 _mmplayer_set_playspeed(MMHandleType hplayer, float rate, bool streaming)
9416 {
9417         mm_player_t* player = (mm_player_t*)hplayer;
9418         gint64 pos_nsec = 0;
9419         int ret = MM_ERROR_NONE;
9420         int mute = FALSE;
9421         signed long long start = 0, stop = 0;
9422         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
9423         MMPLAYER_FENTER();
9424
9425         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
9426         MMPLAYER_RETURN_VAL_IF_FAIL(streaming || !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API);
9427
9428         /* The sound of video is not supported under 0.0 and over 2.0. */
9429         if (rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN) {
9430                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
9431                         mute = TRUE;
9432         }
9433         _mmplayer_set_mute(hplayer, mute);
9434
9435         if (player->playback_rate == rate)
9436                 return MM_ERROR_NONE;
9437
9438         /* If the position is reached at start potion during fast backward, EOS is posted.
9439          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
9440          * */
9441         player->playback_rate = rate;
9442
9443         current_state = MMPLAYER_CURRENT_STATE(player);
9444
9445         if (current_state != MM_PLAYER_STATE_PAUSED)
9446                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec);
9447
9448         LOGD("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_nsec), ret, current_state);
9449
9450         if ((current_state == MM_PLAYER_STATE_PAUSED)
9451                 || (!ret) /*|| (player->last_position != 0 && pos_msec == 0)*/) {
9452                 LOGW("returning last point : %"G_GINT64_FORMAT, player->last_position);
9453                 pos_nsec = player->last_position;
9454         }
9455
9456         if (rate >= 0) {
9457                 start = pos_nsec;
9458                 stop = GST_CLOCK_TIME_NONE;
9459         } else {
9460                 start = GST_CLOCK_TIME_NONE;
9461                 stop = pos_nsec;
9462         }
9463
9464         if (!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
9465                                 player->playback_rate,
9466                                 GST_FORMAT_TIME,
9467                                 (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
9468                                 GST_SEEK_TYPE_SET, start,
9469                                 GST_SEEK_TYPE_SET, stop)) {
9470                 LOGE("failed to set speed playback\n");
9471                 return MM_ERROR_PLAYER_SEEK;
9472         }
9473
9474         LOGD("succeeded to set speed playback as %0.1f\n", rate);
9475
9476         MMPLAYER_FLEAVE();
9477
9478         return MM_ERROR_NONE;;
9479 }
9480
9481 int
9482 _mmplayer_set_position(MMHandleType hplayer, int format, gint64 position)
9483 {
9484         mm_player_t* player = (mm_player_t*)hplayer;
9485         int ret = MM_ERROR_NONE;
9486
9487         MMPLAYER_FENTER();
9488
9489         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9490
9491         /* check pipline building state */
9492         __mmplayer_check_pipeline(player);
9493
9494         ret = __gst_set_position(player, format, position, FALSE);
9495
9496         MMPLAYER_FLEAVE();
9497
9498         return ret;
9499 }
9500
9501 int
9502 _mmplayer_get_position(MMHandleType hplayer, int format, gint64 *position)
9503 {
9504         mm_player_t* player = (mm_player_t*)hplayer;
9505         int ret = MM_ERROR_NONE;
9506
9507         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9508
9509         ret = __gst_get_position(player, format, position);
9510
9511         return ret;
9512 }
9513
9514 int
9515 _mmplayer_get_duration(MMHandleType hplayer, gint64 *duration)
9516 {
9517         mm_player_t* player = (mm_player_t*)hplayer;
9518         int ret = MM_ERROR_NONE;
9519
9520         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9521         MMPLAYER_RETURN_VAL_IF_FAIL(duration, MM_ERROR_COMMON_INVALID_ARGUMENT);
9522
9523         *duration = player->duration;
9524         return ret;
9525 }
9526
9527 int
9528 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos)
9529 {
9530         mm_player_t* player = (mm_player_t*)hplayer;
9531         int ret = MM_ERROR_NONE;
9532
9533         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9534
9535         ret = __gst_get_buffer_position(player, format, start_pos, stop_pos);
9536
9537         return ret;
9538 }
9539
9540 int
9541 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position)
9542 {
9543         mm_player_t* player = (mm_player_t*)hplayer;
9544         int ret = MM_ERROR_NONE;
9545
9546         MMPLAYER_FENTER();
9547
9548         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9549
9550         ret = __gst_adjust_subtitle_position(player, format, position);
9551
9552         MMPLAYER_FLEAVE();
9553
9554         return ret;
9555 }
9556
9557 static gboolean
9558 __mmplayer_is_midi_type(gchar* str_caps)
9559 {
9560         if ((g_strrstr(str_caps, "audio/midi")) ||
9561                 (g_strrstr(str_caps, "application/x-gst_ff-mmf")) ||
9562                 (g_strrstr(str_caps, "application/x-smaf")) ||
9563                 (g_strrstr(str_caps, "audio/x-imelody")) ||
9564                 (g_strrstr(str_caps, "audio/mobile-xmf")) ||
9565                 (g_strrstr(str_caps, "audio/xmf")) ||
9566                 (g_strrstr(str_caps, "audio/mxmf"))) {
9567                 LOGD("midi\n");
9568                 return TRUE;
9569         }
9570
9571         return FALSE;
9572 }
9573
9574 static gboolean
9575 __mmplayer_is_only_mp3_type(gchar *str_caps)
9576 {
9577         if (g_strrstr(str_caps, "application/x-id3") ||
9578                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion= (int)1")))
9579                 return TRUE;
9580         return FALSE;
9581 }
9582
9583 static void
9584 __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps)
9585 {
9586         GstStructure* caps_structure = NULL;
9587         gint samplerate = 0;
9588         gint channels = 0;
9589
9590         MMPLAYER_FENTER();
9591         MMPLAYER_RETURN_IF_FAIL(player && caps);
9592
9593         caps_structure = gst_caps_get_structure(caps, 0);
9594
9595         /* set stream information */
9596         gst_structure_get_int(caps_structure, "rate", &samplerate);
9597         mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
9598
9599         gst_structure_get_int(caps_structure, "channels", &channels);
9600         mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
9601
9602         LOGD("audio samplerate : %d     channels : %d\n", samplerate, channels);
9603 }
9604
9605 static void
9606 __mmplayer_update_content_type_info(mm_player_t* player)
9607 {
9608         MMPLAYER_FENTER();
9609         MMPLAYER_RETURN_IF_FAIL(player && player->type);
9610
9611         if (__mmplayer_is_midi_type(player->type)) {
9612                 player->bypass_audio_effect = TRUE;
9613         } else if (g_strrstr(player->type, "application/x-hls")) {
9614                 /* If it can't know exact type when it parses uri because of redirection case,
9615                  * it will be fixed by typefinder or when doing autoplugging.
9616                  */
9617                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
9618                 if (player->streamer) {
9619                         player->streamer->is_adaptive_streaming = TRUE;
9620                         player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
9621                         player->streamer->buffering_req.rebuffer_time = 5 * 1000;
9622                 }
9623         } else if (g_strrstr(player->type, "application/dash+xml")) {
9624                 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
9625         }
9626
9627         MMPLAYER_FLEAVE();
9628 }
9629
9630 static void
9631 __mmplayer_typefind_have_type(GstElement *tf, guint probability,
9632 GstCaps *caps, gpointer data)
9633 {
9634         mm_player_t* player = (mm_player_t*)data;
9635         GstPad* pad = NULL;
9636
9637         MMPLAYER_FENTER();
9638
9639         MMPLAYER_RETURN_IF_FAIL(player && tf && caps);
9640
9641         /* store type string */
9642         MMPLAYER_FREEIF(player->type);
9643         player->type = gst_caps_to_string(caps);
9644         if (player->type) {
9645                 LOGD("[handle: %p] media type %s found, probability %d%% / %d\n",
9646                                 player, player->type, probability, gst_caps_get_size(caps));
9647         }
9648
9649         if ((!MMPLAYER_IS_RTSP_STREAMING(player)) &&
9650                 (g_strrstr(player->type, "audio/x-raw-int"))) {
9651                 LOGE("not support media format\n");
9652
9653                 if (player->msg_posted == FALSE) {
9654                         MMMessageParamType msg_param;
9655                         memset(&msg_param, 0, sizeof(MMMessageParamType));
9656
9657                         msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
9658                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9659
9660                         /* don't post more if one was sent already */
9661                         player->msg_posted = TRUE;
9662                 }
9663                 return;
9664         }
9665
9666         __mmplayer_update_content_type_info(player);
9667
9668         pad = gst_element_get_static_pad(tf, "src");
9669         if (!pad) {
9670                 LOGE("fail to get typefind src pad.\n");
9671                 return;
9672         }
9673
9674         if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
9675                 gboolean async = FALSE;
9676                 LOGE("failed to autoplug %s\n", player->type);
9677
9678                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
9679
9680                 if (async && player->msg_posted == FALSE)
9681                         __mmplayer_handle_missed_plugin(player);
9682
9683                 goto DONE;
9684         }
9685
9686 DONE:
9687         gst_object_unref(GST_OBJECT(pad));
9688
9689         MMPLAYER_FLEAVE();
9690
9691         return;
9692 }
9693
9694 static GstElement *
9695 __mmplayer_create_decodebin(mm_player_t* player)
9696 {
9697         GstElement *decodebin = NULL;
9698
9699         MMPLAYER_FENTER();
9700
9701         /* create decodebin */
9702         decodebin = gst_element_factory_make("decodebin", NULL);
9703
9704         if (!decodebin) {
9705                 LOGE("fail to create decodebin\n");
9706                 goto ERROR;
9707         }
9708
9709         /* raw pad handling signal */
9710         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
9711                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
9712
9713         /* no-more-pad pad handling signal */
9714         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
9715                                                 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
9716
9717         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
9718                                                 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
9719
9720         /* This signal is emitted when a pad for which there is no further possible
9721            decoding is added to the decodebin.*/
9722         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
9723                                                 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player);
9724
9725         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
9726            before looking for any elements that can handle that stream.*/
9727         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
9728                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
9729
9730         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
9731            before looking for any elements that can handle that stream.*/
9732         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
9733                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
9734
9735         /* This signal is emitted once decodebin has finished decoding all the data.*/
9736         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
9737                                                 G_CALLBACK(__mmplayer_gst_decode_drained), player);
9738
9739         /* This signal is emitted when a element is added to the bin.*/
9740         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
9741                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
9742
9743 ERROR:
9744         return decodebin;
9745 }
9746
9747 static gboolean
9748 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
9749 {
9750         MMPlayerGstElement* mainbin = NULL;
9751         GstElement* decodebin = NULL;
9752         GstElement* queue2 = NULL;
9753         GstPad* sinkpad = NULL;
9754         GstPad* qsrcpad = NULL;
9755         gint64 dur_bytes = 0L;
9756
9757         guint max_buffer_size_bytes = 0;
9758         gint init_buffering_time = player->streamer->buffering_req.prebuffer_time;
9759
9760         MMPLAYER_FENTER();
9761         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, FALSE);
9762
9763         mainbin = player->pipeline->mainbin;
9764
9765         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
9766                 (MMPLAYER_IS_HTTP_STREAMING(player))) {
9767                 LOGD("creating http streaming buffering queue(queue2)\n");
9768
9769                 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
9770                         LOGE("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
9771                 } else {
9772                         queue2 = gst_element_factory_make("queue2", "queue2");
9773                         if (!queue2) {
9774                                 LOGE("failed to create buffering queue element\n");
9775                                 goto ERROR;
9776                         }
9777
9778                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) {
9779                                 LOGE("failed to add buffering queue\n");
9780                                 goto ERROR;
9781                         }
9782
9783                         sinkpad = gst_element_get_static_pad(queue2, "sink");
9784                         qsrcpad = gst_element_get_static_pad(queue2, "src");
9785
9786                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
9787                                 LOGE("failed to link buffering queue");
9788                                 goto ERROR;
9789                         }
9790
9791                         if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
9792                                 LOGE("fail to get duration");
9793
9794                         LOGD("dur_bytes = %"G_GINT64_FORMAT, dur_bytes);
9795
9796                         muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
9797
9798                         if (dur_bytes > 0) {
9799                                 if (MMPLAYER_USE_FILE_FOR_BUFFERING(player)) {
9800                                         type = MUXED_BUFFER_TYPE_FILE;
9801                                 } else {
9802                                         type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
9803                                         player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
9804                                 }
9805                         } else {
9806                                 dur_bytes = 0;
9807                         }
9808
9809                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
9810                         // if (!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
9811                         if (!g_strrstr(player->type, "video/mpegts")) {
9812                                 max_buffer_size_bytes = (type == MUXED_BUFFER_TYPE_FILE) ? (player->ini.http_max_size_bytes) : (5*1024*1024);
9813                                 LOGD("max_buffer_size_bytes = %d", max_buffer_size_bytes);
9814
9815                                 /* FIXME : pass ini setting directly. is this ok? */
9816                                 __mm_player_streaming_set_queue2(player->streamer,
9817                                                                                                 queue2,
9818                                                                                                 FALSE,
9819                                                                                                 max_buffer_size_bytes,
9820                                                                                                 player->ini.http_buffering_time,
9821                                                                                                 1.0,                                                            // no meaning
9822                                                                                                 player->ini.http_buffering_limit,       // no meaning
9823                                                                                                 type,
9824                                                                                                 player->http_file_buffering_path,
9825                                                                                                 (guint64)dur_bytes);
9826                         }
9827
9828                         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(queue2)) {
9829                                 LOGE("failed to sync queue2 state with parent\n");
9830                                 goto ERROR;
9831                         }
9832
9833                         srcpad = qsrcpad;
9834
9835                         gst_object_unref(GST_OBJECT(sinkpad));
9836
9837                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
9838                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
9839                 }
9840         }
9841
9842         /* create decodebin */
9843         decodebin = __mmplayer_create_decodebin(player);
9844
9845         if (!decodebin) {
9846                 LOGE("can not create autoplug element\n");
9847                 goto ERROR;
9848         }
9849
9850         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
9851                 LOGE("failed to add decodebin\n");
9852                 goto ERROR;
9853         }
9854
9855         /* to force caps on the decodebin element and avoid reparsing stuff by
9856         * typefind. It also avoids a deadlock in the way typefind activates pads in
9857         * the state change */
9858         g_object_set(decodebin, "sink-caps", caps, NULL);
9859
9860         sinkpad = gst_element_get_static_pad(decodebin, "sink");
9861
9862         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
9863                 LOGE("failed to link decodebin\n");
9864                 goto ERROR;
9865         }
9866
9867         gst_object_unref(GST_OBJECT(sinkpad));
9868
9869         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
9870         mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin;
9871
9872         /* set decodebin property about buffer in streaming playback. *
9873          * in case of HLS/DASH, it does not need to have big buffer        *
9874          * because it is kind of adaptive streaming.                  */
9875         if (!MMPLAYER_IS_HTTP_PD(player) && MMPLAYER_IS_HTTP_STREAMING(player)) {
9876                 guint max_size_bytes = MAX_DECODEBIN_BUFFER_BYTES;
9877                 guint64 max_size_time = MAX_DECODEBIN_BUFFER_TIME;
9878                 init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
9879
9880                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
9881                         || MMPLAYER_IS_DASH_STREAMING(player)) {
9882                         max_size_bytes = MAX_DECODEBIN_ADAPTIVE_BUFFER_BYTES;
9883                         max_size_time = MAX_DECODEBIN_ADAPTIVE_BUFFER_TIME;
9884                 }
9885
9886                 g_object_set(G_OBJECT(decodebin), "use-buffering", TRUE,
9887                                                                                         "high-percent", (gint)player->ini.http_buffering_limit,
9888                                                                                         "low-percent", 1,   // 1%
9889                                                                                         "max-size-bytes", max_size_bytes,
9890                                                                                         "max-size-time", (guint64)(max_size_time * GST_SECOND),
9891                                                                                         "max-size-buffers", 0, NULL);  // disable or automatic
9892         }
9893
9894         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin)) {
9895                 LOGE("failed to sync decodebin state with parent\n");
9896                 goto ERROR;
9897         }
9898
9899         MMPLAYER_FLEAVE();
9900
9901         return TRUE;
9902
9903 ERROR:
9904
9905         if (sinkpad)
9906                 gst_object_unref(GST_OBJECT(sinkpad));
9907
9908         if (queue2) {
9909                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
9910                  * You need to explicitly set elements to the NULL state before
9911                  * dropping the final reference, to allow them to clean up.
9912                  */
9913                 gst_element_set_state(queue2, GST_STATE_NULL);
9914
9915                 /* And, it still has a parent "player".
9916                  * You need to let the parent manage the object instead of unreffing the object directly.
9917                  */
9918                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
9919                 gst_object_unref(queue2);
9920                 queue2 = NULL;
9921         }
9922
9923         if (decodebin) {
9924                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
9925                  * You need to explicitly set elements to the NULL state before
9926                  * dropping the final reference, to allow them to clean up.
9927                  */
9928                 gst_element_set_state(decodebin, GST_STATE_NULL);
9929
9930                 /* And, it still has a parent "player".
9931                  * You need to let the parent manage the object instead of unreffing the object directly.
9932                  */
9933
9934                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
9935                 gst_object_unref(decodebin);
9936                 decodebin = NULL;
9937         }
9938
9939         return FALSE;
9940 }
9941
9942 static int
9943 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
9944 {
9945         MMPLAYER_FENTER();
9946
9947         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
9948         MMPLAYER_RETURN_VAL_IF_FAIL(mime, MM_ERROR_INVALID_ARGUMENT);
9949
9950         LOGD("class : %s, mime : %s \n", factory_class, mime);
9951
9952         /* add missing plugin */
9953         /* NOTE : msl should check missing plugin for image mime type.
9954          * Some motion jpeg clips can have playable audio track.
9955          * So, msl have to play audio after displaying popup written video format not supported.
9956          */
9957         if (!(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)) {
9958                 if (!(player->can_support_codec | player->videodec_linked | player->audiodec_linked)) {
9959                         LOGD("not found demuxer\n");
9960                         player->not_found_demuxer = TRUE;
9961                         player->unlinked_demuxer_mime = g_strdup_printf("%s", mime);
9962
9963                         goto DONE;
9964                 }
9965         }
9966
9967         if (!g_strrstr(factory_class, "Demuxer")) {
9968                 if ((g_str_has_prefix(mime, "video")) || (g_str_has_prefix(mime, "image"))) {
9969                         LOGD("can support codec=0x%X, vdec_linked=%d, adec_linked=%d\n",
9970                                 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
9971
9972                         /* check that clip have multi tracks or not */
9973                         if ((player->can_support_codec & FOUND_PLUGIN_VIDEO) && (player->videodec_linked)) {
9974                                 LOGD("video plugin is already linked\n");
9975                         } else {
9976                                 LOGW("add VIDEO to missing plugin\n");
9977                                 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
9978                                 player->unlinked_video_mime = g_strdup_printf("%s", mime);
9979                         }
9980                 } else if (g_str_has_prefix(mime, "audio")) {
9981                         if ((player->can_support_codec & FOUND_PLUGIN_AUDIO) && (player->audiodec_linked)) {
9982                                 LOGD("audio plugin is already linked\n");
9983                         } else {
9984                                 LOGW("add AUDIO to missing plugin\n");
9985                                 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
9986                                 player->unlinked_audio_mime = g_strdup_printf("%s", mime);
9987                         }
9988                 }
9989         }
9990
9991 DONE:
9992         MMPLAYER_FLEAVE();
9993
9994         return MM_ERROR_NONE;
9995 }
9996
9997
9998 static void
9999 __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
10000 {
10001         mm_player_t* player = (mm_player_t*)data;
10002
10003         MMPLAYER_FENTER();
10004
10005         MMPLAYER_RETURN_IF_FAIL(player);
10006
10007         /* remove fakesink. */
10008         if (!__mmplayer_gst_remove_fakesink(player,
10009                                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK])) {
10010                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
10011                  * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
10012                  * source element are not same. To overcome this situation, this function will called
10013                  * several places and several times. Therefore, this is not an error case.
10014                  */
10015                 return;
10016         }
10017
10018         LOGD("[handle: %p] pipeline has completely constructed", player);
10019
10020         if ((player->ini.async_start) &&
10021                 (player->msg_posted == FALSE) &&
10022                 (player->cmd >= MMPLAYER_COMMAND_START))
10023                 __mmplayer_handle_missed_plugin(player);
10024
10025         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-complete");
10026 }
10027
10028 static gboolean
10029 __mmplayer_verify_next_play_path(mm_player_t *player)
10030 {
10031         MMHandleType attrs = 0;
10032         MMPlayerParseProfile profile;
10033         gint uri_idx = 0, check_cnt = 0;
10034         char *uri = NULL;
10035         gint mode = MM_PLAYER_PD_MODE_NONE;
10036         gint video = 0;
10037         gint count = 0;
10038         gint gapless = 0;
10039         guint num_of_list = 0;
10040         static int profile_tv = -1;
10041
10042         MMPLAYER_FENTER();
10043
10044         LOGD("checking for gapless play");
10045
10046         if (player->pipeline->textbin) {
10047                 LOGE("subtitle path is enabled. gapless play is not supported.\n");
10048                 goto ERROR;
10049         }
10050
10051         attrs = MMPLAYER_GET_ATTRS(player);
10052         if (!attrs) {
10053                 LOGE("fail to get attributes.\n");
10054                 goto ERROR;
10055         }
10056
10057         mm_attrs_get_int_by_name(attrs, "content_video_found", &video);
10058
10059         if (__builtin_expect(profile_tv == -1, 0)) {
10060                 char *profileName;
10061                 system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
10062                 switch (*profileName) {
10063                 case 't':
10064                 case 'T':
10065                         profile_tv = 1;
10066                         break;
10067                 default:
10068                         profile_tv = 0;
10069                 }
10070                 free(profileName);
10071         }
10072         /* gapless playback is not supported in case of video at TV profile. */
10073         if (profile_tv && video) {
10074                 LOGW("not support video gapless playback");
10075                 goto ERROR;
10076         }
10077
10078         if (mm_attrs_get_int_by_name(attrs, "pd_mode", &mode) == MM_ERROR_NONE) {
10079                 if (mode == TRUE) {
10080                         LOGW("pd mode\n");
10081                         goto ERROR;
10082                 }
10083         }
10084
10085         if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
10086                 LOGE("can not get play count\n");
10087
10088         if (mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless) != MM_ERROR_NONE)
10089                 LOGE("can not get gapless mode\n");
10090
10091         if (video && !gapless) {
10092                 LOGW("not enabled video gapless playback");
10093                 goto ERROR;
10094         }
10095
10096         if ((count == -1 || count > 1)) /* enable gapless when looping or repeat */
10097                 gapless = 1;
10098
10099         if (!gapless) {
10100                 LOGW("gapless is disabled\n");  /* FIXME: playlist(without gapless) is not implemented. */
10101                 goto ERROR;
10102         }
10103
10104         num_of_list = g_list_length(player->uri_info.uri_list);
10105
10106         LOGD("repeat count = %d, num_of_list = %d\n", count, num_of_list);
10107
10108         if (num_of_list == 0) {
10109                 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE) {
10110                         LOGE("can not get profile_uri\n");
10111                         goto ERROR;
10112                 }
10113
10114                 if (!uri) {
10115                         LOGE("uri list is empty.\n");
10116                         goto ERROR;
10117                 }
10118
10119                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
10120                 LOGD("add original path : %s ", uri);
10121
10122                 num_of_list = 1;
10123                 uri = NULL;
10124         }
10125
10126         uri_idx = player->uri_info.uri_idx;
10127
10128         while (TRUE) {
10129                 check_cnt++;
10130
10131                 if (check_cnt > num_of_list) {
10132                         LOGE("there is no valid uri.");
10133                         goto ERROR;
10134                 }
10135
10136                 LOGD("uri idx : %d / %d\n", uri_idx, num_of_list);
10137
10138                 if (uri_idx < num_of_list-1) {
10139                         uri_idx++;
10140                 } else {
10141                         if ((count <= 1) && (count != -1)) {
10142                                 LOGD("no repeat.");
10143                                 goto ERROR;
10144                         } else if (count > 1) {
10145                                 /* decrease play count */
10146                                 /* we succeeded to rewind. update play count and then wait for next EOS */
10147                                 count--;
10148
10149                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
10150
10151                                 /* commit attribute */
10152                                 if (mmf_attrs_commit(attrs))
10153                                         LOGE("failed to commit attribute\n");
10154                         }
10155
10156                         /* count < 0 : repeat continually */
10157                         uri_idx = 0;
10158                 }
10159
10160                 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
10161                 LOGD("uri idx : %d, uri = %s\n", uri_idx, uri);
10162
10163                 if (uri == NULL) {
10164                         LOGW("next uri does not exist\n");
10165                         continue;
10166                 }
10167
10168                 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE) {
10169                         LOGE("failed to parse profile\n");
10170                         continue;
10171                 }
10172
10173                 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
10174                         (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP)) {
10175                         LOGW("uri type is not supported(%d).", profile.uri_type);
10176                         continue;
10177                 }
10178
10179                 break;
10180         }
10181
10182         player->uri_info.uri_idx = uri_idx;
10183         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
10184
10185         if (mmf_attrs_commit(player->attrs)) {
10186                 LOGE("failed to commit.\n");
10187                 goto ERROR;
10188         }
10189
10190         LOGD("next uri %s(%d)\n", uri, uri_idx);
10191
10192         return TRUE;
10193
10194 ERROR:
10195
10196         LOGE("unable to play next path. EOS will be posted soon.\n");
10197         return FALSE;
10198 }
10199
10200 static void
10201 __mmplayer_initialize_next_play(mm_player_t *player)
10202 {
10203         int i;
10204
10205         MMPLAYER_FENTER();
10206
10207         player->smooth_streaming = FALSE;
10208         player->videodec_linked = 0;
10209         player->audiodec_linked = 0;
10210         player->videosink_linked = 0;
10211         player->audiosink_linked = 0;
10212         player->textsink_linked = 0;
10213         player->is_external_subtitle_present = FALSE;
10214         player->is_external_subtitle_added_now = FALSE;
10215         player->not_supported_codec = MISSING_PLUGIN_NONE;
10216         player->can_support_codec = FOUND_PLUGIN_NONE;
10217         player->pending_seek.is_pending = FALSE;
10218         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
10219         player->pending_seek.pos = 0;
10220         player->msg_posted = FALSE;
10221         player->has_many_types = FALSE;
10222         player->no_more_pad = FALSE;
10223         player->not_found_demuxer = 0;
10224         player->doing_seek = FALSE;
10225         player->max_audio_channels = 0;
10226         player->is_subtitle_force_drop = FALSE;
10227         player->play_subtitle = FALSE;
10228         player->adjust_subtitle_pos = 0;
10229
10230         player->total_bitrate = 0;
10231         player->total_maximum_bitrate = 0;
10232
10233         _mmplayer_track_initialize(player);
10234         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
10235
10236         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
10237                 player->bitrate[i] = 0;
10238                 player->maximum_bitrate[i] = 0;
10239         }
10240
10241         if (player->v_stream_caps) {
10242                 gst_caps_unref(player->v_stream_caps);
10243                 player->v_stream_caps = NULL;
10244         }
10245
10246         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
10247
10248         /* clean found parsers */
10249         if (player->parsers) {
10250                 GList *parsers = player->parsers;
10251                 for (; parsers; parsers = g_list_next(parsers)) {
10252                         gchar *name = parsers->data;
10253                         MMPLAYER_FREEIF(name);
10254                 }
10255                 g_list_free(player->parsers);
10256                 player->parsers = NULL;
10257         }
10258
10259         /* clean found audio decoders */
10260         if (player->audio_decoders) {
10261                 GList *a_dec = player->audio_decoders;
10262                 for (; a_dec; a_dec = g_list_next(a_dec)) {
10263                         gchar *name = a_dec->data;
10264                         MMPLAYER_FREEIF(name);
10265                 }
10266                 g_list_free(player->audio_decoders);
10267                 player->audio_decoders = NULL;
10268         }
10269
10270         MMPLAYER_FLEAVE();
10271 }
10272
10273 static void
10274 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
10275 {
10276         MMPlayerGstElement *mainbin = NULL;
10277         MMMessageParamType msg_param = {0,};
10278         GstElement *element = NULL;
10279         MMHandleType attrs = 0;
10280         char *uri = NULL;
10281         enum MainElementID elemId = MMPLAYER_M_NUM;
10282
10283         MMPLAYER_FENTER();
10284
10285         if ((player == NULL) ||
10286                 (player->pipeline == NULL) ||
10287                 (player->pipeline->mainbin == NULL)) {
10288                 LOGE("player is null.\n");
10289                 goto ERROR;
10290         }
10291
10292         mainbin = player->pipeline->mainbin;
10293         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
10294
10295         attrs = MMPLAYER_GET_ATTRS(player);
10296         if (!attrs) {
10297                 LOGE("fail to get attributes.\n");
10298                 goto ERROR;
10299         }
10300
10301         /* Initialize Player values */
10302         __mmplayer_initialize_next_play(player);
10303
10304         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
10305
10306         if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE) {
10307                 LOGE("failed to parse profile\n");
10308                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
10309                 goto ERROR;
10310         }
10311
10312         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
10313                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player))) {
10314                 LOGE("it's dash or hls. not support.");
10315                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
10316                 goto ERROR;
10317         }
10318
10319         /* setup source */
10320         switch (player->profile.uri_type) {
10321         /* file source */
10322         case MM_PLAYER_URI_TYPE_FILE:
10323         {
10324                 LOGD("using filesrc for 'file://' handler.\n");
10325                 if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
10326                         LOGE("failed to get storage info");
10327                         break;
10328                 }
10329
10330                 element = gst_element_factory_make("filesrc", "source");
10331
10332                 if (!element) {
10333                         LOGE("failed to create filesrc\n");
10334                         break;
10335                 }
10336
10337                 g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
10338                 break;
10339         }
10340         case MM_PLAYER_URI_TYPE_URL_HTTP:
10341         {
10342                 gchar *user_agent, *cookies, **cookie_list;
10343                 gint http_timeout = DEFAULT_HTTP_TIMEOUT;
10344                 user_agent = cookies = NULL;
10345                 cookie_list = NULL;
10346
10347                 element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
10348                 if (!element) {
10349                         LOGE("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
10350                         break;
10351                 }
10352                 LOGD("using http streamming source [%s].\n", player->ini.httpsrc_element);
10353
10354                 /* get attribute */
10355                 mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
10356                 mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
10357
10358                 if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
10359                         LOGD("get timeout from ini\n");
10360                         http_timeout = player->ini.http_timeout;
10361                 }
10362
10363                 /* get attribute */
10364                 SECURE_LOGD("location : %s\n", player->profile.uri);
10365                 SECURE_LOGD("cookies : %s\n", cookies);
10366                 SECURE_LOGD("user_agent :  %s\n", user_agent);
10367                 LOGD("timeout : %d\n", http_timeout);
10368
10369                 /* setting property to streaming source */
10370                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
10371                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
10372                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
10373
10374                 /* parsing cookies */
10375                 if ((cookie_list = util_get_cookie_list((const char*)cookies)))
10376                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
10377                 if (user_agent)
10378                         g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
10379                 break;
10380         }
10381         default:
10382                 LOGE("not support uri type %d\n", player->profile.uri_type);
10383                 break;
10384         }
10385
10386         if (!element) {
10387                 LOGE("no source element was created.\n");
10388                 goto ERROR;
10389         }
10390
10391         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
10392                 LOGE("failed to add source element to pipeline\n");
10393                 gst_object_unref(GST_OBJECT(element));
10394                 element = NULL;
10395                 goto ERROR;
10396         }
10397
10398         /* take source element */
10399         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
10400         mainbin[MMPLAYER_M_SRC].gst = element;
10401
10402         element = NULL;
10403
10404         if (MMPLAYER_IS_HTTP_STREAMING(player)) {
10405                 if (player->streamer == NULL) {
10406                         player->streamer = __mm_player_streaming_create();
10407                         __mm_player_streaming_initialize(player->streamer);
10408                 }
10409
10410                 elemId = MMPLAYER_M_TYPEFIND;
10411                 element = gst_element_factory_make("typefind", "typefinder");
10412                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
10413                         G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
10414         } else {
10415                 elemId = MMPLAYER_M_AUTOPLUG;
10416                 element = __mmplayer_create_decodebin(player);
10417         }
10418
10419         /* check autoplug element is OK */
10420         if (!element) {
10421                 LOGE("can not create element(%d)\n", elemId);
10422                 goto ERROR;
10423         }
10424
10425         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
10426                 LOGE("failed to add sinkbin to pipeline\n");
10427                 gst_object_unref(GST_OBJECT(element));
10428                 element = NULL;
10429                 goto ERROR;
10430         }
10431
10432         mainbin[elemId].id = elemId;
10433         mainbin[elemId].gst = element;
10434
10435         if (gst_element_link(mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE) {
10436                 LOGE("Failed to link src - autoplug(or typefind)\n");
10437                 goto ERROR;
10438         }
10439
10440         if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
10441                 LOGE("Failed to change state of src element\n");
10442                 goto ERROR;
10443         }
10444
10445         if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
10446                 if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
10447                         LOGE("Failed to change state of decodebin\n");
10448                         goto ERROR;
10449                 }
10450         } else {
10451                 if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {
10452                         LOGE("Failed to change state of src element\n");
10453                         goto ERROR;
10454                 }
10455         }
10456
10457         player->gapless.stream_changed = TRUE;
10458         player->gapless.running = TRUE;
10459         MMPLAYER_FLEAVE();
10460         return;
10461
10462 ERROR:
10463         if (player) {
10464                 MMPLAYER_PLAYBACK_UNLOCK(player);
10465
10466                 if (!player->msg_posted) {
10467                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
10468                         player->msg_posted = TRUE;
10469                 }
10470         }
10471         return;
10472 }
10473
10474 static gboolean
10475 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
10476 {
10477         mm_player_selector_t *selector = &player->selector[type];
10478         MMPlayerGstElement *sinkbin = NULL;
10479         enum MainElementID selectorId = MMPLAYER_M_NUM;
10480         enum MainElementID sinkId = MMPLAYER_M_NUM;
10481         GstPad *srcpad = NULL;
10482         GstPad *sinkpad = NULL;
10483         gboolean send_notice = FALSE;
10484
10485         MMPLAYER_FENTER();
10486         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
10487
10488         LOGD("type %d", type);
10489
10490         switch (type) {
10491         case MM_PLAYER_TRACK_TYPE_AUDIO:
10492                 selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
10493                 sinkId = MMPLAYER_A_BIN;
10494                 sinkbin = player->pipeline->audiobin;
10495                 break;
10496         case MM_PLAYER_TRACK_TYPE_VIDEO:
10497                 selectorId = MMPLAYER_M_V_INPUT_SELECTOR;
10498                 sinkId = MMPLAYER_V_BIN;
10499                 sinkbin = player->pipeline->videobin;
10500                 send_notice = TRUE;
10501                 break;
10502         case MM_PLAYER_TRACK_TYPE_TEXT:
10503                 selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
10504                 sinkId = MMPLAYER_T_BIN;
10505                 sinkbin = player->pipeline->textbin;
10506                 break;
10507         default:
10508                 LOGE("requested type is not supportable");
10509                 return FALSE;
10510                 break;
10511         }
10512
10513         if (player->pipeline->mainbin[selectorId].gst) {
10514                 gint n;
10515
10516                 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
10517
10518                 if (selector->event_probe_id != 0)
10519                         gst_pad_remove_probe(srcpad, selector->event_probe_id);
10520                 selector->event_probe_id = 0;
10521
10522                 if ((sinkbin) && (sinkbin[sinkId].gst)) {
10523                         sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
10524
10525                         if (srcpad && sinkpad) {
10526                                 /* after getting drained signal there is no data flows, so no need to do pad_block */
10527                                 LOGD("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
10528                                 gst_pad_unlink(srcpad, sinkpad);
10529
10530                                 /* send custom event to sink pad to handle it at video sink */
10531                                 if (send_notice) {
10532                                         LOGD("send custom event to sinkpad");
10533                                         GstStructure *s = gst_structure_new_empty("application/flush-buffer");
10534                                         GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, s);
10535                                         gst_pad_send_event(sinkpad, event);
10536                                 }
10537                         }
10538
10539                         gst_object_unref(sinkpad);
10540                         sinkpad = NULL;
10541                 }
10542                 gst_object_unref(srcpad);
10543                 srcpad = NULL;
10544
10545                 LOGD("selector release");
10546
10547                 /* release and unref requests pad from the selector */
10548                 for (n = 0; n < selector->channels->len; n++) {
10549                         GstPad *sinkpad = g_ptr_array_index(selector->channels, n);
10550                         gst_element_release_request_pad((player->pipeline->mainbin[selectorId].gst), sinkpad);
10551                 }
10552                 g_ptr_array_set_size(selector->channels, 0);
10553
10554                 gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
10555                 gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
10556
10557                 player->pipeline->mainbin[selectorId].gst = NULL;
10558                 selector = NULL;
10559         }
10560
10561         return TRUE;
10562 }
10563
10564 static void
10565 __mmplayer_deactivate_old_path(mm_player_t *player)
10566 {
10567         MMPLAYER_FENTER();
10568         MMPLAYER_RETURN_IF_FAIL(player);
10569
10570         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
10571                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
10572                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
10573                 LOGE("deactivate selector error");
10574                 goto ERROR;
10575         }
10576
10577         _mmplayer_track_destroy(player);
10578         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
10579
10580         if (player->streamer) {
10581                 __mm_player_streaming_deinitialize(player->streamer);
10582                 __mm_player_streaming_destroy(player->streamer);
10583                 player->streamer = NULL;
10584         }
10585
10586         MMPLAYER_PLAYBACK_LOCK(player);
10587         MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
10588
10589         MMPLAYER_FLEAVE();
10590         return;
10591
10592 ERROR:
10593
10594         if (!player->msg_posted) {
10595                 MMMessageParamType msg = {0,};
10596
10597                 /*post error*/
10598                 msg.code = MM_ERROR_PLAYER_INTERNAL;
10599                 LOGE("next_uri_play> deactivate error");
10600
10601                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
10602                 player->msg_posted = TRUE;
10603         }
10604         return;
10605 }
10606
10607 int _mmplayer_set_file_buffering_path(MMHandleType hplayer, const char* file_path)
10608 {
10609         int result = MM_ERROR_NONE;
10610         mm_player_t* player = (mm_player_t*) hplayer;
10611         MMPLAYER_FENTER();
10612
10613         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10614
10615         if (file_path) {
10616                 player->http_file_buffering_path = (gchar*)file_path;
10617                 LOGD("temp file path: %s\n", player->http_file_buffering_path);
10618         }
10619         MMPLAYER_FLEAVE();
10620         return result;
10621 }
10622
10623 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
10624 {
10625         int result = MM_ERROR_NONE;
10626         mm_player_t* player = (mm_player_t*) hplayer;
10627         MMPLAYER_FENTER();
10628
10629         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10630
10631         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
10632         if (mmf_attrs_commit(player->attrs)) {
10633                 LOGE("failed to commit the original uri.\n");
10634                 result = MM_ERROR_PLAYER_INTERNAL;
10635         } else {
10636                 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
10637                         LOGE("failed to add the original uri in the uri list.\n");
10638         }
10639
10640         MMPLAYER_FLEAVE();
10641         return result;
10642 }
10643
10644 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
10645 {
10646         mm_player_t* player = (mm_player_t*) hplayer;
10647         guint num_of_list = 0;
10648
10649         MMPLAYER_FENTER();
10650
10651         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10652         MMPLAYER_RETURN_VAL_IF_FAIL(uri, MM_ERROR_INVALID_ARGUMENT);
10653
10654         if (player->pipeline && player->pipeline->textbin) {
10655                 LOGE("subtitle path is enabled.\n");
10656                 return MM_ERROR_PLAYER_INVALID_STATE;
10657         }
10658
10659         num_of_list = g_list_length(player->uri_info.uri_list);
10660
10661         if (is_first_path == TRUE) {
10662                 if (num_of_list == 0) {
10663                         player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
10664                         LOGD("add original path : %s", uri);
10665                 } else {
10666                         player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
10667                         player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
10668
10669                         LOGD("change original path : %s", uri);
10670                 }
10671         } else {
10672                 MMHandleType attrs = 0;
10673                 attrs = MMPLAYER_GET_ATTRS(player);
10674
10675                 if (num_of_list == 0) {
10676                         char *original_uri = NULL;
10677
10678                         if (attrs) {
10679                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
10680
10681                                 if (!original_uri) {
10682                                         LOGE("there is no original uri.");
10683                                         return MM_ERROR_PLAYER_INVALID_STATE;
10684                                 }
10685
10686                                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
10687                                 player->uri_info.uri_idx = 0;
10688
10689                                 LOGD("add original path at first : %s(%d)", original_uri);
10690                         }
10691                 }
10692
10693                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
10694                 LOGD("add new path : %s(total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
10695         }
10696
10697         MMPLAYER_FLEAVE();
10698         return MM_ERROR_NONE;
10699 }
10700
10701 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
10702 {
10703         mm_player_t* player = (mm_player_t*) hplayer;
10704         char *next_uri = NULL;
10705         guint num_of_list = 0;
10706
10707         MMPLAYER_FENTER();
10708         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10709
10710         num_of_list = g_list_length(player->uri_info.uri_list);
10711
10712         if (num_of_list > 0) {
10713                 gint uri_idx = player->uri_info.uri_idx;
10714
10715                 if (uri_idx < num_of_list-1)
10716                         uri_idx++;
10717                 else
10718                         uri_idx = 0;
10719
10720                 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
10721                 LOGE("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
10722
10723                 *uri = g_strdup(next_uri);
10724         }
10725
10726         MMPLAYER_FLEAVE();
10727         return MM_ERROR_NONE;
10728 }
10729
10730 static void
10731 __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad,
10732 GstCaps *caps, gpointer data)
10733 {
10734         mm_player_t* player = (mm_player_t*)data;
10735         const gchar* klass = NULL;
10736         const gchar* mime = NULL;
10737         gchar* caps_str = NULL;
10738
10739         klass = gst_element_factory_get_metadata(gst_element_get_factory(elem), GST_ELEMENT_METADATA_KLASS);
10740         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
10741         caps_str = gst_caps_to_string(caps);
10742
10743         LOGW("unknown type of caps : %s from %s",
10744                                         caps_str, GST_ELEMENT_NAME(elem));
10745
10746         MMPLAYER_FREEIF(caps_str);
10747
10748         /* There is no available codec. */
10749         __mmplayer_check_not_supported_codec(player, klass, mime);
10750 }
10751
10752 static gboolean
10753 __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad,
10754 GstCaps * caps,  gpointer data)
10755 {
10756         mm_player_t* player = (mm_player_t*)data;
10757         const char* mime = NULL;
10758         gboolean ret = TRUE;
10759
10760         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
10761         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
10762
10763         if (g_str_has_prefix(mime, "audio")) {
10764                 GstStructure* caps_structure = NULL;
10765                 gint samplerate = 0;
10766                 gint channels = 0;
10767                 gchar *caps_str = NULL;
10768
10769                 caps_structure = gst_caps_get_structure(caps, 0);
10770                 gst_structure_get_int(caps_structure, "rate", &samplerate);
10771                 gst_structure_get_int(caps_structure, "channels", &channels);
10772
10773                 if ((channels > 0 && samplerate == 0)) {
10774                         LOGD("exclude audio...");
10775                         ret = FALSE;
10776                 }
10777
10778                 caps_str = gst_caps_to_string(caps);
10779                 /* set it directly because not sent by TAG */
10780                 if (g_strrstr(caps_str, "mobile-xmf"))
10781                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
10782                 MMPLAYER_FREEIF(caps_str);
10783         } else if (g_str_has_prefix(mime, "video") && !player->ini.video_playback_supported) {
10784                 MMMessageParamType msg_param;
10785                 memset(&msg_param, 0, sizeof(MMMessageParamType));
10786                 msg_param.code = MM_ERROR_NOT_SUPPORT_API;
10787                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
10788                 LOGD("video file is not supported on this device");
10789                 ret = FALSE;
10790         } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
10791                 LOGD("already video linked");
10792                 ret = FALSE;
10793         } else {
10794                 LOGD("found new stream");
10795         }
10796
10797         return ret;
10798 }
10799
10800 static int
10801 __mmplayer_check_codec_info(mm_player_t* player, const char* klass, GstCaps* caps, char* factory_name)
10802 {
10803         int ret = MM_ERROR_NONE;
10804         int idx = 0;
10805         int codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
10806
10807         if ((g_strrstr(klass, "Codec/Decoder/Audio"))) {
10808                 GstStructure* str = NULL;
10809                 gint channels = 0;
10810                 mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type);
10811
10812                 LOGD("audio codec type: %d", codec_type);
10813                 if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
10814                         /* sw codec will be skipped */
10815                         for (idx = 0; player->ini.audiocodec_element_sw[idx][0] != '\0'; idx++) {
10816                                 if (strstr(factory_name, player->ini.audiocodec_element_sw[idx])) {
10817                                         LOGW("skipping sw acodec:[%s] by codec type", factory_name);
10818                                         ret = MM_ERROR_PLAYER_INTERNAL;
10819                                         goto DONE;
10820                                 }
10821                         }
10822                 } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
10823                         /* hw codec will be skipped */
10824                         if (strcmp(player->ini.audiocodec_element_hw, "") &&
10825                             g_strrstr(factory_name, player->ini.audiocodec_element_hw)) {
10826                                 LOGW("skipping hw acodec:[%s] by codec type", factory_name);
10827                                 ret = MM_ERROR_PLAYER_INTERNAL;
10828                                 goto DONE;
10829                         }
10830                 }
10831
10832                 str = gst_caps_get_structure(caps, 0);
10833                 if (str) {
10834                         gst_structure_get_int(str, "channels", &channels);
10835
10836                         LOGD("check audio ch : %d %d\n", player->max_audio_channels, channels);
10837                         if (player->max_audio_channels < channels)
10838                                 player->max_audio_channels = channels;
10839                 }
10840                 /* set stream information */
10841                 if (!player->audiodec_linked)
10842                         __mmplayer_set_audio_attrs(player, caps);
10843
10844                 /* update codec info */
10845                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
10846                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
10847                 player->audiodec_linked = 1;
10848
10849         } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
10850
10851                 mm_attrs_get_int_by_name(player->attrs, "video_codec_type", &codec_type);
10852
10853                 LOGD("video codec type: %d", codec_type);
10854                 if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
10855                         /* sw codec is skipped */
10856                         for (idx = 0; player->ini.videocodec_element_sw[idx][0] != '\0'; idx++) {
10857                                 if (strstr(factory_name, player->ini.videocodec_element_sw[idx])) {
10858                                         LOGW("skipping sw vcodec:[%s] by codec type", factory_name);
10859                                         ret = MM_ERROR_PLAYER_INTERNAL;
10860                                         goto DONE;
10861                                 }
10862                         }
10863                 } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
10864                         /* hw codec is skipped */
10865                         if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
10866                                 LOGW("skipping hw vcodec:[%s] by codec type", factory_name);
10867                                 ret = MM_ERROR_PLAYER_INTERNAL;
10868                                 goto DONE;
10869                         }
10870                 }
10871
10872                 if ((strlen(player->ini.videocodec_element_hw) > 0) &&
10873                         (g_strrstr(factory_name, player->ini.videocodec_element_hw))) {
10874
10875                         /* mark video decoder for acquire */
10876                         if (player->video_decoder_resource == NULL) {
10877                                 if (mm_resource_manager_mark_for_acquire(player->resource_manager,
10878                                                 MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER,
10879                                                 MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
10880                                                 &player->video_decoder_resource)
10881                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
10882                                         LOGE("could not mark video_decoder resource for acquire");
10883                                         ret = MM_ERROR_PLAYER_INTERNAL;
10884                                         goto DONE;
10885                                 }
10886                         } else {
10887                                 LOGW("video decoder resource is already acquired, skip it.");
10888                                 ret = MM_ERROR_PLAYER_INTERNAL;
10889                                 goto DONE;
10890                         }
10891
10892                         player->interrupted_by_resource = FALSE;
10893                         /* acquire resources for video playing */
10894                         if (mm_resource_manager_commit(player->resource_manager)
10895                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
10896                                 LOGE("could not acquire resources for video decoding\n");
10897                                 ret = MM_ERROR_PLAYER_INTERNAL;
10898                                 goto DONE;
10899                         }
10900                 }
10901
10902                 /* update codec info */
10903                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
10904                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
10905                 player->videodec_linked = 1;
10906         }
10907
10908 DONE:
10909         return ret;
10910 }
10911
10912 static gint
10913 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad,
10914 GstCaps* caps, GstElementFactory* factory, gpointer data)
10915 {
10916         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
10917          We are defining our own and will be removed when it actually exposed */
10918         typedef enum {
10919                 GST_AUTOPLUG_SELECT_TRY,
10920                 GST_AUTOPLUG_SELECT_EXPOSE,
10921                 GST_AUTOPLUG_SELECT_SKIP
10922         } GstAutoplugSelectResult;
10923
10924         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
10925         mm_player_t* player = (mm_player_t*)data;
10926
10927         gchar* factory_name = NULL;
10928         gchar* caps_str = NULL;
10929         const gchar* klass = NULL;
10930         gint idx = 0;
10931
10932         factory_name = GST_OBJECT_NAME(factory);
10933         klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
10934         caps_str = gst_caps_to_string(caps);
10935
10936         LOGD("[handle: %p] found new element [%s] to link", player, factory_name);
10937
10938         /* store type string */
10939         if (player->type == NULL) {
10940                 player->type = gst_caps_to_string(caps);
10941                 __mmplayer_update_content_type_info(player);
10942         }
10943
10944         /* filtering exclude keyword */
10945         for (idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++) {
10946                 if (strstr(factory_name, player->ini.exclude_element_keyword[idx])) {
10947                         LOGW("skipping [%s] by exculde keyword [%s]\n",
10948                                         factory_name, player->ini.exclude_element_keyword[idx]);
10949
10950                         result = GST_AUTOPLUG_SELECT_SKIP;
10951                         goto DONE;
10952                 }
10953         }
10954
10955         /* exclude webm format */
10956         /* NOTE : MSL have to post MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT
10957          * because webm format is not supportable.
10958          * If webm is disabled in "autoplug-continue", there is no state change
10959          * failure or error because the decodebin will expose the pad directly.
10960          * It make MSL invoke _prepare_async_callback.
10961          * So, we need to disable webm format in "autoplug-select" */
10962         if (caps_str && strstr(caps_str, "webm")) {
10963                 LOGW("webm is not supported");
10964                 result = GST_AUTOPLUG_SELECT_SKIP;
10965                 goto DONE;
10966         }
10967
10968         /* check factory class for filtering */
10969         /* NOTE : msl don't need to use image plugins.
10970          * So, those plugins should be skipped for error handling.
10971          */
10972         if (g_strrstr(klass, "Codec/Decoder/Image")) {
10973                 LOGD("skipping [%s] by not required\n", factory_name);
10974                 result = GST_AUTOPLUG_SELECT_SKIP;
10975                 goto DONE;
10976         }
10977
10978         if ((MMPLAYER_IS_MS_BUFF_SRC(player)) &&
10979                 (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser")))) {
10980                 // TO CHECK : subtitle if needed, add subparse exception.
10981                 LOGD("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
10982                 result = GST_AUTOPLUG_SELECT_SKIP;
10983                 goto DONE;
10984         }
10985
10986         if (g_strrstr(factory_name, "mpegpsdemux")) {
10987                 LOGD("skipping PS container - not support\n");
10988                 result = GST_AUTOPLUG_SELECT_SKIP;
10989                 goto DONE;
10990         }
10991
10992         if (g_strrstr(factory_name, "mssdemux"))
10993                 player->smooth_streaming = TRUE;
10994
10995         if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
10996                 (g_strrstr(klass, "Codec/Decoder/Video"))) {
10997                 gint stype = 0;
10998                 gint width = 0;
10999                 GstStructure *str = NULL;
11000                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
11001
11002                 /* don't make video because of not required */
11003                 if ((stype == MM_DISPLAY_SURFACE_NULL) &&
11004                         (player->set_mode.media_packet_video_stream == FALSE)) {
11005                         LOGD("no video because it's not required. -> return expose");
11006                         result = GST_AUTOPLUG_SELECT_EXPOSE;
11007                         goto DONE;
11008                 }
11009
11010                 /* get w/h for omx state-tune */
11011                 /* FIXME: deprecated? */
11012                 str = gst_caps_get_structure(caps, 0);
11013                 gst_structure_get_int(str, "width", &width);
11014
11015                 if (width != 0) {
11016                         if (player->v_stream_caps) {
11017                                 gst_caps_unref(player->v_stream_caps);
11018                                 player->v_stream_caps = NULL;
11019                         }
11020
11021                         player->v_stream_caps = gst_caps_copy(caps);
11022                         LOGD("take caps for video state tune");
11023                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
11024                 }
11025         }
11026
11027         if (g_strrstr(klass, "Codec/Decoder")) {
11028                 if (__mmplayer_check_codec_info(player, klass, caps, factory_name) != MM_ERROR_NONE) {
11029                         LOGD("skipping %s codec", factory_name);
11030                         result = GST_AUTOPLUG_SELECT_SKIP;
11031                         goto DONE;
11032                 }
11033         }
11034
11035 DONE:
11036         MMPLAYER_FREEIF(caps_str);
11037
11038         return result;
11039 }
11040
11041 static void
11042 __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad,
11043 gpointer data)
11044 {
11045         //mm_player_t* player = (mm_player_t*)data;
11046         GstCaps* caps = NULL;
11047
11048         LOGD("[Decodebin2] pad-removed signal\n");
11049
11050         caps = gst_pad_query_caps(new_pad, NULL);
11051         if (caps) {
11052                 gchar* caps_str = NULL;
11053                 caps_str = gst_caps_to_string(caps);
11054
11055                 LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem));
11056
11057                 MMPLAYER_FREEIF(caps_str);
11058                 gst_caps_unref(caps);
11059         }
11060 }
11061
11062 static void
11063 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
11064 {
11065         mm_player_t* player = (mm_player_t*)data;
11066         GstIterator *iter = NULL;
11067         GValue item = { 0, };
11068         GstPad *pad = NULL;
11069         gboolean done = FALSE;
11070         gboolean is_all_drained = TRUE;
11071
11072         MMPLAYER_FENTER();
11073         MMPLAYER_RETURN_IF_FAIL(player);
11074
11075         LOGD("__mmplayer_gst_decode_drained");
11076
11077         if (player->use_deinterleave == TRUE) {
11078                 LOGD("group playing mode.");
11079                 return;
11080         }
11081
11082         if (!MMPLAYER_CMD_TRYLOCK(player)) {
11083                 LOGW("Fail to get cmd lock");
11084                 return;
11085         }
11086
11087         if (!player->gapless.reconfigure && /* If it is already checked, skip verify. */
11088                 !__mmplayer_verify_next_play_path(player)) {
11089                 LOGD("decoding is finished.");
11090                 __mmplayer_reset_gapless_state(player);
11091                 MMPLAYER_CMD_UNLOCK(player);
11092                 return;
11093         }
11094
11095         player->gapless.reconfigure = TRUE;
11096
11097         /* check decodebin src pads whether they received EOS or not */
11098         iter = gst_element_iterate_src_pads(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
11099
11100         while (!done) {
11101                 switch (gst_iterator_next(iter, &item)) {
11102                 case GST_ITERATOR_OK:
11103                         pad = g_value_get_object(&item);
11104                         if (pad && !GST_PAD_IS_EOS(pad)) {
11105                                 LOGW("[%s:%s] not received EOS yet.", GST_DEBUG_PAD_NAME(pad));
11106                                 is_all_drained = FALSE;
11107                                 break;
11108                         }
11109                         g_value_reset(&item);
11110                         break;
11111                 case GST_ITERATOR_RESYNC:
11112                         gst_iterator_resync(iter);
11113                         break;
11114                 case GST_ITERATOR_ERROR:
11115                 case GST_ITERATOR_DONE:
11116                         done = TRUE;
11117                         break;
11118                 }
11119         }
11120         g_value_unset(&item);
11121         gst_iterator_free(iter);
11122
11123         if (!is_all_drained) {
11124                 LOGD("Wait util the all pads get EOS.");
11125                 MMPLAYER_CMD_UNLOCK(player);
11126                 MMPLAYER_FLEAVE();
11127                 return;
11128         }
11129
11130         player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_AUDIO] = FALSE;
11131         player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_VIDEO] = FALSE;
11132
11133         /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
11134         MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL); /* post message for gapless */
11135         __mmplayer_deactivate_old_path(player);
11136         MMPLAYER_CMD_UNLOCK(player);
11137
11138         MMPLAYER_FLEAVE();
11139 }
11140
11141 static void
11142 __mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
11143 {
11144         mm_player_t* player = (mm_player_t*)data;
11145         const gchar* klass = NULL;
11146         gchar* factory_name = NULL;
11147
11148         klass = gst_element_factory_get_metadata(gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
11149         factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
11150
11151         LOGD("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
11152
11153         if (__mmplayer_add_dump_buffer_probe(player, element))
11154                 LOGD("add buffer probe");
11155
11156         //<-
11157         if (g_strrstr(klass, "Codec/Decoder/Audio")) {
11158                 gchar* selected = NULL;
11159                 selected = g_strdup(GST_ELEMENT_NAME(element));
11160                 player->audio_decoders = g_list_append(player->audio_decoders, selected);
11161         }
11162         //-> temp code
11163
11164         if (g_strrstr(klass, "Parser")) {
11165                 gchar* selected = NULL;
11166
11167                 selected = g_strdup(factory_name);
11168                 player->parsers = g_list_append(player->parsers, selected);
11169         }
11170
11171         if (g_strrstr(klass, "Demuxer/Adaptive")) {
11172                 player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX;
11173                 player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst = element;
11174
11175                 LOGD("set max variant limit: %d, %d %d", player->adaptive_info.limit.bandwidth,
11176                                                 player->adaptive_info.limit.width, player->adaptive_info.limit.height);
11177
11178                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
11179                                                 "max-bandwidth", player->adaptive_info.limit.bandwidth,
11180                                                 "max-video-width", player->adaptive_info.limit.width,
11181                                                 "max-video-height", player->adaptive_info.limit.height, NULL);
11182
11183         } else if (g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) {
11184                 /* FIXIT : first value will be overwritten if there's more
11185                  * than 1 demuxer/parser
11186                  */
11187
11188                 //LOGD("plugged element is demuxer. take it\n");
11189                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
11190                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
11191
11192                 /*Added for multi audio support */ // Q. del?
11193                 if (g_strrstr(klass, "Demux")) {
11194                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
11195                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
11196                 }
11197         }
11198
11199         if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) {
11200                 int surface_type = 0;
11201
11202                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
11203         }
11204
11205         // to support trust-zone only
11206         if (g_strrstr(factory_name, "asfdemux")) {
11207                 LOGD("set file-location %s\n", player->profile.uri);
11208                 g_object_set(G_OBJECT(element), "file-location", player->profile.uri, NULL);
11209
11210                 if (player->video_hub_download_mode == TRUE)
11211                         g_object_set(G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
11212         } else if (g_strrstr(factory_name, "legacyh264parse")) {
11213                 LOGD("[%s] output-format to legacyh264parse\n", "mssdemux");
11214                 g_object_set(G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
11215         } else if (g_strrstr(factory_name, "mpegaudioparse")) {
11216                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
11217                         (__mmplayer_is_only_mp3_type(player->type))) {
11218                         LOGD("[mpegaudioparse] set streaming pull mode.");
11219                         g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
11220                 }
11221         } else if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
11222                 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
11223         }
11224
11225         if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
11226                 (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))) {
11227                 LOGD("plugged element is multiqueue. take it\n");
11228
11229                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
11230                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
11231
11232                 if (!MMPLAYER_IS_HTTP_PD(player) &&
11233                         ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
11234                         (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)))) {
11235                         /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
11236                         __mm_player_streaming_set_multiqueue(player->streamer,
11237                                 element,
11238                                 TRUE,
11239                                 player->ini.http_buffering_time,
11240                                 1.0,
11241                                 player->ini.http_buffering_limit);
11242
11243                         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
11244                 }
11245         }
11246
11247         return;
11248 }
11249
11250 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
11251 {
11252         MMPLAYER_FENTER();
11253         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11254
11255         if (MMPLAYER_IS_STREAMING(player))
11256                 return FALSE;
11257
11258         /* This callback can be set to music player only. */
11259         if ((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO) {
11260                 LOGW("audio callback is not supported for video");
11261                 return FALSE;
11262         }
11263
11264         if (player->audio_stream_cb) {
11265                 GstPad *pad = NULL;
11266
11267                 pad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
11268
11269                 if (!pad) {
11270                         LOGE("failed to get sink pad from audiosink to probe data\n");
11271                         return FALSE;
11272                 }
11273                 player->audio_cb_probe_id = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
11274                         __mmplayer_audio_stream_probe, player, NULL);
11275
11276                 gst_object_unref(pad);
11277
11278                 pad = NULL;
11279         } else {
11280                 LOGE("There is no audio callback to configure.\n");
11281                 return FALSE;
11282         }
11283
11284         MMPLAYER_FLEAVE();
11285
11286         return TRUE;
11287 }
11288
11289 static void
11290 __mmplayer_release_misc(mm_player_t* player)
11291 {
11292         int i;
11293         bool cur_mode = player->set_mode.rich_audio;
11294         MMPLAYER_FENTER();
11295
11296         MMPLAYER_RETURN_IF_FAIL(player);
11297
11298         player->video_stream_cb = NULL;
11299         player->video_stream_cb_user_param = NULL;
11300         player->video_stream_prerolled = FALSE;
11301
11302         player->audio_stream_cb = NULL;
11303         player->audio_stream_render_cb_ex = NULL;
11304         player->audio_stream_cb_user_param = NULL;
11305         player->audio_stream_sink_sync = false;
11306
11307         player->video_stream_changed_cb = NULL;
11308         player->video_stream_changed_cb_user_param = NULL;
11309
11310         player->audio_stream_changed_cb = NULL;
11311         player->audio_stream_changed_cb_user_param = NULL;
11312
11313         player->sent_bos = FALSE;
11314         player->playback_rate = DEFAULT_PLAYBACK_RATE;
11315
11316         player->doing_seek = FALSE;
11317
11318         player->total_bitrate = 0;
11319         player->total_maximum_bitrate = 0;
11320
11321         player->not_found_demuxer = 0;
11322
11323         player->last_position = 0;
11324         player->duration = 0;
11325         player->http_content_size = 0;
11326         player->not_supported_codec = MISSING_PLUGIN_NONE;
11327         player->can_support_codec = FOUND_PLUGIN_NONE;
11328         player->pending_seek.is_pending = FALSE;
11329         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
11330         player->pending_seek.pos = 0;
11331         player->msg_posted = FALSE;
11332         player->has_many_types = FALSE;
11333         player->max_audio_channels = 0;
11334         player->video_share_api_delta = 0;
11335         player->video_share_clock_delta = 0;
11336         player->is_subtitle_force_drop = FALSE;
11337         player->play_subtitle = FALSE;
11338         player->adjust_subtitle_pos = 0;
11339         player->last_multiwin_status = FALSE;
11340         player->has_closed_caption = FALSE;
11341         player->set_mode.media_packet_video_stream = FALSE;
11342         player->profile.uri_type = MM_PLAYER_URI_TYPE_NONE;
11343         memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
11344         /* recover mode */
11345         player->set_mode.rich_audio = cur_mode;
11346
11347         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
11348                 player->bitrate[i] = 0;
11349                 player->maximum_bitrate[i] = 0;
11350         }
11351
11352         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
11353
11354         /* remove media stream cb(appsrc cb) */
11355         for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++) {
11356                 player->media_stream_buffer_status_cb[i] = NULL;
11357                 player->media_stream_seek_data_cb[i] = NULL;
11358                 player->buffer_cb_user_param[i] = NULL;
11359                 player->seek_cb_user_param[i] = NULL;
11360         }
11361         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
11362
11363         /* free memory related to audio effect */
11364         MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
11365
11366         if (player->adaptive_info.var_list) {
11367                 g_list_free_full(player->adaptive_info.var_list, g_free);
11368                 player->adaptive_info.var_list = NULL;
11369         }
11370
11371         player->adaptive_info.limit.bandwidth = ADAPTIVE_VARIANT_DEFAULT_VALUE;
11372         player->adaptive_info.limit.width = ADAPTIVE_VARIANT_DEFAULT_VALUE;
11373         player->adaptive_info.limit.height = ADAPTIVE_VARIANT_DEFAULT_VALUE;
11374
11375         /* Reset video360 settings to their defaults in case if the pipeline is to be
11376          * re-created.
11377          * */
11378         player->video360_metadata.is_spherical = -1;
11379         player->is_openal_plugin_used = FALSE;
11380
11381         player->is_content_spherical = FALSE;
11382         player->is_video360_enabled = TRUE;
11383         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
11384         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
11385         player->video360_yaw_radians = PLAYER_SPHERICAL_DEFAULT_YAW;
11386         player->video360_pitch_radians = PLAYER_SPHERICAL_DEFAULT_PITCH;
11387         player->video360_zoom = 1.0f;
11388         player->video360_horizontal_fov = PLAYER_SPHERICAL_DEFAULT_H_FOV;
11389         player->video360_vertical_fov = PLAYER_SPHERICAL_DEFAULT_V_FOV;
11390
11391         player->sound.rg_enable = false;
11392
11393         MMPLAYER_FLEAVE();
11394 }
11395
11396 static void
11397 __mmplayer_release_misc_post(mm_player_t* player)
11398 {
11399         char *original_uri = NULL;
11400         MMPLAYER_FENTER();
11401
11402         /* player->pipeline is already released before. */
11403
11404         MMPLAYER_RETURN_IF_FAIL(player);
11405
11406         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
11407
11408         /* clean found parsers */
11409         if (player->parsers) {
11410                 GList *parsers = player->parsers;
11411                 for (; parsers; parsers = g_list_next(parsers)) {
11412                         gchar *name = parsers->data;
11413                         MMPLAYER_FREEIF(name);
11414                 }
11415                 g_list_free(player->parsers);
11416                 player->parsers = NULL;
11417         }
11418
11419         /* clean found audio decoders */
11420         if (player->audio_decoders) {
11421                 GList *a_dec = player->audio_decoders;
11422                 for (; a_dec; a_dec = g_list_next(a_dec)) {
11423                         gchar *name = a_dec->data;
11424                         MMPLAYER_FREEIF(name);
11425                 }
11426                 g_list_free(player->audio_decoders);
11427                 player->audio_decoders = NULL;
11428         }
11429
11430         /* clean the uri list except original uri */
11431         if (player->uri_info.uri_list) {
11432                 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
11433
11434                 if (player->attrs) {
11435                         mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
11436                         LOGD("restore original uri = %s\n", original_uri);
11437
11438                         if (mmf_attrs_commit(player->attrs))
11439                                 LOGE("failed to commit the original uri.\n");
11440                 }
11441
11442                 GList *uri_list = player->uri_info.uri_list;
11443                 for (; uri_list; uri_list = g_list_next(uri_list)) {
11444                         gchar *uri = uri_list->data;
11445                         MMPLAYER_FREEIF(uri);
11446                 }
11447                 g_list_free(player->uri_info.uri_list);
11448                 player->uri_info.uri_list = NULL;
11449         }
11450
11451         /* clear the audio stream buffer list */
11452         __mmplayer_audio_stream_clear_buffer(player, FALSE);
11453
11454         /* clear the video stream bo list */
11455         __mmplayer_video_stream_destroy_bo_list(player);
11456         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
11457
11458         if (player->profile.input_mem.buf) {
11459                 free(player->profile.input_mem.buf);
11460                 player->profile.input_mem.buf = NULL;
11461         }
11462         player->profile.input_mem.len = 0;
11463         player->profile.input_mem.offset = 0;
11464
11465         player->uri_info.uri_idx = 0;
11466         MMPLAYER_FLEAVE();
11467 }
11468
11469 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
11470 {
11471         GstElement *element = NULL;
11472         GstPad *sinkpad;
11473
11474         LOGD("creating %s to plug\n", name);
11475
11476         element = gst_element_factory_make(name, NULL);
11477         if (!element) {
11478                 LOGE("failed to create queue\n");
11479                 return NULL;
11480         }
11481
11482         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY)) {
11483                 LOGE("failed to set state READY to %s\n", name);
11484                 gst_object_unref(element);
11485                 return NULL;
11486         }
11487
11488         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element)) {
11489                 LOGE("failed to add %s\n", name);
11490                 gst_object_unref(element);
11491                 return NULL;
11492         }
11493
11494         sinkpad = gst_element_get_static_pad(element, "sink");
11495
11496         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
11497                 LOGE("failed to link %s\n", name);
11498                 gst_object_unref(sinkpad);
11499                 gst_object_unref(element);
11500                 return NULL;
11501         }
11502
11503         LOGD("linked %s to pipeline successfully\n", name);
11504
11505         gst_object_unref(sinkpad);
11506
11507         return element;
11508 }
11509
11510 gboolean
11511 __mmplayer_check_subtitle(mm_player_t* player)
11512 {
11513         MMHandleType attrs = 0;
11514         char *subtitle_uri = NULL;
11515
11516         MMPLAYER_FENTER();
11517
11518         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11519
11520         /* get subtitle attribute */
11521         attrs = MMPLAYER_GET_ATTRS(player);
11522         if (!attrs)
11523                 return FALSE;
11524
11525         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
11526         if (!subtitle_uri || !strlen(subtitle_uri))
11527                 return FALSE;
11528
11529         LOGD("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
11530         player->is_external_subtitle_present = TRUE;
11531
11532         MMPLAYER_FLEAVE();
11533
11534         return TRUE;
11535 }
11536
11537 static gboolean
11538 __mmplayer_can_extract_pcm(mm_player_t* player)
11539 {
11540         MMHandleType attrs = 0;
11541         gboolean sound_extraction = FALSE;
11542
11543         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11544
11545         attrs = MMPLAYER_GET_ATTRS(player);
11546         if (!attrs) {
11547                 LOGE("fail to get attributes.");
11548                 return FALSE;
11549         }
11550
11551         /* get sound_extraction property */
11552         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
11553
11554         if (!sound_extraction) {
11555                 LOGD("checking pcm extraction mode : %d ", sound_extraction);
11556                 return FALSE;
11557         }
11558
11559         return TRUE;
11560 }
11561
11562 static gboolean
11563 __mmplayer_handle_streaming_error(mm_player_t* player, GstMessage * message)
11564 {
11565         LOGD("\n");
11566         MMMessageParamType msg_param;
11567         gchar *msg_src_element = NULL;
11568         GstStructure *s = NULL;
11569         guint error_id = 0;
11570         gchar *error_string = NULL;
11571
11572         MMPLAYER_FENTER();
11573
11574         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11575         MMPLAYER_RETURN_VAL_IF_FAIL(message, FALSE);
11576
11577         s = gst_structure_copy(gst_message_get_structure(message));
11578
11579
11580         if (!gst_structure_get_uint(s, "error_id", &error_id))
11581                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
11582
11583         switch (error_id) {
11584         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
11585                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
11586                 break;
11587         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
11588                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
11589                 break;
11590         case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
11591                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
11592                 break;
11593         case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
11594                 msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
11595                 break;
11596         case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
11597                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
11598                 break;
11599         case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
11600                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
11601                 break;
11602         case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
11603                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
11604                 break;
11605         case MMPLAYER_STREAMING_ERROR_INVALID_URL:
11606                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
11607                 break;
11608         case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
11609                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
11610                 break;
11611         case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
11612                 msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
11613                 break;
11614         case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
11615                 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
11616                 break;
11617         case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
11618                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
11619                 break;
11620         case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
11621                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
11622                 break;
11623         case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
11624                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
11625                 break;
11626         case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
11627                 msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
11628                 break;
11629         case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
11630                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
11631                 break;
11632         case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
11633                 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
11634                 break;
11635         case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
11636                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
11637                 break;
11638         case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
11639                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
11640                 break;
11641         case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
11642                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
11643                 break;
11644         case MMPLAYER_STREAMING_ERROR_GONE:
11645                 msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
11646                 break;
11647         case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
11648                 msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
11649                 break;
11650         case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
11651                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
11652                 break;
11653         case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
11654                 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
11655                 break;
11656         case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
11657                 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
11658                 break;
11659         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
11660                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
11661                 break;
11662         case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
11663                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
11664                 break;
11665         case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
11666                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
11667                 break;
11668         case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
11669                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
11670                 break;
11671         case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
11672                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
11673                 break;
11674         case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
11675                 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
11676                 break;
11677         case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
11678                 msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
11679                 break;
11680         case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
11681                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
11682                 break;
11683         case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
11684                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
11685                 break;
11686         case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
11687                 msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
11688                 break;
11689         case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
11690                 msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
11691                 break;
11692         case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
11693                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
11694                 break;
11695         case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
11696                 msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
11697                 break;
11698         case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
11699                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
11700                 break;
11701         case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
11702                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
11703                 break;
11704         case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
11705                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
11706                 break;
11707         case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
11708                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
11709                 break;
11710         case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
11711                 msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
11712                 break;
11713         case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
11714                 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
11715                 break;
11716         case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
11717                 msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
11718                 break;
11719         default:
11720                 {
11721                         gst_structure_free(s);
11722                         return MM_ERROR_PLAYER_STREAMING_FAIL;
11723                 }
11724         }
11725
11726         error_string = g_strdup(gst_structure_get_string(s, "error_string"));
11727         if (error_string)
11728                 msg_param.data = (void *) error_string;
11729
11730         if (message->src) {
11731                 msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
11732
11733                 LOGE("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
11734                         msg_src_element, msg_param.code, (char*)msg_param.data);
11735         }
11736
11737         /* post error to application */
11738         if (!player->msg_posted) {
11739                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
11740
11741                 /* don't post more if one was sent already */
11742                 player->msg_posted = TRUE;
11743         } else
11744                 LOGD("skip error post because it's sent already.\n");
11745
11746         gst_structure_free(s);
11747         MMPLAYER_FLEAVE();
11748         g_free(error_string);
11749
11750         return TRUE;
11751
11752 }
11753
11754 static void
11755 __mmplayer_handle_eos_delay(mm_player_t* player, int delay_in_ms)
11756 {
11757         MMPLAYER_RETURN_IF_FAIL(player);
11758
11759         /* post now if delay is zero */
11760         if (delay_in_ms == 0 || player->set_mode.pcm_extraction) {
11761                 LOGD("eos delay is zero. posting EOS now\n");
11762                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
11763
11764                 if (player->set_mode.pcm_extraction)
11765                         __mmplayer_cancel_eos_timer(player);
11766
11767                 return;
11768         }
11769
11770         /* cancel if existing */
11771         __mmplayer_cancel_eos_timer(player);
11772
11773         /* init new timeout */
11774         /* NOTE : consider give high priority to this timer */
11775         LOGD("posting EOS message after [%d] msec\n", delay_in_ms);
11776
11777         player->eos_timer = g_timeout_add(delay_in_ms,
11778                 __mmplayer_eos_timer_cb, player);
11779
11780         player->context.global_default = g_main_context_default();
11781         LOGD("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
11782
11783         /* check timer is valid. if not, send EOS now */
11784         if (player->eos_timer == 0) {
11785                 LOGW("creating timer for delayed EOS has failed. sending EOS now\n");
11786                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
11787         }
11788 }
11789
11790 static void
11791 __mmplayer_cancel_eos_timer(mm_player_t* player)
11792 {
11793         MMPLAYER_RETURN_IF_FAIL(player);
11794
11795         if (player->eos_timer) {
11796                 LOGD("cancel eos timer");
11797                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
11798                 player->eos_timer = 0;
11799         }
11800
11801         return;
11802 }
11803
11804 static gboolean
11805 __mmplayer_eos_timer_cb(gpointer u_data)
11806 {
11807         mm_player_t* player = NULL;
11808         MMHandleType attrs = 0;
11809         int count = 0;
11810
11811         MMPLAYER_RETURN_VAL_IF_FAIL(u_data, FALSE);
11812
11813         player = (mm_player_t*) u_data;
11814         attrs = MMPLAYER_GET_ATTRS(player);
11815
11816         mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
11817
11818         if (count == -1) {
11819                 gint ret_value = 0;
11820                 ret_value = __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
11821                 if (ret_value != MM_ERROR_NONE)
11822                         LOGE("seeking to 0 failed in repeat play");
11823         } else {
11824                 /* posting eos */
11825                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
11826         }
11827
11828         /* we are returning FALSE as we need only one posting */
11829         return FALSE;
11830 }
11831
11832 /* sending event to one of sinkelements */
11833 static gboolean
11834 __gst_send_event_to_sink(mm_player_t* player, GstEvent* event)
11835 {
11836         GstEvent * event2 = NULL;
11837         GList *sinks = NULL;
11838         gboolean res = FALSE;
11839         MMPLAYER_FENTER();
11840
11841         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11842         MMPLAYER_RETURN_VAL_IF_FAIL(event, FALSE);
11843
11844         /* While adding subtitles in live feeds seek is getting called.
11845            Adding defensive check in framework layer.*/
11846         if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
11847                 if (MMPLAYER_IS_LIVE_STREAMING(player)) {
11848                         LOGE("Should not send seek event during live playback");
11849                         return TRUE;
11850                 }
11851         }
11852
11853         if (player->play_subtitle)
11854                 event2 = gst_event_copy((const GstEvent *)event);
11855
11856         sinks = player->sink_elements;
11857         while (sinks) {
11858                 GstElement *sink = GST_ELEMENT_CAST(sinks->data);
11859
11860                 if (GST_IS_ELEMENT(sink)) {
11861                         /* keep ref to the event */
11862                         gst_event_ref(event);
11863
11864                         if ((res = gst_element_send_event(sink, event))) {
11865                                 LOGD("sending event[%s] to sink element [%s] success!\n",
11866                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
11867
11868                                 /* rtsp case, asyn_done is not called after seek during pause state */
11869                                 if (MMPLAYER_IS_RTSP_STREAMING(player)) {
11870                                         if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
11871                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
11872                                                         LOGD("RTSP seek completed, after pause state..\n");
11873                                                         player->doing_seek = FALSE;
11874                                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
11875                                                 }
11876
11877                                         }
11878                                 }
11879
11880                                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
11881                                         sinks = g_list_next(sinks);
11882                                         continue;
11883                                 } else {
11884                                         break;
11885                                 }
11886                         }
11887
11888                         LOGD("sending event[%s] to sink element [%s] failed. try with next one.\n",
11889                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
11890                 }
11891
11892                 sinks = g_list_next(sinks);
11893         }
11894
11895         /* Note : Textbin is not linked to the video or audio bin.
11896          * It needs to send the event to the text sink seperatelly.
11897          */
11898          if (player->play_subtitle && player->pipeline) {
11899                 GstElement *text_sink = GST_ELEMENT_CAST(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
11900
11901                 if (GST_IS_ELEMENT(text_sink)) {
11902                         /* keep ref to the event */
11903                         gst_event_ref(event2);
11904
11905                         if ((res = gst_element_send_event(text_sink, event2)))
11906                                 LOGD("sending event[%s] to subtitle sink element [%s] success!\n",
11907                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
11908                         else
11909                                 LOGE("sending event[%s] to subtitle sink element [%s] failed!\n",
11910                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
11911
11912                         gst_event_unref(event2);
11913                 }
11914          }
11915
11916         gst_event_unref(event);
11917
11918         MMPLAYER_FLEAVE();
11919
11920         return res;
11921 }
11922
11923 static void
11924 __mmplayer_add_sink(mm_player_t* player, GstElement* sink)
11925 {
11926         MMPLAYER_FENTER();
11927
11928         MMPLAYER_RETURN_IF_FAIL(player);
11929         MMPLAYER_RETURN_IF_FAIL(sink);
11930
11931         player->sink_elements =
11932                 g_list_append(player->sink_elements, sink);
11933
11934         MMPLAYER_FLEAVE();
11935 }
11936
11937 static void
11938 __mmplayer_del_sink(mm_player_t* player, GstElement* sink)
11939 {
11940         MMPLAYER_FENTER();
11941
11942         MMPLAYER_RETURN_IF_FAIL(player);
11943         MMPLAYER_RETURN_IF_FAIL(sink);
11944
11945         player->sink_elements =
11946                         g_list_remove(player->sink_elements, sink);
11947
11948         MMPLAYER_FLEAVE();
11949 }
11950
11951 static gboolean
11952 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
11953                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
11954                         gint64 cur, GstSeekType stop_type, gint64 stop)
11955 {
11956         GstEvent* event = NULL;
11957         gboolean result = FALSE;
11958
11959         MMPLAYER_FENTER();
11960
11961         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11962
11963         if (player->pipeline && player->pipeline->textbin)
11964                 __mmplayer_drop_subtitle(player, FALSE);
11965
11966         event = gst_event_new_seek(rate, format, flags, cur_type,
11967                 cur, stop_type, stop);
11968
11969         result = __gst_send_event_to_sink(player, event);
11970
11971         MMPLAYER_FLEAVE();
11972
11973         return result;
11974 }
11975
11976 /* NOTE : be careful with calling this api. please refer to below glib comment
11977  * glib comment : Note that there is a bug in GObject that makes this function much
11978  * less useful than it might seem otherwise. Once gobject is disposed, the callback
11979  * will no longer be called, but, the signal handler is not currently disconnected.
11980  * If the instance is itself being freed at the same time than this doesn't matter,
11981  * since the signal will automatically be removed, but if instance persists,
11982  * then the signal handler will leak. You should not remove the signal yourself
11983  * because in a future versions of GObject, the handler will automatically be
11984  * disconnected.
11985  *
11986  * It's possible to work around this problem in a way that will continue to work
11987  * with future versions of GObject by checking that the signal handler is still
11988  * connected before disconnected it:
11989  *
11990  *  if (g_signal_handler_is_connected(instance, id))
11991  *    g_signal_handler_disconnect(instance, id);
11992  */
11993 static void
11994 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
11995 {
11996         GList* sig_list = NULL;
11997         MMPlayerSignalItem* item = NULL;
11998
11999         MMPLAYER_FENTER();
12000
12001         MMPLAYER_RETURN_IF_FAIL(player);
12002
12003         LOGD("release signals type : %d", type);
12004
12005         if (type >= MM_PLAYER_SIGNAL_TYPE_ALL) {
12006                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
12007                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
12008                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
12009                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
12010                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
12011                 return;
12012         }
12013
12014         sig_list = player->signals[type];
12015
12016         for (; sig_list; sig_list = sig_list->next) {
12017                 item = sig_list->data;
12018
12019                 if (item && item->obj && GST_IS_ELEMENT(item->obj)) {
12020                         if (g_signal_handler_is_connected(item->obj, item->sig))
12021                                 g_signal_handler_disconnect(item->obj, item->sig);
12022                 }
12023
12024                 MMPLAYER_FREEIF(item);
12025         }
12026
12027         g_list_free(player->signals[type]);
12028         player->signals[type] = NULL;
12029
12030         MMPLAYER_FLEAVE();
12031
12032         return;
12033 }
12034
12035 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
12036 {
12037         mm_player_t* player = 0;
12038         int prev_display_surface_type = 0;
12039         void *prev_display_overlay = NULL;
12040         const gchar *klass = NULL;
12041         gchar *cur_videosink_name = NULL;
12042         int ret = 0;
12043         int i = 0;
12044         int num_of_dec = 2; /* DEC1, DEC2 */
12045
12046         MMPLAYER_FENTER();
12047
12048         MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
12049         MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
12050
12051         player = MM_PLAYER_CAST(handle);
12052
12053         if (surface_type >= MM_DISPLAY_SURFACE_NUM) {
12054                 LOGE("Not support this surface type(%d) for changing vidoesink", surface_type);
12055                 MMPLAYER_FLEAVE();
12056                 return MM_ERROR_INVALID_ARGUMENT;
12057         }
12058
12059         /* load previous attributes */
12060         if (player->attrs) {
12061                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &prev_display_surface_type);
12062                 mm_attrs_get_data_by_name(player->attrs, "display_overlay", &prev_display_overlay);
12063                 LOGD("[0: Video surface, 4: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
12064                 if (prev_display_surface_type == surface_type) {
12065                         LOGD("incoming display surface type is same as previous one, do nothing..");
12066                         MMPLAYER_FLEAVE();
12067                         return MM_ERROR_NONE;
12068                 }
12069         } else {
12070                 LOGE("failed to load attributes");
12071                 MMPLAYER_FLEAVE();
12072                 return MM_ERROR_PLAYER_INTERNAL;
12073         }
12074
12075         /* check videosink element is created */
12076         if (!player->pipeline || !player->pipeline->videobin ||
12077                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
12078                 LOGD("videosink element is not yet ready");
12079
12080                 /* videobin is not created yet, so we just set attributes related to display surface */
12081                 LOGD("store display attribute for given surface type(%d)", surface_type);
12082                 mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
12083                 mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
12084                 if (mmf_attrs_commit(player->attrs)) {
12085                         LOGE("failed to commit attribute");
12086                         MMPLAYER_FLEAVE();
12087                         return MM_ERROR_PLAYER_INTERNAL;
12088                 }
12089                 MMPLAYER_FLEAVE();
12090                 return MM_ERROR_NONE;
12091         } else {
12092                 /* get player command status */
12093                 if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE)) {
12094                         LOGE("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command", player->cmd);
12095                         MMPLAYER_FLEAVE();
12096                         return MM_ERROR_PLAYER_INVALID_STATE;
12097                 }
12098
12099                 /* surface change */
12100                 for (i = 0 ; i < num_of_dec ; i++) {
12101                         if (player->pipeline->mainbin &&
12102                                 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) {
12103                                 GstElementFactory *decfactory;
12104                                 decfactory = gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst);
12105
12106                                 klass = gst_element_factory_get_metadata(decfactory, GST_ELEMENT_METADATA_KLASS);
12107                                 if ((g_strrstr(klass, "Codec/Decoder/Video"))) {
12108                                         if ((prev_display_surface_type == MM_DISPLAY_SURFACE_OVERLAY) && (surface_type == MM_DISPLAY_SURFACE_REMOTE)) {
12109                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, "fakesink", surface_type, display_overlay);
12110                                                 if (ret) {
12111                                                         goto ERROR_CASE;
12112                                                 } else {
12113                                                         LOGW("success to changing display surface(%d)", surface_type);
12114                                                         MMPLAYER_FLEAVE();
12115                                                         return MM_ERROR_NONE;
12116                                                 }
12117                                         } else if ((prev_display_surface_type == MM_DISPLAY_SURFACE_REMOTE) && (surface_type == MM_DISPLAY_SURFACE_OVERLAY)) {
12118                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_overlay, surface_type, display_overlay);
12119                                                 if (ret) {
12120                                                         goto ERROR_CASE;
12121                                                 } else {
12122                                                         LOGW("success to changing display surface(%d)", surface_type);
12123                                                         MMPLAYER_FLEAVE();
12124                                                         return MM_ERROR_NONE;
12125                                                 }
12126                                         } else {
12127                                                 LOGE("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface", surface_type, cur_videosink_name);
12128                                                 ret = MM_ERROR_PLAYER_INTERNAL;
12129                                                 goto ERROR_CASE;
12130                                         }
12131                                 }
12132                         }
12133                 }
12134         }
12135
12136 ERROR_CASE:
12137         /* rollback to previous attributes */
12138         mm_attrs_set_int_by_name(player->attrs, "display_surface_type", prev_display_surface_type);
12139         mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(void*));
12140         if (mmf_attrs_commit(player->attrs)) {
12141                 LOGE("failed to commit attributes to rollback");
12142                 MMPLAYER_FLEAVE();
12143                 return MM_ERROR_PLAYER_INTERNAL;
12144         }
12145         MMPLAYER_FLEAVE();
12146         return ret;
12147 }
12148
12149 /* NOTE : It does not support some use cases, eg using colorspace converter */
12150 int
12151 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
12152 {
12153         GstPad *src_pad_dec = NULL;
12154         GstPad *sink_pad_videosink = NULL;
12155         GstPad *sink_pad_videobin = NULL;
12156         GstClock *clock = NULL;
12157         MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
12158         int ret = MM_ERROR_NONE;
12159         gboolean is_audiobin_created = TRUE;
12160
12161         MMPLAYER_FENTER();
12162
12163         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
12164         MMPLAYER_RETURN_VAL_IF_FAIL(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
12165         MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
12166
12167         LOGD("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
12168         LOGD("surface type(%d), display overlay(%x)", surface_type, display_overlay);
12169
12170         /* get information whether if audiobin is created */
12171         if (!player->pipeline->audiobin ||
12172                      !player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
12173                 LOGW("audiobin is null, this video content may not have audio data");
12174                 is_audiobin_created = FALSE;
12175         }
12176
12177         /* get current state of player */
12178         previous_state = MMPLAYER_CURRENT_STATE(player);
12179         LOGD("previous state(%d)", previous_state);
12180
12181
12182         /* get src pad of decoder and block it */
12183         src_pad_dec = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
12184         if (!src_pad_dec) {
12185                 LOGE("failed to get src pad from decode in mainbin");
12186                 return MM_ERROR_PLAYER_INTERNAL;
12187         }
12188
12189         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING) {
12190                 LOGW("trying to block pad(video)");
12191 //              if (!gst_pad_set_blocked(src_pad_dec, TRUE))
12192                 gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
12193                         NULL, NULL, NULL);
12194                 {
12195                         LOGE("failed to set block pad(video)");
12196                         return MM_ERROR_PLAYER_INTERNAL;
12197                 }
12198                 LOGW("pad is blocked(video)");
12199         } else {
12200                 /* no data flows, so no need to do pad_block */
12201                 if (player->doing_seek)
12202                         LOGW("not completed seek(%d), do nothing", player->doing_seek);
12203
12204                 LOGD("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
12205         }
12206
12207         /* remove pad */
12208         if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
12209                 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin)))) {
12210                 LOGE("failed to remove previous ghost_pad for videobin");
12211                 return MM_ERROR_PLAYER_INTERNAL;
12212         }
12213
12214         /* change state of videobin to NULL */
12215         LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
12216         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
12217         if (ret != GST_STATE_CHANGE_SUCCESS) {
12218                 LOGE("failed to change state of videobin to NULL");
12219                 return MM_ERROR_PLAYER_INTERNAL;
12220         }
12221
12222         /* unlink between decoder and videobin and remove previous videosink from videobin */
12223         gst_element_unlink(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
12224         if (!gst_bin_remove(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst))) {
12225                 LOGE("failed to remove former videosink from videobin");
12226                 return MM_ERROR_PLAYER_INTERNAL;
12227         }
12228
12229         __mmplayer_del_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
12230
12231         /* create a new videosink and add it to videobin */
12232         player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, "videosink");
12233         if (!player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
12234                 LOGE("failed to create videosink element\n");
12235                 MMPLAYER_FLEAVE();
12236                 return MM_ERROR_PLAYER_INTERNAL;
12237         }
12238         gst_bin_add(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
12239         __mmplayer_add_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
12240         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
12241
12242         /* save attributes */
12243         if (player->attrs) {
12244                 /* set a new display surface type */
12245                 mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
12246                 /* set a new diplay overlay */
12247                 switch (surface_type) {
12248                 case MM_DISPLAY_SURFACE_OVERLAY:
12249                         LOGD("save attributes related to video display surface : id = %d", *(int*)display_overlay);
12250                         mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
12251                         break;
12252                 default:
12253                         LOGE("invalid type(%d) for changing display surface", surface_type);
12254                         MMPLAYER_FLEAVE();
12255                         return MM_ERROR_INVALID_ARGUMENT;
12256                 }
12257                 if (mmf_attrs_commit(player->attrs)) {
12258                         LOGE("failed to commit");
12259                         MMPLAYER_FLEAVE();
12260                         return MM_ERROR_PLAYER_INTERNAL;
12261                 }
12262         } else {
12263                 LOGE("player->attrs is null, failed to save attributes");
12264                 MMPLAYER_FLEAVE();
12265                 return MM_ERROR_PLAYER_INTERNAL;
12266         }
12267
12268         /* update video param */
12269         if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "update_all_param")) {
12270                 LOGE("failed to update video param");
12271                 return MM_ERROR_PLAYER_INTERNAL;
12272         }
12273
12274         /* change state of videobin to READY */
12275         LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
12276         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
12277         if (ret != GST_STATE_CHANGE_SUCCESS) {
12278                 LOGE("failed to change state of videobin to READY");
12279                 return MM_ERROR_PLAYER_INTERNAL;
12280         }
12281
12282         /* change ghostpad */
12283         sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
12284         if (!sink_pad_videosink) {
12285                 LOGE("failed to get sink pad from videosink element");
12286                 return MM_ERROR_PLAYER_INTERNAL;
12287         }
12288         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
12289         if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE)) {
12290                 LOGE("failed to set active to ghost_pad");
12291                 return MM_ERROR_PLAYER_INTERNAL;
12292         }
12293         if (FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
12294                 LOGE("failed to change ghostpad for videobin");
12295                 return MM_ERROR_PLAYER_INTERNAL;
12296         }
12297         gst_object_unref(sink_pad_videosink);
12298
12299         /* link decoder with videobin */
12300         sink_pad_videobin = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
12301         if (!sink_pad_videobin) {
12302                 LOGE("failed to get sink pad from videobin");
12303                 return MM_ERROR_PLAYER_INTERNAL;
12304         }
12305         if (GST_PAD_LINK_OK != gst_pad_link(src_pad_dec, sink_pad_videobin)) {
12306                 LOGE("failed to link");
12307                 return MM_ERROR_PLAYER_INTERNAL;
12308         }
12309         gst_object_unref(sink_pad_videobin);
12310
12311         /* clock setting for a new videosink plugin */
12312         /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
12313                         so we set it from audiosink plugin or pipeline(system clock) */
12314         if (!is_audiobin_created) {
12315                 LOGW("audiobin is not created, get clock from pipeline..");
12316                 clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
12317         } else {
12318                 clock = GST_ELEMENT_CLOCK(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
12319         }
12320         if (clock) {
12321                 GstClockTime now;
12322                 GstClockTime base_time;
12323                 LOGD("set the clock to videosink");
12324                 gst_element_set_clock(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
12325                 clock = GST_ELEMENT_CLOCK(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
12326                 if (clock) {
12327                         LOGD("got clock of videosink");
12328                         now = gst_clock_get_time(clock);
12329                         base_time = GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
12330                         LOGD("at time %" GST_TIME_FORMAT ", base %"
12331                                         GST_TIME_FORMAT, GST_TIME_ARGS(now), GST_TIME_ARGS(base_time));
12332                 } else {
12333                         LOGE("failed to get clock of videosink after setting clock");
12334                         return MM_ERROR_PLAYER_INTERNAL;
12335                 }
12336         } else
12337                 LOGW("failed to get clock, maybe it is the time before first playing");
12338
12339         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING) {
12340                 /* change state of videobin to PAUSED */
12341                 LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
12342                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
12343                 if (ret != GST_STATE_CHANGE_FAILURE) {
12344                         LOGW("change state of videobin to PLAYING, ret(%d)", ret);
12345                 } else {
12346                         LOGE("failed to change state of videobin to PLAYING");
12347                         return MM_ERROR_PLAYER_INTERNAL;
12348                 }
12349
12350                 /* release blocked and unref src pad of video decoder */
12351                 #if 0
12352                 if (!gst_pad_set_blocked(src_pad_dec, FALSE)) {
12353                         LOGE("failed to set pad blocked FALSE(video)");
12354                         return MM_ERROR_PLAYER_INTERNAL;
12355                 }
12356                 #endif
12357                 LOGW("pad is unblocked(video)");
12358         } else {
12359                 if (player->doing_seek)
12360                         LOGW("not completed seek(%d)", player->doing_seek);
12361                 /* change state of videobin to PAUSED */
12362                 LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
12363                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
12364                 if (ret != GST_STATE_CHANGE_FAILURE) {
12365                         LOGW("change state of videobin to PAUSED, ret(%d)", ret);
12366                 } else {
12367                         LOGE("failed to change state of videobin to PLAYING");
12368                         return MM_ERROR_PLAYER_INTERNAL;
12369                 }
12370
12371                 /* already skipped pad block */
12372                 LOGD("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
12373         }
12374
12375         /* do get/set position for new videosink plugin */
12376         {
12377                 gint64 position = 0;
12378
12379                 LOGD("do get/set position for new videosink plugin");
12380                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position)) {
12381                         LOGE("failed to get position");
12382                         return MM_ERROR_PLAYER_INTERNAL;
12383                 }
12384 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
12385                 /* accurate seek */
12386                 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE)) {
12387                         LOGE("failed to set position");
12388                         return MM_ERROR_PLAYER_INTERNAL;
12389                 }
12390 #else
12391                 /* key unit seek */
12392                 ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
12393                                 GST_FORMAT_TIME, (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
12394                                                         GST_SEEK_TYPE_SET, position,
12395                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
12396                 if (!ret) {
12397                         LOGE("failed to set position");
12398                         return MM_ERROR_PLAYER_INTERNAL;
12399                 }
12400 #endif
12401         }
12402
12403         if (src_pad_dec)
12404                 gst_object_unref(src_pad_dec);
12405         LOGD("success to change sink");
12406
12407         MMPLAYER_FLEAVE();
12408
12409         return MM_ERROR_NONE;
12410 }
12411
12412
12413 /* Note : if silent is true, then subtitle would not be displayed. :*/
12414 int _mmplayer_set_subtitle_silent(MMHandleType hplayer, int silent)
12415 {
12416         mm_player_t* player = (mm_player_t*) hplayer;
12417
12418         MMPLAYER_FENTER();
12419
12420         /* check player handle */
12421         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12422
12423         player->set_mode.subtitle_off = silent;
12424
12425         LOGD("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
12426
12427         MMPLAYER_FLEAVE();
12428
12429         return MM_ERROR_NONE;
12430 }
12431
12432 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
12433 {
12434         MMPlayerGstElement* mainbin = NULL;
12435         MMPlayerGstElement* textbin = NULL;
12436         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
12437         GstState current_state = GST_STATE_VOID_PENDING;
12438         GstState element_state = GST_STATE_VOID_PENDING;
12439         GstState element_pending_state = GST_STATE_VOID_PENDING;
12440         gint64 time = 0;
12441         GstEvent *event = NULL;
12442         int result = MM_ERROR_NONE;
12443
12444         GstClock *curr_clock = NULL;
12445         GstClockTime base_time, start_time, curr_time;
12446
12447
12448         MMPLAYER_FENTER();
12449
12450         /* check player handle */
12451         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
12452                                                                 player->pipeline &&
12453                                                                 player->pipeline->mainbin &&
12454                                                                 player->pipeline->textbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
12455
12456         mainbin = player->pipeline->mainbin;
12457         textbin = player->pipeline->textbin;
12458
12459         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
12460
12461         // sync clock with current pipeline
12462         curr_clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
12463         curr_time = gst_clock_get_time(curr_clock);
12464
12465         base_time = gst_element_get_base_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
12466         start_time = gst_element_get_start_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
12467
12468         LOGD("state: %d, base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
12469                 current_state, GST_TIME_ARGS(base_time), GST_TIME_ARGS(start_time), GST_TIME_ARGS(curr_time));
12470
12471         if (current_state > GST_STATE_READY) {
12472                 // sync state with current pipeline
12473                 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
12474                 gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_PAUSED);
12475                 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
12476
12477                 ret = gst_element_get_state(mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
12478                 if (GST_STATE_CHANGE_FAILURE == ret) {
12479                         LOGE("fail to state change.\n");
12480                         result = MM_ERROR_PLAYER_INTERNAL;
12481                         goto ERROR;
12482                 }
12483         }
12484
12485         gst_element_set_base_time(textbin[MMPLAYER_T_BIN].gst, base_time);
12486         gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
12487
12488         if (curr_clock) {
12489                 gst_element_set_clock(textbin[MMPLAYER_T_BIN].gst, curr_clock);
12490                 gst_object_unref(curr_clock);
12491         }
12492
12493         // seek to current position
12494         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
12495                 result = MM_ERROR_PLAYER_INVALID_STATE;
12496                 LOGE("gst_element_query_position failed, invalid state\n");
12497                 goto ERROR;
12498         }
12499
12500         LOGD("seek time = %"G_GINT64_FORMAT", rate = %f", time, player->playback_rate);
12501         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);
12502         if (event) {
12503                 __gst_send_event_to_sink(player, event);
12504         } else {
12505                 result = MM_ERROR_PLAYER_INTERNAL;
12506                 LOGE("gst_event_new_seek failed"); /* pipeline will got error and can not be recovered */
12507                 goto ERROR;
12508         }
12509
12510         /* sync state with current pipeline */
12511         gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
12512         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
12513         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
12514
12515         return MM_ERROR_NONE;
12516
12517 ERROR:
12518         /* release text pipeline resource */
12519         player->textsink_linked = 0;
12520
12521         /* release signal */
12522         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
12523
12524         /* release textbin with it's childs */
12525         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN);
12526         MMPLAYER_FREEIF(player->pipeline->textbin);
12527         player->pipeline->textbin = NULL;
12528
12529         /* release subtitle elem */
12530         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBSRC);
12531         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBPARSE);
12532
12533         return result;
12534 }
12535
12536 static int
12537 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
12538 {
12539         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
12540         GstState current_state = GST_STATE_VOID_PENDING;
12541
12542         MMHandleType attrs = 0;
12543         MMPlayerGstElement* mainbin = NULL;
12544         MMPlayerGstElement* textbin = NULL;
12545
12546         gchar* subtitle_uri = NULL;
12547         int result = MM_ERROR_NONE;
12548         const gchar *charset = NULL;
12549
12550         MMPLAYER_FENTER();
12551
12552         /* check player handle */
12553         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
12554                                                                 player->pipeline &&
12555                                                                 player->pipeline->mainbin &&
12556                                                                 player->pipeline->textbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
12557         MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT);
12558
12559         mainbin = player->pipeline->mainbin;
12560         textbin = player->pipeline->textbin;
12561
12562         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
12563         if (current_state < GST_STATE_READY) {
12564                 result = MM_ERROR_PLAYER_INVALID_STATE;
12565                 LOGE("Pipeline is not in proper state\n");
12566                 goto EXIT;
12567         }
12568
12569         attrs = MMPLAYER_GET_ATTRS(player);
12570         if (!attrs) {
12571                 LOGE("cannot get content attribute\n");
12572                 result = MM_ERROR_PLAYER_INTERNAL;
12573                 goto EXIT;
12574         }
12575
12576         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
12577         if (!subtitle_uri || strlen(subtitle_uri) < 1) {
12578                 LOGE("subtitle uri is not proper filepath\n");
12579                 result = MM_ERROR_PLAYER_INVALID_URI;
12580                 goto EXIT;
12581         }
12582
12583         if (!util_get_storage_info(filepath, &player->storage_info[MMPLAYER_PATH_TEXT])) {
12584                 LOGE("failed to get storage info of subtitle path");
12585                 result = MM_ERROR_PLAYER_INVALID_URI;
12586                 goto EXIT;
12587         }
12588
12589         LOGD("old subtitle file path is [%s]\n", subtitle_uri);
12590         LOGD("new subtitle file path is [%s]\n", filepath);
12591
12592         if (!strcmp(filepath, subtitle_uri)) {
12593                 LOGD("No need to swtich subtitle, as input filepath is same as current filepath\n");
12594                 goto EXIT;
12595         } else {
12596                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
12597                 if (mmf_attrs_commit(player->attrs)) {
12598                         LOGE("failed to commit.\n");
12599                         goto EXIT;
12600                 }
12601         }
12602
12603         //gst_pad_set_blocked_async(src-srcpad, TRUE)
12604         MMPLAYER_SUBTITLE_INFO_LOCK(player);
12605         player->subtitle_language_list = NULL;
12606         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
12607
12608         ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
12609         if (ret != GST_STATE_CHANGE_SUCCESS) {
12610                 LOGE("failed to change state of textbin to READY");
12611                 result = MM_ERROR_PLAYER_INTERNAL;
12612                 goto EXIT;
12613         }
12614
12615         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_READY);
12616         if (ret != GST_STATE_CHANGE_SUCCESS) {
12617                 LOGE("failed to change state of subparse to READY");
12618                 result = MM_ERROR_PLAYER_INTERNAL;
12619                 goto EXIT;
12620         }
12621
12622         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
12623         if (ret != GST_STATE_CHANGE_SUCCESS) {
12624                 LOGE("failed to change state of filesrc to READY");
12625                 result = MM_ERROR_PLAYER_INTERNAL;
12626                 goto EXIT;
12627         }
12628
12629         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_TEXT);
12630
12631         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
12632
12633         charset = util_get_charset(filepath);
12634         if (charset) {
12635                 LOGD("detected charset is %s\n", charset);
12636                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
12637         }
12638
12639         result = _mmplayer_sync_subtitle_pipeline(player);
12640
12641 EXIT:
12642         MMPLAYER_FLEAVE();
12643         return result;
12644 }
12645
12646 /* API to switch between external subtitles */
12647 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
12648 {
12649         int result = MM_ERROR_NONE;
12650         mm_player_t* player = (mm_player_t*)hplayer;
12651         char *path = NULL;
12652
12653         MMPLAYER_FENTER();
12654
12655         /* check player handle */
12656         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12657
12658         /* filepath can be null in idle state */
12659         if (filepath) {
12660                 /* check file path */
12661                 if ((path = strstr(filepath, "file://")))
12662                         result = util_exist_file_path(path + 7);
12663                 else
12664                         result = util_exist_file_path(filepath);
12665
12666                 if (result != MM_ERROR_NONE) {
12667                         LOGE("invalid subtitle path 0x%X", result);
12668                         return result; /* file not found or permission denied */
12669                 }
12670         }
12671
12672         if (!player->pipeline) {
12673                 /* IDLE state */
12674                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
12675                 if (mmf_attrs_commit(player->attrs)) {
12676                         LOGE("failed to commit");       /* subtitle path will not be created */
12677                         return MM_ERROR_PLAYER_INTERNAL;
12678                 }
12679         } else {
12680                 /* cur state <> IDLE(READY, PAUSE, PLAYING..) */
12681                 /* check filepath */
12682                 MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT);
12683
12684                 if (!__mmplayer_check_subtitle(player)) {
12685                         mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
12686                         if (mmf_attrs_commit(player->attrs)) {
12687                                 LOGE("failed to commit");
12688                                 return MM_ERROR_PLAYER_INTERNAL;
12689                         }
12690
12691                         if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) {
12692                                 LOGE("fail to create text pipeline");
12693                                 return MM_ERROR_PLAYER_INTERNAL;
12694                         }
12695
12696                         result = _mmplayer_sync_subtitle_pipeline(player);
12697                 } else {
12698                         result = __mmplayer_change_external_subtitle_language(player, filepath);
12699                 }
12700
12701                 MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
12702                 player->is_external_subtitle_added_now = TRUE;
12703
12704                 MMPLAYER_SUBTITLE_INFO_LOCK(player);
12705                 if (!player->subtitle_language_list) {
12706                         gint64 timeout = g_get_monotonic_time() + G_TIME_SPAN_SECOND; /* wait 1 sec */
12707                         if (!MMPLAYER_SUBTITLE_INFO_WAIT_UNTIL(player, timeout))
12708                                 LOGW("subtitle language list is not updated yet");
12709                 }
12710                 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
12711         }
12712
12713         MMPLAYER_FLEAVE();
12714         return result;
12715 }
12716
12717 static int
12718 __mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index)
12719 {
12720         int result = MM_ERROR_NONE;
12721         gchar* change_pad_name = NULL;
12722         GstPad* sinkpad = NULL;
12723         MMPlayerGstElement* mainbin = NULL;
12724         enum MainElementID elemId = MMPLAYER_M_NUM;
12725         GstCaps* caps = NULL;
12726         gint total_track_num = 0;
12727
12728         MMPLAYER_FENTER();
12729
12730         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin,
12731                                                                                                         MM_ERROR_PLAYER_NOT_INITIALIZED);
12732
12733         LOGD("Change Track(%d) to %d\n", type, index);
12734
12735         mainbin = player->pipeline->mainbin;
12736
12737         if (type == MM_PLAYER_TRACK_TYPE_AUDIO) {
12738                 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
12739         } else if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
12740                 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
12741         } else {
12742                 /* Changing Video Track is not supported. */
12743                 LOGE("Track Type Error\n");
12744                 goto EXIT;
12745         }
12746
12747         if (mainbin[elemId].gst == NULL) {
12748                 result = MM_ERROR_PLAYER_NO_OP;
12749                 LOGD("Req track doesn't exist\n");
12750                 goto EXIT;
12751         }
12752
12753         total_track_num = player->selector[type].total_track_num;
12754         if (total_track_num <= 0) {
12755                 result = MM_ERROR_PLAYER_NO_OP;
12756                 LOGD("Language list is not available \n");
12757                 goto EXIT;
12758         }
12759
12760         if ((index < 0) || (index >= total_track_num)) {
12761                 result = MM_ERROR_INVALID_ARGUMENT;
12762                 LOGD("Not a proper index : %d \n", index);
12763                 goto EXIT;
12764         }
12765
12766         /*To get the new pad from the selector*/
12767         change_pad_name = g_strdup_printf("sink_%u", index);
12768         if (change_pad_name == NULL) {
12769                 result = MM_ERROR_PLAYER_INTERNAL;
12770                 LOGD("Pad does not exists\n");
12771                 goto EXIT;
12772         }
12773
12774         LOGD("new active pad name: %s\n", change_pad_name);
12775
12776         sinkpad = gst_element_get_static_pad(mainbin[elemId].gst, change_pad_name);
12777         if (sinkpad == NULL) {
12778                 LOGD("sinkpad is NULL");
12779                 result = MM_ERROR_PLAYER_INTERNAL;
12780                 goto EXIT;
12781         }
12782
12783         LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
12784         g_object_set(mainbin[elemId].gst, "active-pad", sinkpad, NULL);
12785
12786         caps = gst_pad_get_current_caps(sinkpad);
12787         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
12788
12789         if (sinkpad)
12790                 gst_object_unref(sinkpad);
12791
12792         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
12793                 __mmplayer_set_audio_attrs(player, caps);
12794
12795 EXIT:
12796
12797         MMPLAYER_FREEIF(change_pad_name);
12798         return result;
12799 }
12800
12801 int _mmplayer_change_track_language(MMHandleType hplayer, MMPlayerTrackType type, int index)
12802 {
12803         int result = MM_ERROR_NONE;
12804         mm_player_t* player = NULL;
12805         MMPlayerGstElement* mainbin = NULL;
12806
12807         gint current_active_index = 0;
12808
12809         GstState current_state = GST_STATE_VOID_PENDING;
12810         GstEvent* event = NULL;
12811         gint64 time = 0;
12812
12813         MMPLAYER_FENTER();
12814
12815         player = (mm_player_t*)hplayer;
12816         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12817
12818         if (!player->pipeline) {
12819                 LOGE("Track %d pre setting -> %d\n", type, index);
12820
12821                 player->selector[type].active_pad_index = index;
12822                 goto EXIT;
12823         }
12824
12825         mainbin = player->pipeline->mainbin;
12826
12827         current_active_index = player->selector[type].active_pad_index;
12828
12829         /*If index is same as running index no need to change the pad*/
12830         if (current_active_index == index)
12831                 goto EXIT;
12832
12833         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
12834                 result = MM_ERROR_PLAYER_INVALID_STATE;
12835                 goto EXIT;
12836         }
12837
12838         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
12839         if (current_state < GST_STATE_PAUSED) {
12840                 result = MM_ERROR_PLAYER_INVALID_STATE;
12841                 LOGW("Pipeline not in porper state\n");
12842                 goto EXIT;
12843         }
12844
12845         result = __mmplayer_change_selector_pad(player, type, index);
12846         if (result != MM_ERROR_NONE) {
12847                 LOGE("change selector pad error\n");
12848                 goto EXIT;
12849         }
12850
12851         player->selector[type].active_pad_index = index;
12852
12853         if (current_state == GST_STATE_PLAYING) {
12854                 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);
12855                 if (event) {
12856                         __gst_send_event_to_sink(player, event);
12857                 } else {
12858                         result = MM_ERROR_PLAYER_INTERNAL;
12859                         goto EXIT;
12860                 }
12861         }
12862
12863 EXIT:
12864         return result;
12865 }
12866
12867 int _mmplayer_get_subtitle_silent(MMHandleType hplayer, int* silent)
12868 {
12869         mm_player_t* player = (mm_player_t*) hplayer;
12870
12871         MMPLAYER_FENTER();
12872
12873         /* check player handle */
12874         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12875
12876         *silent = player->set_mode.subtitle_off;
12877
12878         LOGD("subtitle is %s.\n", silent ? "ON" : "OFF");
12879
12880         MMPLAYER_FLEAVE();
12881
12882         return MM_ERROR_NONE;
12883 }
12884
12885 gboolean
12886 __is_ms_buff_src(mm_player_t* player)
12887 {
12888         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
12889
12890         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_MS_BUFF) ? TRUE : FALSE;
12891 }
12892
12893 gboolean
12894 __has_suffix(mm_player_t* player, const gchar* suffix)
12895 {
12896         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
12897         MMPLAYER_RETURN_VAL_IF_FAIL(suffix, FALSE);
12898
12899         gboolean ret = FALSE;
12900         gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
12901         gchar* t_suffix = g_ascii_strdown(suffix, -1);
12902
12903         if (g_str_has_suffix(player->profile.uri, suffix))
12904                 ret = TRUE;
12905
12906         MMPLAYER_FREEIF(t_url);
12907         MMPLAYER_FREEIF(t_suffix);
12908
12909         return ret;
12910 }
12911
12912 int
12913 _mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
12914 {
12915         mm_player_t* player = (mm_player_t*) hplayer;
12916
12917         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12918
12919         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL) {
12920                 MMPLAYER_PRINT_STATE(player);
12921                 LOGE("wrong-state : can't set the download mode to parse");
12922                 return MM_ERROR_PLAYER_INVALID_STATE;
12923         }
12924
12925         LOGD("set video hub download mode to %s", (mode) ? "ON" : "OFF");
12926         player->video_hub_download_mode = mode;
12927
12928         return MM_ERROR_NONE;
12929 }
12930
12931 int
12932 _mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
12933 {
12934         mm_player_t* player = (mm_player_t*) hplayer;
12935
12936         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12937
12938         LOGD("enable sync handler : %s", (enable) ? "ON" : "OFF");
12939         player->sync_handler = enable;
12940
12941         return MM_ERROR_NONE;
12942 }
12943
12944 int
12945 _mmplayer_set_video_share_master_clock(MMHandleType hplayer, gint64 clock, gint64 clock_delta,
12946                                                                                 gint64 video_time, gint64 media_clock, gint64 audio_time)
12947 {
12948         mm_player_t* player = (mm_player_t*) hplayer;
12949         MMPlayerGstElement* mainbin = NULL;
12950         GstClockTime start_time_audio = 0, start_time_video = 0;
12951         GstClockTimeDiff base_time = 0, new_base_time = 0;
12952         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
12953         gint64 api_delta = 0;
12954         gint64 position = 0, position_delta = 0;
12955         gint64 adj_base_time = 0;
12956         GstClock *curr_clock = NULL;
12957         GstClockTime curr_time = 0;
12958         gboolean query_ret = TRUE;
12959         int result = MM_ERROR_NONE;
12960
12961         MMPLAYER_FENTER();
12962
12963         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
12964         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
12965         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
12966
12967         /* LOGD("in(us) : %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT,
12968                                                                         clock, clock_delta, video_time, media_clock, audio_time); */
12969
12970         if ((video_time < 0) || (player->doing_seek)) {
12971                 LOGD("skip setting master clock. %lld", video_time);
12972                 goto EXIT;
12973         }
12974
12975         mainbin = player->pipeline->mainbin;
12976
12977         curr_clock = gst_pipeline_get_clock(GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
12978         curr_time = gst_clock_get_time(curr_clock);
12979
12980         current_state = MMPLAYER_CURRENT_STATE(player);
12981
12982         if (current_state == MM_PLAYER_STATE_PLAYING)
12983                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
12984
12985         if ((current_state != MM_PLAYER_STATE_PLAYING) ||
12986                 (!query_ret)) {
12987                 position = player->last_position;
12988                 LOGD("query fail. %"G_GINT64_FORMAT, position);
12989         }
12990
12991         clock *= GST_USECOND;
12992         clock_delta *= GST_USECOND;
12993
12994         api_delta = clock - curr_time;
12995         if ((player->video_share_api_delta == 0) || (player->video_share_api_delta > api_delta))
12996                 player->video_share_api_delta = api_delta;
12997         else
12998                 clock_delta += (api_delta - player->video_share_api_delta);
12999
13000         if ((player->video_share_clock_delta == 0) || (player->video_share_clock_delta > clock_delta)) {
13001                 player->video_share_clock_delta = (gint64)clock_delta;
13002
13003                 position_delta = (position/GST_USECOND) - video_time;
13004                 position_delta *= GST_USECOND;
13005
13006                 adj_base_time = position_delta;
13007                 LOGD("video_share_clock_delta = %"G_GINT64_FORMAT", adj = %"G_GINT64_FORMAT, player->video_share_clock_delta, adj_base_time);
13008
13009         } else {
13010                 gint64 new_play_time = 0;
13011                 gint64 network_delay = 0;
13012
13013                 video_time *= GST_USECOND;
13014
13015                 network_delay = clock_delta - player->video_share_clock_delta;
13016                 new_play_time = video_time + network_delay;
13017
13018                 adj_base_time = position - new_play_time;
13019
13020                 LOGD("%"G_GINT64_FORMAT"(delay) = %"G_GINT64_FORMAT" - %"G_GINT64_FORMAT" / %"G_GINT64_FORMAT
13021                          "(adj) = %"G_GINT64_FORMAT"(slave_pos) - %"G_GINT64_FORMAT"(master_pos) - %"G_GINT64_FORMAT"(delay)",
13022                         network_delay, clock_delta, player->video_share_clock_delta, adj_base_time, position, video_time, network_delay);
13023         }
13024
13025         /* Adjust Current Stream Time with base_time of sink
13026          * 1. Set Start time to CLOCK NONE, to control the base time by MSL
13027          * 2. Set new base time
13028          *    if adj_base_time is positive value, the stream time will be decreased.
13029          * 3. If seek event is occurred, the start time will be reset. */
13030         if ((player->pipeline->audiobin) &&
13031                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst)) {
13032                 start_time_audio = gst_element_get_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
13033
13034                 if (start_time_audio != GST_CLOCK_TIME_NONE) {
13035                         LOGD("audio sink : gst_element_set_start_time -> NONE");
13036                         gst_element_set_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, GST_CLOCK_TIME_NONE);
13037                 }
13038
13039                 base_time = gst_element_get_base_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
13040         }
13041
13042         if ((player->pipeline->videobin) &&
13043                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst)) {
13044                 start_time_video = gst_element_get_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
13045
13046                 if (start_time_video != GST_CLOCK_TIME_NONE) {
13047                         LOGD("video sink : gst_element_set_start_time -> NONE");
13048                         gst_element_set_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst, GST_CLOCK_TIME_NONE);
13049                 }
13050
13051                 // if videobin exist, get base_time from videobin.
13052                 base_time = gst_element_get_base_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
13053         }
13054
13055         new_base_time = base_time + adj_base_time;
13056
13057         if ((player->pipeline->audiobin) &&
13058                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
13059                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), (GstClockTime)new_base_time);
13060
13061         if ((player->pipeline->videobin) &&
13062                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
13063                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), (GstClockTime)new_base_time);
13064
13065 EXIT:
13066         MMPLAYER_FLEAVE();
13067
13068         return result;
13069 }
13070
13071 int
13072 _mmplayer_get_video_share_master_clock(MMHandleType hplayer, gint64 *video_time, gint64 *media_clock, gint64 *audio_time)
13073 {
13074         mm_player_t* player = (mm_player_t*) hplayer;
13075         MMPlayerGstElement* mainbin = NULL;
13076         GstClock *curr_clock = NULL;
13077         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
13078         gint64 position = 0;
13079         gboolean query_ret = TRUE;
13080
13081         MMPLAYER_FENTER();
13082
13083         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
13084         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
13085         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
13086
13087         MMPLAYER_RETURN_VAL_IF_FAIL(video_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
13088         MMPLAYER_RETURN_VAL_IF_FAIL(media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT);
13089         MMPLAYER_RETURN_VAL_IF_FAIL(audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
13090
13091         mainbin = player->pipeline->mainbin;
13092
13093         curr_clock = gst_pipeline_get_clock(GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
13094
13095         current_state = MMPLAYER_CURRENT_STATE(player);
13096
13097         if (current_state != MM_PLAYER_STATE_PAUSED)
13098                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
13099
13100         if ((current_state == MM_PLAYER_STATE_PAUSED) ||
13101                 (!query_ret))
13102                 position = player->last_position;
13103
13104         *media_clock = *video_time = *audio_time = (position/GST_USECOND);
13105
13106         LOGD("media_clock: %"G_GINT64_FORMAT", video_time: %"G_GINT64_FORMAT"(us)", *media_clock, *video_time);
13107
13108         if (curr_clock)
13109                 gst_object_unref(curr_clock);
13110
13111         MMPLAYER_FLEAVE();
13112
13113         return MM_ERROR_NONE;
13114 }
13115
13116 static gboolean
13117 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
13118 {
13119         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13120         MMPLAYER_RETURN_VAL_IF_FAIL(element, FALSE);
13121
13122         gchar *factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
13123         gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
13124
13125         int idx = 0;
13126
13127         for (idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++) {
13128                 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx])) {
13129                         LOGD("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
13130                         mm_player_dump_t *dump_s;
13131                         dump_s = g_malloc(sizeof(mm_player_dump_t));
13132
13133                         if (dump_s == NULL) {
13134                                 LOGE("malloc fail");
13135                                 return FALSE;
13136                         }
13137
13138                         dump_s->dump_element_file = NULL;
13139                         dump_s->dump_pad = NULL;
13140                         dump_s->dump_pad = gst_element_get_static_pad(element, "sink");
13141
13142                         if (dump_s->dump_pad) {
13143                                 memset(dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
13144                                 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]);
13145                                 dump_s->dump_element_file = fopen(dump_file_name, "w+");
13146                                 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);
13147                                 /* add list for removed buffer probe and close FILE */
13148                                 player->dump_list = g_list_append(player->dump_list, dump_s);
13149                                 LOGD("%s sink pad added buffer probe for dump", factory_name);
13150                                 return TRUE;
13151                         } else {
13152                                 g_free(dump_s);
13153                                 dump_s = NULL;
13154                                 LOGE("failed to get %s sink pad added", factory_name);
13155                         }
13156
13157
13158                 }
13159         }
13160         return FALSE;
13161 }
13162
13163 static GstPadProbeReturn
13164 __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data)
13165 {
13166         FILE *dump_data = (FILE *) u_data;
13167 //      int written = 0;
13168         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
13169         GstMapInfo probe_info = GST_MAP_INFO_INIT;
13170
13171         MMPLAYER_RETURN_VAL_IF_FAIL(dump_data, FALSE);
13172
13173         gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
13174
13175 //      LOGD("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
13176
13177         fwrite(probe_info.data, 1, probe_info.size , dump_data);
13178
13179         return GST_PAD_PROBE_OK;
13180 }
13181
13182 static void
13183 __mmplayer_release_dump_list(GList *dump_list)
13184 {
13185         if (dump_list) {
13186                 GList *d_list = dump_list;
13187                 for (; d_list; d_list = g_list_next(d_list)) {
13188                         mm_player_dump_t *dump_s = d_list->data;
13189                         if (dump_s->dump_pad) {
13190                                 if (dump_s->probe_handle_id)
13191                                         gst_pad_remove_probe(dump_s->dump_pad, dump_s->probe_handle_id);
13192                         }
13193                         if (dump_s->dump_element_file) {
13194                                 fclose(dump_s->dump_element_file);
13195                                 dump_s->dump_element_file = NULL;
13196                         }
13197                         MMPLAYER_FREEIF(dump_s);
13198                 }
13199                 g_list_free(dump_list);
13200                 dump_list = NULL;
13201         }
13202 }
13203
13204 int
13205 _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
13206 {
13207         mm_player_t* player = (mm_player_t*) hplayer;
13208
13209         MMPLAYER_FENTER();
13210
13211         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13212         MMPLAYER_RETURN_VAL_IF_FAIL(exist, MM_ERROR_INVALID_ARGUMENT);
13213
13214         *exist = player->has_closed_caption;
13215
13216         MMPLAYER_FLEAVE();
13217
13218         return MM_ERROR_NONE;
13219 }
13220
13221 void _mm_player_video_stream_internal_buffer_unref(void *buffer)
13222 {
13223         MMPLAYER_FENTER();
13224         if (buffer) {
13225                 // LOGD("unref internal gst buffer %p", buffer);
13226                 gst_buffer_unref((GstBuffer *)buffer);
13227                 buffer = NULL;
13228         }
13229         MMPLAYER_FLEAVE();
13230 }
13231
13232 void
13233 __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data)
13234 {
13235         mm_player_t *player  = (mm_player_t*)user_data;
13236         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
13237         guint64 current_level_bytes = 0;
13238
13239         MMPLAYER_RETURN_IF_FAIL(player);
13240
13241         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13242
13243         LOGI("app-src: feed audio(%llu)\n", current_level_bytes);
13244         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13245
13246         if (player->media_stream_buffer_status_cb[type])
13247                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
13248         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13249
13250 }
13251
13252 void
13253 __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data)
13254 {
13255         mm_player_t *player  = (mm_player_t*)user_data;
13256         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
13257         guint64 current_level_bytes = 0;
13258
13259         MMPLAYER_RETURN_IF_FAIL(player);
13260
13261         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13262
13263         LOGI("app-src: feed video(%llu)\n", current_level_bytes);
13264
13265         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13266         if (player->media_stream_buffer_status_cb[type])
13267                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
13268         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13269 }
13270
13271 void
13272 __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data)
13273 {
13274         mm_player_t *player  = (mm_player_t*)user_data;
13275         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
13276         guint64 current_level_bytes = 0;
13277
13278         MMPLAYER_RETURN_IF_FAIL(player);
13279
13280         LOGI("app-src: feed subtitle\n");
13281
13282         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13283
13284         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13285         if (player->media_stream_buffer_status_cb[type])
13286                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
13287
13288         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13289 }
13290
13291 void
13292 __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data)
13293 {
13294         mm_player_t *player  = (mm_player_t*)user_data;
13295         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
13296         guint64 current_level_bytes = 0;
13297
13298         MMPLAYER_RETURN_IF_FAIL(player);
13299
13300         LOGI("app-src: audio buffer is full.\n");
13301
13302         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13303
13304         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13305
13306         if (player->media_stream_buffer_status_cb[type])
13307                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param[type]);
13308
13309         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13310 }
13311
13312 void
13313 __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data)
13314 {
13315         mm_player_t *player  = (mm_player_t*)user_data;
13316         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
13317         guint64 current_level_bytes = 0;
13318
13319         MMPLAYER_RETURN_IF_FAIL(player);
13320
13321         LOGI("app-src: video buffer is full.\n");
13322
13323         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13324
13325         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13326         if (player->media_stream_buffer_status_cb[type])
13327                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param[type]);
13328
13329         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13330 }
13331
13332 gboolean
13333 __gst_seek_audio_data(GstElement * appsrc, guint64 position, gpointer user_data)
13334 {
13335         mm_player_t *player  = (mm_player_t*)user_data;
13336         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
13337
13338         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13339
13340         LOGD("app-src: seek audio data %llu\n", position);
13341         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13342
13343         if (player->media_stream_seek_data_cb[type])
13344                 player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
13345         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13346
13347         return TRUE;
13348 }
13349
13350 gboolean
13351 __gst_seek_video_data(GstElement * appsrc, guint64 position, gpointer user_data)
13352 {
13353         mm_player_t *player  = (mm_player_t*)user_data;
13354         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
13355
13356         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13357
13358         LOGD("app-src: seek video data %llu\n", position);
13359         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13360         if (player->media_stream_seek_data_cb[type])
13361                 player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
13362         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13363
13364         return TRUE;
13365 }
13366
13367 gboolean
13368 __gst_seek_subtitle_data(GstElement * appsrc, guint64 position, gpointer user_data)
13369 {
13370         mm_player_t *player  = (mm_player_t*)user_data;
13371         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
13372
13373         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13374
13375         LOGD("app-src: seek subtitle data\n");
13376         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13377
13378         if (player->media_stream_seek_data_cb[type])
13379                 player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
13380         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13381
13382         return TRUE;
13383 }
13384
13385 int
13386 _mmplayer_set_pcm_spec(MMHandleType hplayer, int samplerate, int channel)
13387 {
13388         mm_player_t* player = (mm_player_t*) hplayer;
13389
13390         MMPLAYER_FENTER();
13391
13392         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13393
13394         player->pcm_samplerate = samplerate;
13395         player->pcm_channel = channel;
13396
13397         MMPLAYER_FLEAVE();
13398         return MM_ERROR_NONE;
13399 }
13400
13401 int _mmplayer_get_timeout(MMHandleType hplayer, int *timeout)
13402 {
13403         mm_player_t* player = (mm_player_t*) hplayer;
13404
13405         MMPLAYER_FENTER();
13406
13407         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13408         MMPLAYER_RETURN_VAL_IF_FAIL(timeout, MM_ERROR_COMMON_INVALID_ARGUMENT);
13409
13410         if (MMPLAYER_IS_STREAMING(player))
13411                 *timeout = player->ini.live_state_change_timeout;
13412         else
13413                 *timeout = player->ini.localplayback_state_change_timeout;
13414
13415         LOGD("timeout = %d\n", *timeout);
13416
13417         MMPLAYER_FLEAVE();
13418         return MM_ERROR_NONE;
13419 }
13420
13421 int _mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int *extra_num)
13422 {
13423         mm_player_t* player = (mm_player_t*) hplayer;
13424
13425         MMPLAYER_FENTER();
13426
13427         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13428         MMPLAYER_RETURN_VAL_IF_FAIL(num && extra_num, MM_ERROR_COMMON_INVALID_ARGUMENT);
13429
13430         *num = player->video_num_buffers;
13431         *extra_num = player->video_extra_num_buffers;
13432
13433         LOGD("state %d, num %d(%d)\n", MMPLAYER_CURRENT_STATE(player), *num, *extra_num);
13434
13435         MMPLAYER_FLEAVE();
13436         return MM_ERROR_NONE;
13437 }
13438
13439 static void
13440 __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type)
13441 {
13442         int i = 0;
13443         MMPLAYER_FENTER();
13444         MMPLAYER_RETURN_IF_FAIL(player);
13445
13446         for (i = 0; i < MMPLAYER_PATH_MAX; i++) {
13447
13448                 if (path_type == MMPLAYER_PATH_MAX || path_type == i) {
13449                         player->storage_info[i].type = STORAGE_TYPE_INTERNAL;
13450                         player->storage_info[i].state = STORAGE_STATE_UNMOUNTABLE;
13451                         player->storage_info[i].id = -1;
13452                         memset(player->storage_info[i].path, 0x00, MM_MAX_URL_LEN);
13453
13454                         if (path_type != MMPLAYER_PATH_MAX)
13455                                 break;
13456                 }
13457         }
13458
13459         MMPLAYER_FLEAVE();
13460 }
13461
13462 int _mmplayer_manage_external_storage_state(MMHandleType hplayer, int id, int state)
13463 {
13464         int ret = MM_ERROR_NONE;
13465         mm_player_t* player = (mm_player_t*)hplayer;
13466         MMMessageParamType msg_param = {0, };
13467
13468         MMPLAYER_FENTER();
13469         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13470
13471         LOGW("state changed storage %d:%d", id, state);
13472
13473         if (state != STORAGE_STATE_UNMOUNTABLE && state != STORAGE_STATE_REMOVED)
13474                 return MM_ERROR_NONE;
13475
13476         /* FIXME: text path should be handled seperately. */
13477         if (((player->storage_info[MMPLAYER_PATH_VOD].type == STORAGE_TYPE_EXTERNAL) && (player->storage_info[MMPLAYER_PATH_VOD].id == id)) ||
13478                 ((player->storage_info[MMPLAYER_PATH_TEXT].type == STORAGE_TYPE_EXTERNAL) && (player->storage_info[MMPLAYER_PATH_TEXT].id == id))) {
13479                 LOGW("external storage is removed");
13480
13481                 if (player->msg_posted == FALSE) {
13482                         memset(&msg_param, 0, sizeof(MMMessageParamType));
13483                         msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
13484                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
13485                         player->msg_posted = TRUE;
13486                 }
13487
13488                 /* unrealize the player */
13489                 ret = _mmplayer_unrealize(hplayer);
13490                 if (ret != MM_ERROR_NONE)
13491                         LOGE("failed to unrealize");
13492         }
13493
13494         MMPLAYER_FLEAVE();
13495         return ret;
13496 }
13497
13498 int _mmplayer_get_adaptive_variant_info(MMHandleType hplayer, int *num, char **var_info)
13499 {
13500         int ret = MM_ERROR_NONE;
13501         mm_player_t* player = (mm_player_t*) hplayer;
13502         int idx = 0, total = 0;
13503         gchar *result = NULL, *tmp = NULL;
13504
13505         MMPLAYER_FENTER();
13506         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13507         MMPLAYER_RETURN_VAL_IF_FAIL(num && var_info, MM_ERROR_COMMON_INVALID_ARGUMENT);
13508
13509         total = *num = g_list_length(player->adaptive_info.var_list);
13510         if (total <= 0) {
13511                 LOGW("There is no stream variant info.");
13512                 return ret;
13513         }
13514
13515         result = g_strdup("");
13516         for (idx = 0 ; idx < total ; idx++) {
13517                 VariantData *v_data = NULL;
13518                 v_data = g_list_nth_data(player->adaptive_info.var_list, idx);
13519
13520                 if (v_data) {
13521                         gchar data[64] = {0};
13522                         snprintf(data, sizeof(data), "%d,%d,%d,", v_data->bandwidth, v_data->width, v_data->height);
13523
13524                         tmp = g_strconcat(result, data, NULL);
13525                         g_free(result);
13526                         result = tmp;
13527                 } else {
13528                         LOGW("There is no variant data in %d", idx);
13529                         (*num)--;
13530                 }
13531         }
13532
13533         *var_info = (char *)result;
13534
13535         LOGD("variant info %d:%s", *num, *var_info);
13536         MMPLAYER_FLEAVE();
13537         return ret;
13538 }
13539
13540 int _mmplayer_set_max_adaptive_variant_limit(MMHandleType hplayer, int bandwidth, int width, int height)
13541 {
13542         int ret = MM_ERROR_NONE;
13543         mm_player_t* player = (mm_player_t*) hplayer;
13544
13545         MMPLAYER_FENTER();
13546         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13547
13548         LOGD("set limit to [b]%d, [w]%d, [h]%d", bandwidth, width, height);
13549
13550         player->adaptive_info.limit.bandwidth = (bandwidth >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (bandwidth) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
13551         player->adaptive_info.limit.width = (width >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (width) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
13552         player->adaptive_info.limit.height = (height >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (height) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
13553
13554         if (player->pipeline && player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst) {
13555                 LOGD("update max limit of %s", GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst));
13556                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
13557                                                 "max-bandwidth", bandwidth, "max-video-width", width, "max-video-height", height, NULL);
13558
13559                 /* FIXME: seek to current position for applying new variant limitation */
13560         }
13561
13562         MMPLAYER_FLEAVE();
13563         return ret;
13564
13565 }
13566
13567 int _mmplayer_get_max_adaptive_variant_limit(MMHandleType hplayer, int *bandwidth, int *width, int *height)
13568 {
13569         int ret = MM_ERROR_NONE;
13570         mm_player_t* player = (mm_player_t*) hplayer;
13571
13572         MMPLAYER_FENTER();
13573         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13574         MMPLAYER_RETURN_VAL_IF_FAIL(bandwidth && width && height, MM_ERROR_COMMON_INVALID_ARGUMENT);
13575
13576         *bandwidth = player->adaptive_info.limit.bandwidth;
13577         *width = player->adaptive_info.limit.width;
13578         *height = player->adaptive_info.limit.height;
13579
13580         LOGD("get limit to [b]%d, [w]%d, [h]%d", *bandwidth, *width, *height);
13581
13582         MMPLAYER_FLEAVE();
13583         return ret;
13584 }
13585
13586 int _mmplayer_set_streaming_buffering_time(MMHandleType hplayer, int buffer_ms, int rebuffer_ms)
13587 {
13588         int ret = MM_ERROR_NONE;
13589         mm_player_t* player = (mm_player_t*) hplayer;
13590
13591         MMPLAYER_FENTER();
13592         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13593
13594         if (MMPLAYER_CURRENT_STATE(player) !=  MM_PLAYER_STATE_NULL)
13595                 LOGW("buffer_ms will not be applied.");
13596
13597
13598         LOGD("set buffering time %d ms / %d ms", buffer_ms, rebuffer_ms);
13599
13600         if (player->streamer == NULL) {
13601                 player->streamer = __mm_player_streaming_create();
13602                 __mm_player_streaming_initialize(player->streamer);
13603         }
13604
13605         if (buffer_ms >= 0)
13606                 player->streamer->buffering_req.prebuffer_time = buffer_ms;
13607
13608         if (rebuffer_ms >= 0)
13609                 player->streamer->buffering_req.rebuffer_time = rebuffer_ms;
13610
13611         MMPLAYER_FLEAVE();
13612         return ret;
13613
13614 }
13615
13616 int _mmplayer_get_streaming_buffering_time(MMHandleType hplayer, int *buffer_ms, int *rebuffer_ms)
13617 {
13618         int ret = MM_ERROR_NONE;
13619         mm_player_t* player = (mm_player_t*) hplayer;
13620
13621         MMPLAYER_FENTER();
13622         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13623         MMPLAYER_RETURN_VAL_IF_FAIL(buffer_ms && rebuffer_ms, MM_ERROR_COMMON_INVALID_ARGUMENT);
13624
13625         if (player->streamer == NULL) {
13626                 player->streamer = __mm_player_streaming_create();
13627                 __mm_player_streaming_initialize(player->streamer);
13628         }
13629
13630         *buffer_ms = player->streamer->buffering_req.prebuffer_time;
13631         *rebuffer_ms = player->streamer->buffering_req.rebuffer_time;
13632
13633         LOGD("buffering time %d ms / %d ms", *buffer_ms, *rebuffer_ms);
13634
13635         MMPLAYER_FLEAVE();
13636         return ret;
13637 }
13638
13639 int _mmplayer_set_codec_type(MMHandleType hplayer, MMPlayerStreamType stream_type, MMPlayerVideoCodecType codec_type)
13640 {
13641 #define IDX_FIRST_SW_CODEC 0
13642         mm_player_t* player = (mm_player_t*) hplayer;
13643         const char* attr_name = (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO) ? (MM_PLAYER_AUDIO_CODEC_TYPE) : (MM_PLAYER_VIDEO_CODEC_TYPE);
13644         MMHandleType attrs = 0;
13645
13646         MMPLAYER_FENTER();
13647         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13648
13649         LOGD("ini setting : [a][h:%s][s:%s] / [v][h:%s][s:%s]",
13650                 player->ini.audiocodec_element_hw, player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC],
13651                 player->ini.videocodec_element_hw, player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC]);
13652
13653         switch (stream_type) {
13654         case MM_PLAYER_STREAM_TYPE_AUDIO:
13655                 if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
13656                          (!strcmp(player->ini.audiocodec_element_hw, ""))) ||
13657                         ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
13658                          (!strcmp(player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
13659                         LOGE("There is no a codec for codec_type %d", codec_type);
13660                         return MM_ERROR_PLAYER_NO_OP;
13661                 }
13662         break;
13663         case MM_PLAYER_STREAM_TYPE_VIDEO:
13664                 if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
13665                          (!strcmp(player->ini.videocodec_element_hw, ""))) ||
13666                         ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
13667                          (!strcmp(player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
13668                         LOGE("There is no v codec for codec_type %d", codec_type);
13669                         return MM_ERROR_PLAYER_NO_OP;
13670                 }
13671
13672         break;
13673         default:
13674                 LOGE("Invalid stream type %d", stream_type);
13675                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
13676         break;
13677         }
13678
13679         LOGD("update %s codec_type to %d", attr_name, codec_type);
13680
13681         attrs = MMPLAYER_GET_ATTRS(player);
13682         mm_attrs_set_int_by_name(attrs, attr_name, codec_type);
13683
13684         if (mmf_attrs_commit(player->attrs)) {
13685                 LOGE("failed to commit codec_type attributes");
13686                 return MM_ERROR_PLAYER_INTERNAL;
13687         }
13688
13689         MMPLAYER_FLEAVE();
13690         return MM_ERROR_NONE;
13691 }
13692
13693 int
13694 _mmplayer_set_replaygain_enabled(MMHandleType hplayer, bool enabled)
13695 {
13696         mm_player_t* player = (mm_player_t*) hplayer;
13697         GstElement* rg_vol_element = NULL;
13698
13699         MMPLAYER_FENTER();
13700
13701         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13702
13703         player->sound.rg_enable = enabled;
13704
13705         /* just hold rgvolume enable value if pipeline is not ready */
13706         if (!player->pipeline || !player->pipeline->audiobin) {
13707                 LOGD("pipeline is not ready. holding rgvolume enable value\n");
13708                 return MM_ERROR_NONE;
13709         }
13710
13711         rg_vol_element = player->pipeline->audiobin[MMPLAYER_A_RGVOL].gst;
13712
13713         if (!rg_vol_element) {
13714                 LOGD("rgvolume element is not created");
13715                 return MM_ERROR_PLAYER_INTERNAL;
13716         }
13717
13718         if (enabled)
13719                 g_object_set(rg_vol_element, "enable-rgvolume", TRUE, NULL);
13720         else
13721                 g_object_set(rg_vol_element, "enable-rgvolume", FALSE, NULL);
13722
13723         MMPLAYER_FLEAVE();
13724
13725         return MM_ERROR_NONE;
13726 }
13727
13728 int
13729 _mmplayer_is_replaygain_enabled(MMHandleType hplayer, bool *enabled)
13730 {
13731         mm_player_t* player = (mm_player_t*) hplayer;
13732         GstElement* rg_vol_element = NULL;
13733         gboolean enable = FALSE;
13734
13735         MMPLAYER_FENTER();
13736
13737         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13738         MMPLAYER_RETURN_VAL_IF_FAIL(enabled, MM_ERROR_INVALID_ARGUMENT);
13739
13740         /* just hold enable_rg value if pipeline is not ready */
13741         if (!player->pipeline || !player->pipeline->audiobin) {
13742                 LOGD("pipeline is not ready. holding rgvolume value (%d)\n", player->sound.rg_enable);
13743                 *enabled = player->sound.rg_enable;
13744                 return MM_ERROR_NONE;
13745         }
13746
13747         rg_vol_element = player->pipeline->audiobin[MMPLAYER_A_RGVOL].gst;
13748
13749         if (!rg_vol_element) {
13750                 LOGD("rgvolume element is not created");
13751                 return MM_ERROR_PLAYER_INTERNAL;
13752         }
13753
13754         g_object_get(rg_vol_element, "enable-rgvolume", &enable, NULL);
13755         *enabled = enable;
13756
13757         MMPLAYER_FLEAVE();
13758
13759         return MM_ERROR_NONE;
13760 }