[0.6.117] Disconnect bus watch before destroy msg thread
[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_SPHERICAL_DEFAULT_YAW   0  /* sync from video360 plugin */
105 #define PLAYER_SPHERICAL_DEFAULT_PITCH 0
106 #define PLAYER_SPHERICAL_DEFAULT_H_FOV 120
107 #define PLAYER_SPHERICAL_DEFAULT_V_FOV 67
108
109 #define SPATIAL_AUDIO_CAPS             "audio/x-raw,format=S16LE,channels=4"
110 #define FEATURE_NAME_SPHERICAL_VIDEO   "http://tizen.org/feature/multimedia.player.spherical_video"
111
112 /*---------------------------------------------------------------------------
113 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
114 ---------------------------------------------------------------------------*/
115
116 /*---------------------------------------------------------------------------
117 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
118 ---------------------------------------------------------------------------*/
119
120 /*---------------------------------------------------------------------------
121 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
122 ---------------------------------------------------------------------------*/
123
124 /*---------------------------------------------------------------------------
125 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
126 ---------------------------------------------------------------------------*/
127 static sound_stream_info_h stream_info;
128
129 /*---------------------------------------------------------------------------
130 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
131 ---------------------------------------------------------------------------*/
132 static int              __mmplayer_gst_create_pipeline(mm_player_t* player);
133 static int              __mmplayer_gst_destroy_pipeline(mm_player_t* player);
134 static int              __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
135 static int              __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
136 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player);
137 static int              __mmplayer_gst_create_text_sink_bin(mm_player_t* player);
138 static int              __mmplayer_gst_element_link_bucket(GList* element_bucket);
139
140 static GstPadProbeReturn        __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data);
141 static void             __mmplayer_gst_decode_pad_added(GstElement* elem, GstPad* pad, gpointer data);
142 static void             __mmplayer_gst_decode_no_more_pads(GstElement* elem, gpointer data);
143 static void             __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gpointer data);
144 static void             __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad, GstCaps *caps, gpointer data);
145 static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
146 static gint             __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad, GstCaps * caps, GstElementFactory* factory, gpointer data);
147 static void __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad, gpointer data);
148 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
149 static void     __mmplayer_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
150 static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
151 static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
152 static void     __mmplayer_typefind_have_type(GstElement *tf, guint probability, GstCaps *caps, gpointer data);
153 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
154 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
155 static gboolean __mmplayer_is_only_mp3_type(gchar *str_caps);
156 static void     __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
157
158 static void             __mmplayer_gst_rtp_no_more_pads(GstElement *element,  gpointer data);
159 static void             __mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data);
160 static MMStreamingType  __mmplayer_get_stream_service_type(mm_player_t* player);
161 static gboolean __mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
162 static void             __mmplayer_release_misc(mm_player_t* player);
163 static void             __mmplayer_release_misc_post(mm_player_t* player);
164 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
165 static GstBusSyncReply __mmplayer_bus_sync_callback(GstBus * bus, GstMessage * message, gpointer data);
166 static void __mmplayer_gst_callback(GstMessage *msg, gpointer data);
167 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
168 static gboolean      __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
169 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
170 static GstPadProbeReturn __mmplayer_audio_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
171 static void __mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
172 static void __mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
173 static GstPadProbeReturn __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
174 static int __mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index);
175
176 static gboolean __mmplayer_check_subtitle(mm_player_t* player);
177 static gboolean __mmplayer_handle_streaming_error(mm_player_t* player, GstMessage * message);
178 static void             __mmplayer_handle_eos_delay(mm_player_t* player, int delay_in_ms);
179 static void             __mmplayer_cancel_eos_timer(mm_player_t* player);
180 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
181 static int              __mmplayer_handle_missed_plugin(mm_player_t* player);
182 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
183 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
184 static void             __mmplayer_add_sink(mm_player_t* player, GstElement* sink);
185 static void             __mmplayer_del_sink(mm_player_t* player, GstElement* sink);
186 static void             __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
187 static gpointer __mmplayer_next_play_thread(gpointer data);
188 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
189
190 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
191 static GstPadProbeReturn __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data);
192 static void __mmplayer_release_dump_list(GList *dump_list);
193
194 static int              __gst_realize(mm_player_t* player);
195 static int              __gst_unrealize(mm_player_t* player);
196 static int              __gst_start(mm_player_t* player);
197 static int              __gst_stop(mm_player_t* player);
198 static int              __gst_pause(mm_player_t* player, gboolean async);
199 static int              __gst_resume(mm_player_t* player, gboolean async);
200 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
201                                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
202                                         gint64 cur, GstSeekType stop_type, gint64 stop);
203 static int __gst_pending_seek(mm_player_t* player);
204
205 static int              __gst_set_position(mm_player_t* player, int format, gint64 position, gboolean internal_called);
206 static int              __gst_get_position(mm_player_t* player, int format, gint64 *position);
207 static int              __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
208 static int              __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
209 static int              __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
210
211 static gboolean __gst_send_event_to_sink(mm_player_t* player, GstEvent* event);
212
213 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
214 static gboolean __mmplayer_can_extract_pcm(mm_player_t* player);
215
216 /* util */
217 static gboolean __is_ms_buff_src(mm_player_t* player);
218 static gboolean __has_suffix(mm_player_t * player, const gchar * suffix);
219
220 static int __mmplayer_realize_streaming_ext(mm_player_t* player);
221 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
222 static int __mmplayer_start_streaming_ext(mm_player_t *player);
223 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
224 static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
225
226 static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
227 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
228 static void __mmplayer_check_pipeline(mm_player_t* player);
229 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
230 static void __mmplayer_deactivate_old_path(mm_player_t *player);
231
232 static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg);
233 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
234
235 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
236 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name);
237 static void             __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data);
238 static void             __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data);
239 static void     __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data);
240 static void             __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data);
241 static void             __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data);
242 static gboolean __gst_seek_audio_data(GstElement * appsrc, guint64 position, gpointer user_data);
243 static gboolean __gst_seek_video_data(GstElement * appsrc, guint64 position, gpointer user_data);
244 static gboolean __gst_seek_subtitle_data(GstElement * appsrc, guint64 position, gpointer user_data);
245 static void             __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data);
246 static void             __mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all);
247 static void             __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer);
248 static void             __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type);
249 static void             __mmplayer_get_metadata_360_from_tags(GstTagList *tags, mm_player_spherical_metadata_t *metadata);
250 static int              __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res, void *user_data);
251
252 /*===========================================================================================
253 |                                                                                                                                                                                       |
254 |  FUNCTION DEFINITIONS                                                                                                                                         |
255 |                                                                                                                                                                                       |
256 ========================================================================================== */
257
258 #if 0 //debug
259 static void
260 print_tag(const GstTagList * list, const gchar * tag, gpointer unused)
261 {
262         gint i, count;
263
264         count = gst_tag_list_get_tag_size(list, tag);
265
266         LOGD("count = %d", count);
267
268         for (i = 0; i < count; i++) {
269                 gchar *str;
270
271                 if (gst_tag_get_type(tag) == G_TYPE_STRING) {
272                         if (!gst_tag_list_get_string_index(list, tag, i, &str))
273                                 g_assert_not_reached();
274                 } else
275                         str = g_strdup_value_contents(gst_tag_list_get_value_index(list, tag, i));
276
277                 if (i == 0)
278                         g_print("  %15s: %s\n", gst_tag_get_nick(tag), str);
279                 else
280                         g_print("                 : %s\n", str);
281
282                 g_free(str);
283         }
284 }
285 #endif
286
287 /* This function should be called after the pipeline goes PAUSED or higher
288 state. */
289 gboolean
290 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag)
291 {
292         static gboolean has_duration = FALSE;
293         static gboolean has_video_attrs = FALSE;
294         static gboolean has_audio_attrs = FALSE;
295         static gboolean has_bitrate = FALSE;
296         gboolean missing_only = FALSE;
297         gboolean all = FALSE;
298         gint64 dur_nsec = 0;
299         GstStructure* p = NULL;
300         MMHandleType attrs = 0;
301         gchar *path = NULL;
302         struct stat sb;
303
304         MMPLAYER_FENTER();
305
306         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
307
308         /* check player state here */
309         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
310                 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) {
311                 /* give warning now only */
312                 LOGW("be careful. content attributes may not available in this state ");
313         }
314
315         /* get content attribute first */
316         attrs = MMPLAYER_GET_ATTRS(player);
317         if (!attrs) {
318                 LOGE("cannot get content attribute");
319                 return FALSE;
320         }
321
322         /* get update flag */
323
324         if (flag & ATTR_MISSING_ONLY) {
325                 missing_only = TRUE;
326                 LOGD("updating missed attr only");
327         }
328
329         if (flag & ATTR_ALL) {
330                 all = TRUE;
331                 has_duration = FALSE;
332                 has_video_attrs = FALSE;
333                 has_audio_attrs = FALSE;
334                 has_bitrate = FALSE;
335
336                 LOGD("updating all attrs");
337         }
338
339         if (missing_only && all) {
340                 LOGW("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
341                 missing_only = FALSE;
342         }
343
344         if ((flag & ATTR_DURATION) || (!has_duration && missing_only) || all) {
345                 LOGD("try to update duration");
346                 has_duration = FALSE;
347
348                 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec) && (dur_nsec > 0)) {
349                         player->duration = dur_nsec;
350                         LOGW("duration : %"G_GINT64_FORMAT" msec", GST_TIME_AS_MSECONDS(dur_nsec));
351                         has_duration = TRUE;
352                 }
353
354                 if (player->duration < 0) {
355                         LOGW("duration is Non-Initialized !!!");
356                         player->duration = 0;
357                 }
358
359                 /* update streaming service type */
360                 player->streaming_type =  __mmplayer_get_stream_service_type(player);
361
362                 /* check duration is OK */
363                 if (dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING(player)) {
364                         /* FIXIT : find another way to get duration here. */
365                         LOGW("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
366                 }
367         }
368
369         if ((flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all) {
370                 /* update audio params
371                 NOTE : We need original audio params and it can be only obtained from src pad of audio
372                 decoder. Below code only valid when we are not using 'resampler' just before
373                 'audioconverter'. */
374
375                 LOGD("try to update audio attrs");
376                 has_audio_attrs = FALSE;
377
378                 if (player->pipeline->audiobin &&
379                          player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
380                         GstCaps *caps_a = NULL;
381                         GstPad* pad = NULL;
382                         gint samplerate = 0, channels = 0;
383
384                         pad = gst_element_get_static_pad(
385                                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink");
386
387                         if (pad) {
388                                 caps_a = gst_pad_get_current_caps(pad);
389
390                                 if (caps_a) {
391                                         p = gst_caps_get_structure(caps_a, 0);
392
393                                         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
394
395                                         gst_structure_get_int(p, "rate", &samplerate);
396                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
397
398                                         gst_structure_get_int(p, "channels", &channels);
399                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
400
401                                         SECURE_LOGD("samplerate : %d    channels : %d", samplerate, channels);
402
403                                         gst_caps_unref(caps_a);
404                                         caps_a = NULL;
405
406                                         has_audio_attrs = TRUE;
407                                 } else
408                                         LOGW("not ready to get audio caps");
409
410                                 gst_object_unref(pad);
411                         } else
412                                 LOGW("failed to get pad from audiosink");
413                 }
414         }
415
416         if ((flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all) {
417                 LOGD("try to update video attrs");
418                 has_video_attrs = FALSE;
419
420                 if (player->pipeline->videobin &&
421                          player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
422                         GstCaps *caps_v = NULL;
423                         GstPad* pad = NULL;
424                         gint tmpNu, tmpDe;
425                         gint width, height;
426
427                         pad = gst_element_get_static_pad(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink");
428                         if (pad) {
429                                 caps_v = gst_pad_get_current_caps(pad);
430
431                                 /* Use v_stream_caps, if fail to get video_sink sink pad*/
432                                 if (!caps_v && player->v_stream_caps) {
433                                         caps_v = player->v_stream_caps;
434                                         gst_caps_ref(caps_v);
435                                 }
436
437                                 if (caps_v) {
438                                         p = gst_caps_get_structure(caps_v, 0);
439                                         gst_structure_get_int(p, "width", &width);
440                                         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
441
442                                         gst_structure_get_int(p, "height", &height);
443                                         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
444
445                                         gst_structure_get_fraction(p, "framerate", &tmpNu, &tmpDe);
446
447                                         SECURE_LOGD("width : %d     height : %d", width, height);
448
449                                         gst_caps_unref(caps_v);
450                                         caps_v = NULL;
451
452                                         if (tmpDe > 0) {
453                                                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
454                                                 SECURE_LOGD("fps : %d", tmpNu / tmpDe);
455                                         }
456
457                                         has_video_attrs = TRUE;
458                                 } else
459                                         LOGD("no negitiated caps from videosink");
460                                 gst_object_unref(pad);
461                                 pad = NULL;
462                         } else {
463                                 LOGD("no videosink sink pad");
464                         }
465                 }
466         }
467
468
469         if ((flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all) {
470                 has_bitrate = FALSE;
471
472                 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
473                 if (player->duration) {
474                         guint64 data_size = 0;
475
476                         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
477                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
478
479                                 if (stat(path, &sb) == 0)
480                                         data_size = (guint64)sb.st_size;
481                         } else if (MMPLAYER_IS_HTTP_STREAMING(player)) {
482                                 data_size = player->http_content_size;
483                         }
484                         LOGD("try to update bitrate : data_size = %"G_GUINT64_FORMAT, data_size);
485
486                         if (data_size) {
487                                 guint64 bitrate = 0;
488                                 guint64 msec_dur = 0;
489
490                                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
491                                 if (msec_dur > 0) {
492                                         bitrate = data_size * 8 * 1000 / msec_dur;
493                                         SECURE_LOGD("file size : %u, video bitrate = %llu", data_size, bitrate);
494                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
495
496                                         has_bitrate = TRUE;
497                                 } else {
498                                         LOGD("player duration is less than 0");
499                                 }
500                         }
501
502                         if (MMPLAYER_IS_RTSP_STREAMING(player)) {
503                                 if (player->total_bitrate) {
504                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
505                                         has_bitrate = TRUE;
506                                 }
507                         }
508                 }
509         }
510
511         /* validate all */
512         if (mmf_attrs_commit(attrs)) {
513                 LOGE("failed to update attributes\n");
514                 return FALSE;
515         }
516
517         MMPLAYER_FLEAVE();
518
519         return TRUE;
520 }
521
522 static MMStreamingType __mmplayer_get_stream_service_type(mm_player_t* player)
523 {
524         MMStreamingType streaming_type = STREAMING_SERVICE_NONE;
525
526         MMPLAYER_FENTER();
527
528         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
529                         player->pipeline &&
530                         player->pipeline->mainbin &&
531                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
532                         STREAMING_SERVICE_NONE);
533
534         /* streaming service type if streaming */
535         if (!MMPLAYER_IS_STREAMING(player))
536                 return STREAMING_SERVICE_NONE;
537
538         if (MMPLAYER_IS_HTTP_STREAMING(player))
539                 streaming_type = (player->duration == 0) ?
540                         STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
541
542         switch (streaming_type) {
543         case STREAMING_SERVICE_LIVE:
544                 LOGD("it's live streaming");
545                 break;
546         case STREAMING_SERVICE_VOD:
547                 LOGD("it's vod streaming");
548                 break;
549         default:
550                 LOGE("should not get here");
551                 break;
552         }
553
554         MMPLAYER_FLEAVE();
555
556         return streaming_type;
557 }
558
559
560 /* this function sets the player state and also report
561  * it to applicaton by calling callback function
562  */
563 int
564 __mmplayer_set_state(mm_player_t* player, int state)
565 {
566         MMMessageParamType msg = {0, };
567         gboolean post_bos = FALSE;
568
569         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
570
571         if (MMPLAYER_CURRENT_STATE(player) == state) {
572                 LOGW("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
573                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
574                 return MM_ERROR_NONE;
575         }
576
577         /* update player states */
578         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
579         MMPLAYER_CURRENT_STATE(player) = state;
580
581         if (MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player))
582                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
583
584         /* print state */
585         MMPLAYER_PRINT_STATE(player);
586
587         switch (MMPLAYER_CURRENT_STATE(player)) {
588         case MM_PLAYER_STATE_NULL:
589         case MM_PLAYER_STATE_READY:
590                 break;
591
592         case MM_PLAYER_STATE_PAUSED:
593                 {
594                         if (!player->sent_bos) {
595                                 /* rtsp case, get content attrs by GstMessage */
596                                 if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
597                                         /* it's first time to update all content attrs. */
598                                         _mmplayer_update_content_attrs(player, ATTR_ALL);
599                                 }
600                         }
601
602                         /* add audio callback probe if condition is satisfied */
603                         if (!player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
604                                 __mmplayer_configure_audio_callback(player);
605
606                         /* FIXIT : handle return value */
607                 }
608                 break;
609
610         case MM_PLAYER_STATE_PLAYING:
611                 {
612                         /* try to get content metadata */
613                         if (!player->sent_bos) {
614                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
615                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
616                                  * legacy mmfw-player api */
617                                 _mmplayer_update_content_attrs(player, ATTR_MISSING_ONLY);
618                         }
619
620                         if ((player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME)) {
621                                 if (!player->sent_bos)
622                                         __mmplayer_handle_missed_plugin(player);
623                         }
624
625                         if (player->resumed_by_rewind && player->playback_rate < 0.0) {
626                                 /* initialize because auto resume is done well. */
627                                 player->resumed_by_rewind = FALSE;
628                                 player->playback_rate = 1.0;
629                         }
630
631                         if (!player->sent_bos) {
632                                 /* check audio codec field is set or not
633                                  * we can get it from typefinder or codec's caps.
634                                  */
635                                 gchar *audio_codec = NULL;
636                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
637
638                                 /* The codec format can't be sent for audio only case like amr, mid etc.
639                                  * Because, parser don't make related TAG.
640                                  * So, if it's not set yet, fill it with found data.
641                                  */
642                                 if (!audio_codec) {
643                                         if (g_strrstr(player->type, "audio/midi"))
644                                                 audio_codec = g_strdup("MIDI");
645                                         else if (g_strrstr(player->type, "audio/x-amr"))
646                                                 audio_codec = g_strdup("AMR");
647                                         else if (g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion= (int)1"))
648                                                 audio_codec = g_strdup("AAC");
649                                         else
650                                                 audio_codec = g_strdup("unknown");
651                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
652
653                                         MMPLAYER_FREEIF(audio_codec);
654                                         if (mmf_attrs_commit(player->attrs))
655                                                 LOGE("failed to update attributes\n");
656
657                                         LOGD("set audio codec type with caps\n");
658                                 }
659
660                                 post_bos = TRUE;
661                         }
662                 }
663                 break;
664
665         case MM_PLAYER_STATE_NONE:
666         default:
667                 LOGW("invalid target state, there is nothing to do.\n");
668                 break;
669         }
670
671
672         /* post message to application */
673         if (MMPLAYER_TARGET_STATE(player) == state) {
674                 /* fill the message with state of player */
675                 msg.union_type = MM_MSG_UNION_STATE;
676                 msg.state.previous = MMPLAYER_PREV_STATE(player);
677                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
678
679                 LOGD("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
680
681                 /* state changed by resource callback */
682                 if (player->interrupted_by_resource) {
683                         msg.state.code = MM_PLAYER_FOCUS_CHANGED_BY_RESOURCE_CONFLICT;
684                         MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
685                 } else { /* state changed by usecase */
686                         MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_CHANGED, &msg);
687                 }
688         } else {
689                 LOGD("intermediate state, do nothing.\n");
690                 MMPLAYER_PRINT_STATE(player);
691                 return MM_ERROR_NONE;
692         }
693
694         if (post_bos) {
695                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BEGIN_OF_STREAM, NULL);
696                 player->sent_bos = TRUE;
697         }
698
699         return MM_ERROR_NONE;
700 }
701
702 static gpointer __mmplayer_next_play_thread(gpointer data)
703 {
704         mm_player_t* player = (mm_player_t*) data;
705         MMPlayerGstElement *mainbin = NULL;
706
707         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
708
709         MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
710         while (!player->next_play_thread_exit) {
711                 LOGD("next play thread started. waiting for signal.\n");
712                 MMPLAYER_NEXT_PLAY_THREAD_WAIT(player);
713
714                 LOGD("reconfigure pipeline for gapless play.\n");
715
716                 if (player->next_play_thread_exit) {
717                         if (player->gapless.reconfigure) {
718                                 player->gapless.reconfigure = false;
719                                 MMPLAYER_PLAYBACK_UNLOCK(player);
720                         }
721                         LOGD("exiting gapless play thread\n");
722                         break;
723                 }
724
725                 mainbin = player->pipeline->mainbin;
726
727                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
728                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
729                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
730                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
731                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
732
733                 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
734         }
735         MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
736
737         return NULL;
738 }
739
740 static void
741 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
742 {
743         MMHandleType attrs = 0;
744         guint64 data_size = 0;
745         gchar* path = NULL;
746         gint64 pos_nsec = 0;
747         struct stat sb;
748
749         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
750
751         __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_nsec);       /* to update player->last_position */
752
753         attrs = MMPLAYER_GET_ATTRS(player);
754         if (!attrs) {
755                 LOGE("fail to get attributes.\n");
756                 return;
757         }
758
759         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
760                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
761
762                 if (stat(path, &sb) == 0)
763                         data_size = (guint64)sb.st_size;
764         } else if (MMPLAYER_IS_HTTP_STREAMING(player))
765                 data_size = player->http_content_size;
766
767         __mm_player_streaming_buffering(player->streamer,
768                                                                                 buffering_msg,
769                                                                                 data_size,
770                                                                                 player->last_position,
771                                                                                 player->duration);
772
773         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
774
775         return;
776 }
777
778 static int
779 __mmplayer_handle_buffering_message(mm_player_t* player)
780 {
781         int ret = MM_ERROR_NONE;
782         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
783         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
784         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
785         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
786
787         if (!player || !player->streamer || (MMPLAYER_IS_LIVE_STREAMING(player) && MMPLAYER_IS_RTSP_STREAMING(player))) {
788                 LOGW("do nothing for buffering msg\n");
789                 ret = MM_ERROR_PLAYER_INVALID_STATE;
790                 goto exit;
791         }
792
793         prev_state = MMPLAYER_PREV_STATE(player);
794         current_state = MMPLAYER_CURRENT_STATE(player);
795         target_state = MMPLAYER_TARGET_STATE(player);
796         pending_state = MMPLAYER_PENDING_STATE(player);
797
798         LOGD("player state : prev %s, current %s, pending %s, target %s, buffering %d",
799                 MMPLAYER_STATE_GET_NAME(prev_state),
800                 MMPLAYER_STATE_GET_NAME(current_state),
801                 MMPLAYER_STATE_GET_NAME(pending_state),
802                 MMPLAYER_STATE_GET_NAME(target_state),
803                 player->streamer->is_buffering);
804
805         if (!player->streamer->is_buffering) {
806                 /* NOTE : if buffering has done, player has to go to target state. */
807                 switch (target_state) {
808                 case MM_PLAYER_STATE_PAUSED:
809                         {
810                                 switch (pending_state) {
811                                 case MM_PLAYER_STATE_PLAYING:
812                                         __gst_pause(player, TRUE);
813                                         break;
814
815                                 case MM_PLAYER_STATE_PAUSED:
816                                         LOGD("player is already going to paused state, there is nothing to do.\n");
817                                         break;
818
819                                 case MM_PLAYER_STATE_NONE:
820                                 case MM_PLAYER_STATE_NULL:
821                                 case MM_PLAYER_STATE_READY:
822                                 default:
823                                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
824                                         break;
825                                 }
826                         }
827                         break;
828
829                 case MM_PLAYER_STATE_PLAYING:
830                         {
831                                 switch (pending_state) {
832                                 case MM_PLAYER_STATE_NONE:
833                                         {
834                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
835                                                         __gst_resume(player, TRUE);
836                                         }
837                                         break;
838
839                                 case MM_PLAYER_STATE_PAUSED:
840                                         /* NOTE: It should be worked as asynchronously.
841                                          * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
842                                          */
843                                         if (current_state == MM_PLAYER_STATE_PLAYING) {
844                                                 /* NOTE: If the current state is PLAYING, it means, async __gst_pause() is not completed yet.
845                                                  * The current state should be changed to paused purposely to prevent state conflict.
846                                                  */
847                                                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
848                                         }
849                                         __gst_resume(player, TRUE);
850                                         break;
851
852                                 case MM_PLAYER_STATE_PLAYING:
853                                         LOGD("player is already going to playing state, there is nothing to do.\n");
854                                         break;
855
856                                 case MM_PLAYER_STATE_NULL:
857                                 case MM_PLAYER_STATE_READY:
858                                 default:
859                                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
860                                         break;
861                                 }
862                         }
863                         break;
864
865                 case MM_PLAYER_STATE_NULL:
866                 case MM_PLAYER_STATE_READY:
867                 case MM_PLAYER_STATE_NONE:
868                 default:
869                         LOGW("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state));
870                         break;
871                 }
872         } else {
873                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
874                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
875                  */
876                 switch (pending_state) {
877                 case MM_PLAYER_STATE_NONE:
878                         {
879                                 if (current_state != MM_PLAYER_STATE_PAUSED) {
880                                         /* rtsp streaming pause makes rtsp server stop sending data. */
881                                         if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
882                                                 LOGD("set pause state during buffering\n");
883                                                 __gst_pause(player, TRUE);
884                                         }
885                                 }
886                         }
887                         break;
888
889                 case MM_PLAYER_STATE_PLAYING:
890                         /* rtsp streaming pause makes rtsp server stop sending data. */
891                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
892                                 __gst_pause(player, TRUE);
893                         break;
894
895                 case MM_PLAYER_STATE_PAUSED:
896                         break;
897
898                 case MM_PLAYER_STATE_NULL:
899                 case MM_PLAYER_STATE_READY:
900                 default:
901                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
902                         break;
903                 }
904         }
905
906 exit:
907         return ret;
908 }
909
910 static void
911 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
912 {
913         MMPlayerGstElement *textbin;
914         MMPLAYER_FENTER();
915
916         MMPLAYER_RETURN_IF_FAIL(player &&
917                                         player->pipeline &&
918                                         player->pipeline->textbin);
919
920         MMPLAYER_RETURN_IF_FAIL(player->pipeline->textbin[MMPLAYER_T_IDENTITY].gst);
921
922         textbin = player->pipeline->textbin;
923
924         if (is_drop) {
925                 LOGD("Drop subtitle text after getting EOS\n");
926
927                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
928                 g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
929
930                 player->is_subtitle_force_drop = TRUE;
931         } else {
932                 if (player->is_subtitle_force_drop == TRUE) {
933                         LOGD("Enable subtitle data path without drop\n");
934
935                         g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
936                         g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
937
938                         LOGD("non-connected with external display");
939
940                         player->is_subtitle_force_drop = FALSE;
941                 }
942         }
943 }
944
945 static VariantData *
946 __mmplayer_adaptive_var_info(const VariantData *self, gpointer user_data)
947 {
948         VariantData *var_info = NULL;
949         g_return_val_if_fail(self != NULL, NULL);
950
951         var_info = g_new0(VariantData, 1);
952         if (!var_info) return NULL;
953         var_info->bandwidth = self->bandwidth;
954         var_info->width = self->width;
955         var_info->height = self->height;
956         return var_info;
957 }
958
959 void _mmplayer_bus_msg_thread_destroy(MMHandleType hplayer)
960 {
961         mm_player_t* player = (mm_player_t*)hplayer;
962         GstMessage *msg = NULL;
963         GQueue *queue = NULL;
964
965         MMPLAYER_FENTER();
966         MMPLAYER_RETURN_IF_FAIL(player);
967
968         /* disconnecting bus watch */
969         if (player->bus_watcher)
970                 __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
971         player->bus_watcher = 0;
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
1389                                         if (!player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
1390                                                 __mmplayer_configure_audio_callback(player);
1391
1392                                         if (!player->sent_bos && oldstate == GST_STATE_READY) {
1393                                                 // managed prepare async case
1394                                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
1395                                                 LOGD("checking prepare mode for async transition - %d", prepare_async);
1396                                         }
1397
1398                                         if (MMPLAYER_IS_STREAMING(player) || MMPLAYER_IS_MS_BUFF_SRC(player) || prepare_async) {
1399                                                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
1400
1401                                                 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
1402                                                         __mm_player_streaming_set_content_bitrate(player->streamer,
1403                                                                 player->total_maximum_bitrate, player->total_bitrate);
1404
1405                                                 if (player->pending_seek.is_pending) {
1406                                                         LOGW("trying to do pending seek");
1407                                                         MMPLAYER_CMD_LOCK(player);
1408                                                         __gst_pending_seek(player);
1409                                                         MMPLAYER_CMD_UNLOCK(player);
1410                                                 }
1411                                         }
1412                                 }
1413                                 break;
1414
1415                         case GST_STATE_PLAYING:
1416                                 {
1417                                         if (MMPLAYER_IS_STREAMING(player)) {
1418                                                 // managed prepare async case when buffering is completed
1419                                                 // pending state should be reset otherwise, it's still playing even though it's resumed after bufferging.
1420                                                 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
1421                                                         (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
1422                                                         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
1423
1424                                                 if (MMPLAYER_IS_RTSP_STREAMING(player) && (MMPLAYER_IS_LIVE_STREAMING(player))) {
1425
1426                                                         LOGD("Current Buffering Percent = %d", player->streamer->buffering_percent);
1427                                                         if (player->streamer->buffering_percent < 100) {
1428
1429                                                                 MMMessageParamType msg_param = {0, };
1430                                                                 LOGW("Posting Buffering Completed Message to Application !!!");
1431
1432                                                                 msg_param.connection.buffering = 100;
1433                                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1434                                                         }
1435                                                 }
1436                                         }
1437
1438                                         if (player->gapless.stream_changed) {
1439                                                 _mmplayer_update_content_attrs(player, ATTR_ALL);
1440                                                 player->gapless.stream_changed = FALSE;
1441                                         }
1442
1443                                         if (player->doing_seek && async_done) {
1444                                                 player->doing_seek = FALSE;
1445                                                 async_done = FALSE;
1446                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1447                                         }
1448                                 }
1449                                 break;
1450
1451                         default:
1452                                 break;
1453                         }
1454                 }
1455                 break;
1456
1457         case GST_MESSAGE_CLOCK_LOST:
1458                         {
1459                                 GstClock *clock = NULL;
1460                                 gboolean need_new_clock = FALSE;
1461
1462                                 gst_message_parse_clock_lost(msg, &clock);
1463                                 LOGD("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
1464
1465                                 if (!player->videodec_linked)
1466                                         need_new_clock = TRUE;
1467                                 else if (!player->ini.use_system_clock)
1468                                         need_new_clock = TRUE;
1469
1470                                 if (need_new_clock) {
1471                                         LOGD("Provide clock is TRUE, do pause->resume\n");
1472                                         __gst_pause(player, FALSE);
1473                                         __gst_resume(player, FALSE);
1474                                 }
1475                         }
1476                         break;
1477
1478         case GST_MESSAGE_NEW_CLOCK:
1479                         {
1480                                 GstClock *clock = NULL;
1481                                 gst_message_parse_new_clock(msg, &clock);
1482                                 LOGD("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
1483                         }
1484                         break;
1485
1486         case GST_MESSAGE_ELEMENT:
1487                         {
1488                                 const gchar *structure_name;
1489                                 gint count = 0, idx = 0;
1490                                 MMHandleType attrs = 0;
1491
1492                                 attrs = MMPLAYER_GET_ATTRS(player);
1493                                 if (!attrs) {
1494                                         LOGE("cannot get content attribute");
1495                                         break;
1496                                 }
1497
1498                                 if (gst_message_get_structure(msg) == NULL)
1499                                         break;
1500
1501                                 structure_name = gst_structure_get_name(gst_message_get_structure(msg));
1502                                 if (!structure_name)
1503                                         break;
1504
1505                                 LOGD("GST_MESSAGE_ELEMENT %s from %s", structure_name, GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)));
1506
1507                                 if (!strcmp(structure_name, "adaptive-streaming-variant")) {
1508                                         const GValue *var_info = NULL;
1509
1510                                         var_info = gst_structure_get_value(gst_message_get_structure(msg), "video-variant-info");
1511                                         if (var_info != NULL) {
1512                                                 if (player->adaptive_info.var_list)
1513                                                         g_list_free_full(player->adaptive_info.var_list, g_free);
1514
1515                                                 /* share addr or copy the list */
1516                                                 player->adaptive_info.var_list =
1517                                                         g_list_copy_deep((GList *)g_value_get_pointer(var_info), (GCopyFunc)__mmplayer_adaptive_var_info, NULL);
1518
1519                                                 count = g_list_length(player->adaptive_info.var_list);
1520                                                 if (count > 0) {
1521                                                         VariantData *temp = NULL;
1522
1523                                                         /* print out for debug */
1524                                                         LOGD("num of variant_info %d", count);
1525                                                         for (idx = 0; idx < count; idx++) {
1526                                                                 temp = g_list_nth_data(player->adaptive_info.var_list, idx);
1527                                                                 if (temp)
1528                                                                         LOGD("variant(%d) [b]%d [w]%d [h]%d ", idx, temp->bandwidth, temp->width, temp->height);
1529                                                         }
1530                                                 }
1531                                         }
1532                                 }
1533
1534                                 if (!strcmp(structure_name, "prepare-decode-buffers")) {
1535                                         gint num_buffers = 0;
1536                                         gint extra_num_buffers = 0;
1537
1538                                         if (gst_structure_get_int(gst_message_get_structure(msg), "num_buffers", &num_buffers)) {
1539                                                 player->video_num_buffers = num_buffers;
1540                                                 LOGD("video_num_buffers : %d", player->video_num_buffers);
1541                                         }
1542
1543                                         if (gst_structure_get_int(gst_message_get_structure(msg), "extra_num_buffers", &extra_num_buffers)) {
1544                                                 player->video_extra_num_buffers = extra_num_buffers;
1545                                                 LOGD("num_of_vout_extra num buffers : %d", extra_num_buffers);
1546                                         }
1547                                         break;
1548                                 }
1549
1550                                 if (!strcmp(structure_name, "Language_list")) {
1551                                         const GValue *lang_list = NULL;
1552                                         lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
1553                                         if (lang_list != NULL) {
1554                                                 count = g_list_length((GList *)g_value_get_pointer(lang_list));
1555                                                 if (count > 1)
1556                                                         LOGD("Total audio tracks(from parser) = %d \n", count);
1557                                         }
1558                                 }
1559
1560                                 if (!strcmp(structure_name, "Ext_Sub_Language_List")) {
1561                                         const GValue *lang_list = NULL;
1562                                         MMPlayerLangStruct *temp = NULL;
1563
1564                                         lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
1565                                         if (lang_list != NULL) {
1566                                                 count = g_list_length((GList *)g_value_get_pointer(lang_list));
1567                                                 if (count) {
1568                                                         MMPLAYER_SUBTITLE_INFO_LOCK(player);
1569                                                         player->subtitle_language_list = (GList *)g_value_get_pointer(lang_list);
1570                                                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
1571                                                         if (mmf_attrs_commit(attrs))
1572                                                                 LOGE("failed to commit.\n");
1573                                                         LOGD("Total subtitle tracks = %d \n", count);
1574
1575                                                         while (count) {
1576                                                                 temp = g_list_nth_data(player->subtitle_language_list, count - 1);
1577                                                                 if (temp)
1578                                                                         LOGD("value of lang_key is %s and lang_code is %s",
1579                                                                                                 temp->language_key, temp->language_code);
1580                                                                 count--;
1581                                                         }
1582                                                         MMPLAYER_SUBTITLE_INFO_SIGNAL(player);
1583                                                         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
1584                                                 }
1585                                         }
1586                                 }
1587
1588                                 /* custom message */
1589                                 if (!strcmp(structure_name, "audio_codec_not_supported")) {
1590                                         MMMessageParamType msg_param = {0,};
1591                                         msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
1592                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
1593                                 }
1594
1595                                 /* custom message for RTSP attribute :
1596                                     RTSP case, buffer is not come from server before PLAYING state. However,we have to get attribute after PAUSE state chaged.
1597                                     sdp which has contents info is received when rtsp connection is opened.
1598                                     extract duration ,codec info , resolution from sdp and get it by GstMessage */
1599                                 if (!strcmp(structure_name, "rtspsrc_properties")) {
1600
1601                                         gchar *audio_codec = NULL;
1602                                         gchar *video_codec = NULL;
1603                                         gchar *video_frame_size = NULL;
1604
1605                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_duration", G_TYPE_UINT64, &player->duration, NULL);
1606                                         LOGD("rtsp duration : %"G_GINT64_FORMAT" msec", GST_TIME_AS_MSECONDS(player->duration));
1607                                         player->streaming_type = __mmplayer_get_stream_service_type(player);
1608
1609                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_audio_codec", G_TYPE_STRING, &audio_codec, NULL);
1610                                         LOGD("rtsp_audio_codec : %s", audio_codec);
1611                                         if (audio_codec)
1612                                                 mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1613
1614                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_video_codec", G_TYPE_STRING, &video_codec, NULL);
1615                                         LOGD("rtsp_video_codec : %s", video_codec);
1616                                         if (video_codec)
1617                                                 mm_attrs_set_string_by_name(player->attrs, "content_video_codec", video_codec);
1618
1619                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_video_frame_size", G_TYPE_STRING, &video_frame_size, NULL);
1620                                         LOGD("rtsp_video_frame_size : %s", video_frame_size);
1621                                         if (video_frame_size) {
1622
1623                                                 char *seperator = strchr(video_frame_size, '-');
1624                                                 if (seperator) {
1625
1626                                                         char video_width[10] = {0,};
1627                                                         int frame_size_len = strlen(video_frame_size);
1628                                                         int separtor_len = strlen(seperator);
1629
1630                                                         strncpy(video_width, video_frame_size, (frame_size_len - separtor_len));
1631                                                         mm_attrs_set_int_by_name(attrs, "content_video_width", atoi(video_width));
1632
1633                                                         seperator++;
1634                                                         mm_attrs_set_int_by_name(attrs, "content_video_height", atoi(seperator));
1635                                                 }
1636                                         }
1637
1638                                         if (mmf_attrs_commit(attrs))
1639                                                 LOGE("failed to commit.\n");
1640                                 }
1641                         }
1642                         break;
1643
1644         case GST_MESSAGE_DURATION_CHANGED:
1645                 {
1646                         LOGD("GST_MESSAGE_DURATION_CHANGED\n");
1647                         if (!__mmplayer_gst_handle_duration(player, msg))
1648                                 LOGW("failed to update duration");
1649                 }
1650
1651                 break;
1652
1653         case GST_MESSAGE_ASYNC_START:
1654                         LOGD("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1655                 break;
1656
1657         case GST_MESSAGE_ASYNC_DONE:
1658                 {
1659                         LOGD("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1660
1661                         /* we only handle messages from pipeline */
1662                         if (msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst)
1663                                 break;
1664
1665                         if (player->doing_seek) {
1666                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
1667                                         player->doing_seek = FALSE;
1668                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1669                                 } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
1670                                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1671                                                 (player->streamer) &&
1672                                                 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
1673                                                 (player->streamer->is_buffering == FALSE)) {
1674                                                 GstQuery *query = NULL;
1675                                                 gboolean busy = FALSE;
1676                                                 gint percent = 0;
1677
1678                                                 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer) {
1679                                                         query = gst_query_new_buffering(GST_FORMAT_PERCENT);
1680                                                         if (gst_element_query(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query))
1681                                                                 gst_query_parse_buffering_percent(query, &busy, &percent);
1682                                                         gst_query_unref(query);
1683
1684                                                         LOGD("buffered percent(%s): %d\n",
1685                                                                 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
1686                                                 }
1687
1688                                                 if (percent >= 100) {
1689                                                         player->streamer->is_buffering = FALSE;
1690                                                         __mmplayer_handle_buffering_message(player);
1691                                                 }
1692                                         }
1693
1694                                         async_done = TRUE;
1695                                 }
1696                         }
1697                 }
1698                 break;
1699
1700         #if 0 /* delete unnecessary logs */
1701         case GST_MESSAGE_REQUEST_STATE:         LOGD("GST_MESSAGE_REQUEST_STATE\n"); break;
1702         case GST_MESSAGE_STEP_START:            LOGD("GST_MESSAGE_STEP_START\n"); break;
1703         case GST_MESSAGE_QOS:                           LOGD("GST_MESSAGE_QOS\n"); break;
1704         case GST_MESSAGE_PROGRESS:                      LOGD("GST_MESSAGE_PROGRESS\n"); break;
1705         case GST_MESSAGE_ANY:                           LOGD("GST_MESSAGE_ANY\n"); break;
1706         case GST_MESSAGE_INFO:                          LOGD("GST_MESSAGE_STATE_DIRTY\n"); break;
1707         case GST_MESSAGE_STATE_DIRTY:           LOGD("GST_MESSAGE_STATE_DIRTY\n"); break;
1708         case GST_MESSAGE_STEP_DONE:                     LOGD("GST_MESSAGE_STEP_DONE\n"); break;
1709         case GST_MESSAGE_CLOCK_PROVIDE:         LOGD("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
1710         case GST_MESSAGE_STRUCTURE_CHANGE:      LOGD("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
1711         case GST_MESSAGE_STREAM_STATUS:         LOGD("GST_MESSAGE_STREAM_STATUS\n"); break;
1712         case GST_MESSAGE_APPLICATION:           LOGD("GST_MESSAGE_APPLICATION\n"); break;
1713         case GST_MESSAGE_SEGMENT_START:         LOGD("GST_MESSAGE_SEGMENT_START\n"); break;
1714         case GST_MESSAGE_SEGMENT_DONE:          LOGD("GST_MESSAGE_SEGMENT_DONE\n"); break;
1715         case GST_MESSAGE_LATENCY:                               LOGD("GST_MESSAGE_LATENCY\n"); break;
1716         #endif
1717
1718         default:
1719                 break;
1720         }
1721
1722         /* should not call 'gst_message_unref(msg)' */
1723         return;
1724 }
1725
1726 static gboolean
1727 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
1728 {
1729         gint64 bytes = 0;
1730
1731         MMPLAYER_FENTER();
1732
1733         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
1734         MMPLAYER_RETURN_VAL_IF_FAIL(msg, FALSE);
1735
1736         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1737                 (msg->src) && (msg->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst)) {
1738                 LOGD("msg src : [%s]", GST_ELEMENT_NAME(GST_ELEMENT_CAST(msg->src)));
1739
1740                 if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes)) {
1741                         LOGD("data total size of http content: %"G_GINT64_FORMAT, bytes);
1742                         player->http_content_size = (bytes > 0) ? (bytes) : (0);
1743                 }
1744         } else
1745                 /* handling audio clip which has vbr. means duration is keep changing */
1746                 _mmplayer_update_content_attrs(player, ATTR_DURATION);
1747
1748         MMPLAYER_FLEAVE();
1749
1750         return TRUE;
1751 }
1752
1753 static void __mmplayer_get_metadata_360_from_tags(GstTagList *tags,
1754                 mm_player_spherical_metadata_t *metadata) {
1755         gst_tag_list_get_int(tags, "is_spherical", &metadata->is_spherical);
1756         gst_tag_list_get_int(tags, "is_stitched", &metadata->is_stitched);
1757         gst_tag_list_get_string(tags, "stitching_software",
1758                         &metadata->stitching_software);
1759         gst_tag_list_get_string(tags, "projection_type",
1760                         &metadata->projection_type_string);
1761         gst_tag_list_get_string(tags, "stereo_mode", &metadata->stereo_mode_string);
1762         gst_tag_list_get_int(tags, "source_count", &metadata->source_count);
1763         gst_tag_list_get_int(tags, "init_view_heading",
1764                         &metadata->init_view_heading);
1765         gst_tag_list_get_int(tags, "init_view_pitch", &metadata->init_view_pitch);
1766         gst_tag_list_get_int(tags, "init_view_roll", &metadata->init_view_roll);
1767         gst_tag_list_get_int(tags, "timestamp", &metadata->timestamp);
1768         gst_tag_list_get_int(tags, "full_pano_width_pixels",
1769                         &metadata->full_pano_width_pixels);
1770         gst_tag_list_get_int(tags, "full_pano_height_pixels",
1771                         &metadata->full_pano_height_pixels);
1772         gst_tag_list_get_int(tags, "cropped_area_image_width",
1773                         &metadata->cropped_area_image_width);
1774         gst_tag_list_get_int(tags, "cropped_area_image_height",
1775                         &metadata->cropped_area_image_height);
1776         gst_tag_list_get_int(tags, "cropped_area_left",
1777                         &metadata->cropped_area_left);
1778         gst_tag_list_get_int(tags, "cropped_area_top", &metadata->cropped_area_top);
1779         gst_tag_list_get_int(tags, "ambisonic_type", &metadata->ambisonic_type);
1780         gst_tag_list_get_int(tags, "ambisonic_format", &metadata->ambisonic_format);
1781         gst_tag_list_get_int(tags, "ambisonic_order", &metadata->ambisonic_order);
1782 }
1783
1784 static gboolean
1785 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg)
1786 {
1787
1788 /* macro for better code readability */
1789 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
1790 if (gst_tag_list_get_string(tag_list, gsttag, &string)) {\
1791         if (string != NULL) { \
1792                 SECURE_LOGD("update tag string : %s\n", string); \
1793                 if (strlen(string) > MM_MAX_STRING_LENGTH) { \
1794                         char *new_string = malloc(MM_MAX_STRING_LENGTH); \
1795                         strncpy(new_string, string, MM_MAX_STRING_LENGTH-1); \
1796                         new_string[MM_MAX_STRING_LENGTH-1] = '\0'; \
1797                         mm_attrs_set_string_by_name(attribute, playertag, new_string); \
1798                         g_free(new_string); \
1799                         new_string = NULL; \
1800                 } else { \
1801                         mm_attrs_set_string_by_name(attribute, playertag, string); \
1802                 } \
1803                 g_free(string); \
1804                 string = NULL; \
1805         } \
1806 }
1807
1808 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
1809 do {    \
1810         GstSample *sample = NULL;\
1811         if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample)) {\
1812                 GstMapInfo info = GST_MAP_INFO_INIT;\
1813                 buffer = gst_sample_get_buffer(sample);\
1814                 if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) {\
1815                         LOGD("failed to get image data from tag");\
1816                         gst_sample_unref(sample);\
1817                         return FALSE;\
1818                 } \
1819                 SECURE_LOGD("update album cover data : %p, size : %d\n", info.data, info.size);\
1820                 MMPLAYER_FREEIF(player->album_art);\
1821                 player->album_art = (gchar *)g_malloc(info.size);\
1822                 if (player->album_art) {\
1823                         memcpy(player->album_art, info.data, info.size);\
1824                         mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, info.size);\
1825                         if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {\
1826                                 msg_param.data = (void *)player->album_art;\
1827                                 msg_param.size = info.size;\
1828                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_IMAGE_BUFFER, &msg_param);\
1829                                 SECURE_LOGD("post message image buffer data : %p, size : %d\n", info.data, info.size);\
1830                         } \
1831                 } \
1832                 gst_buffer_unmap(buffer, &info);\
1833                 gst_sample_unref(sample);\
1834         }       \
1835 } while (0)
1836
1837 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
1838 do {    \
1839         if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint)) { \
1840                 if (v_uint) { \
1841                         int i = 0; \
1842                         gchar *tag_list_str = NULL; \
1843                         MMPlayerTrackType track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
1844                         if (strstr(GST_OBJECT_NAME(msg->src), "audio")) \
1845                                 track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
1846                         else if (strstr(GST_OBJECT_NAME(msg->src), "video")) \
1847                                 track_type = MM_PLAYER_TRACK_TYPE_VIDEO; \
1848                         else \
1849                                 track_type = MM_PLAYER_TRACK_TYPE_TEXT; \
1850                         if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) { \
1851                                 if (track_type == MM_PLAYER_TRACK_TYPE_AUDIO) \
1852                                         mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
1853                                 player->bitrate[track_type] = v_uint; \
1854                                 player->total_bitrate = 0; \
1855                                 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
1856                                         player->total_bitrate += player->bitrate[i]; \
1857                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate); \
1858                                 SECURE_LOGD("update bitrate %d[bps] of stream #%d.\n", v_uint, (int)track_type); \
1859                         } else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) { \
1860                                 player->maximum_bitrate[track_type] = v_uint; \
1861                                 player->total_maximum_bitrate = 0; \
1862                                 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
1863                                         player->total_maximum_bitrate += player->maximum_bitrate[i]; \
1864                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate);\
1865                                 SECURE_LOGD("update maximum bitrate %d[bps] of stream #%d\n", v_uint, (int)track_type);\
1866                         } else { \
1867                                 mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
1868                         } \
1869                         v_uint = 0;\
1870                         g_free(tag_list_str); \
1871                 } \
1872         } \
1873 } while (0)
1874
1875 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
1876 if (gst_tag_list_get_date(tag_list, gsttag, &date)) {\
1877         if (date != NULL) {\
1878                 string = g_strdup_printf("%d", g_date_get_year(date));\
1879                 mm_attrs_set_string_by_name(attribute, playertag, string);\
1880                 SECURE_LOGD("metainfo year : %s\n", string);\
1881                 MMPLAYER_FREEIF(string);\
1882                 g_date_free(date);\
1883         } \
1884 }
1885
1886 #define MMPLAYER_UPDATE_TAG_DATE_TIME(gsttag, attribute, playertag) \
1887 if (gst_tag_list_get_date_time(tag_list, gsttag, &datetime)) {\
1888         if (datetime != NULL) {\
1889                 string = g_strdup_printf("%d", gst_date_time_get_year(datetime));\
1890                 mm_attrs_set_string_by_name(attribute, playertag, string);\
1891                 SECURE_LOGD("metainfo year : %s\n", string);\
1892                 MMPLAYER_FREEIF(string);\
1893                 gst_date_time_unref(datetime);\
1894         } \
1895 }
1896
1897 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
1898 if (gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64)) {\
1899         if (v_uint64) {\
1900                 /* FIXIT : don't know how to store date */\
1901                 g_assert(1);\
1902                 v_uint64 = 0;\
1903         } \
1904 }
1905
1906 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
1907 if (gst_tag_list_get_double(tag_list, gsttag, &v_double)) {\
1908         if (v_double) {\
1909                 /* FIXIT : don't know how to store date */\
1910                 g_assert(1);\
1911                 v_double = 0;\
1912         } \
1913 }
1914
1915         /* function start */
1916         GstTagList* tag_list = NULL;
1917
1918         MMHandleType attrs = 0;
1919
1920         char *string = NULL;
1921         guint v_uint = 0;
1922         GDate *date = NULL;
1923         GstDateTime *datetime = NULL;
1924         /* album cover */
1925         GstBuffer *buffer = NULL;
1926         gint index = 0;
1927         MMMessageParamType msg_param = {0, };
1928
1929         /* currently not used. but those are needed for above macro */
1930         //guint64 v_uint64 = 0;
1931         //gdouble v_double = 0;
1932
1933         MMPLAYER_RETURN_VAL_IF_FAIL(player && msg, FALSE);
1934
1935         attrs = MMPLAYER_GET_ATTRS(player);
1936
1937         MMPLAYER_RETURN_VAL_IF_FAIL(attrs, FALSE);
1938
1939         /* get tag list from gst message */
1940         gst_message_parse_tag(msg, &tag_list);
1941
1942         /* store tags to player attributes */
1943         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
1944         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
1945         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
1946         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
1947         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
1948         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
1949         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
1950         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
1951         MMPLAYER_UPDATE_TAG_DATE_TIME(GST_TAG_DATE_TIME, attrs, "tag_date");
1952         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
1953         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
1954         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
1955         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
1956         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
1957         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
1958         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
1959         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
1960         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
1961         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
1962         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
1963         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
1964         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
1965         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
1966         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
1967         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
1968         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
1969         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
1970         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
1971         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
1972         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
1973         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
1974         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
1975         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
1976         MMPLAYER_UPDATE_TAG_LOCK(player);
1977         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
1978         MMPLAYER_UPDATE_TAG_UNLOCK(player);
1979         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
1980         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
1981         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
1982         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
1983         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
1984         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
1985         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
1986         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
1987         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
1988         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
1989         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
1990         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
1991         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, attrs, "content_video_orientation");
1992
1993         if (strstr(GST_OBJECT_NAME(msg->src), "demux")) {
1994                 if (player->video360_metadata.is_spherical == -1) {
1995                         __mmplayer_get_metadata_360_from_tags(tag_list, &player->video360_metadata);
1996                         mm_attrs_set_int_by_name(attrs, "content_video_is_spherical",
1997                                         player->video360_metadata.is_spherical);
1998                         if (player->video360_metadata.is_spherical == 1) {
1999                                 LOGD("This is spherical content for 360 playback.");
2000                                 player->is_content_spherical = TRUE;
2001                         } else {
2002                                 LOGD("This is not spherical content");
2003                                 player->is_content_spherical = FALSE;
2004                         }
2005
2006                         if (player->video360_metadata.projection_type_string) {
2007                                 if (!strcmp(player->video360_metadata.projection_type_string, "equirectangular")) {
2008                                         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
2009                                 } else {
2010                                         LOGE("Projection %s: code not implemented.\n", player->video360_metadata.projection_type_string);
2011                                         player->is_content_spherical = player->is_video360_enabled = FALSE;
2012                                 }
2013                         }
2014
2015                         if (player->video360_metadata.stereo_mode_string) {
2016                                 if (!strcmp(player->video360_metadata.stereo_mode_string, "mono")) {
2017                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
2018                                 } else if (!strcmp(player->video360_metadata.stereo_mode_string, "left-right")) {
2019                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_STEREOSCOPIC_LEFT_RIGHT;
2020                                 } else if (!strcmp(player->video360_metadata.stereo_mode_string, "top-bottom")) {
2021                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_STEREOSCOPIC_TOP_BOTTOM;
2022                                 } else {
2023                                         LOGE("Stereo mode %s: code not implemented.\n", player->video360_metadata.stereo_mode_string);
2024                                         player->is_content_spherical = player->is_video360_enabled = FALSE;
2025                                 }
2026                         }
2027                 }
2028         }
2029
2030         if (mmf_attrs_commit(attrs))
2031                 LOGE("failed to commit.\n");
2032
2033         gst_tag_list_free(tag_list);
2034
2035         return TRUE;
2036 }
2037
2038 static void
2039 __mmplayer_gst_rtp_no_more_pads(GstElement *element,  gpointer data)
2040 {
2041         mm_player_t* player = (mm_player_t*) data;
2042
2043         MMPLAYER_FENTER();
2044
2045         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2046           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2047           * num_dynamic_pad. and this is no-more-pad situation which means no more pad will be added.
2048           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2049
2050           * [1] audio and video will be dumped with filesink.
2051           * [2] autoplugging is done by just using pad caps.
2052           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
2053           * and the video will be dumped via filesink.
2054           */
2055         if (player->num_dynamic_pad == 0) {
2056                 LOGD("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
2057
2058                 if (!__mmplayer_gst_remove_fakesink(player,
2059                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]))
2060                         /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
2061                          * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
2062                          * source element are not same. To overcome this situation, this function will called
2063                          * several places and several times. Therefore, this is not an error case.
2064                          */
2065                         return;
2066         }
2067
2068         /* create dot before error-return. for debugging */
2069         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-no-more-pad");
2070
2071         player->no_more_pad = TRUE;
2072
2073         MMPLAYER_FLEAVE();
2074 }
2075
2076 static gboolean
2077 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink)
2078 {
2079         GstElement* parent = NULL;
2080
2081         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
2082
2083         /* if we have no fakesink. this meas we are using decodebin which doesn'
2084         t need to add extra fakesink */
2085         MMPLAYER_RETURN_VAL_IF_FAIL(fakesink, TRUE);
2086
2087         /* lock */
2088         MMPLAYER_FSINK_LOCK(player);
2089
2090         if (!fakesink->gst)
2091                 goto ERROR;
2092
2093         /* get parent of fakesink */
2094         parent = (GstElement*)gst_object_get_parent((GstObject*)fakesink->gst);
2095         if (!parent) {
2096                 LOGD("fakesink already removed\n");
2097                 goto ERROR;
2098         }
2099
2100         gst_element_set_locked_state(fakesink->gst, TRUE);
2101
2102         /* setting the state to NULL never returns async
2103          * so no need to wait for completion of state transiton
2104          */
2105         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(fakesink->gst, GST_STATE_NULL))
2106                 LOGE("fakesink state change failure!\n");
2107                 /* FIXIT : should I return here? or try to proceed to next? */
2108                 /* return FALSE; */
2109
2110         /* remove fakesink from it's parent */
2111         if (!gst_bin_remove(GST_BIN(parent), fakesink->gst)) {
2112                 LOGE("failed to remove fakesink\n");
2113
2114                 gst_object_unref(parent);
2115
2116                 goto ERROR;
2117         }
2118
2119         gst_object_unref(parent);
2120
2121         LOGD("state-holder removed\n");
2122
2123         gst_element_set_locked_state(fakesink->gst, FALSE);
2124
2125         MMPLAYER_FSINK_UNLOCK(player);
2126         return TRUE;
2127
2128 ERROR:
2129         if (fakesink->gst)
2130                 gst_element_set_locked_state(fakesink->gst, FALSE);
2131
2132         MMPLAYER_FSINK_UNLOCK(player);
2133         return FALSE;
2134 }
2135
2136
2137 static void
2138 __mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data)
2139 {
2140         GstPad *sinkpad = NULL;
2141         GstCaps* caps = NULL;
2142         GstElement* new_element = NULL;
2143         GstStructure* str = NULL;
2144         const gchar* name = NULL;
2145
2146         mm_player_t* player = (mm_player_t*) data;
2147
2148         MMPLAYER_FENTER();
2149
2150         MMPLAYER_RETURN_IF_FAIL(element && pad);
2151         MMPLAYER_RETURN_IF_FAIL(player &&
2152                                         player->pipeline &&
2153                                         player->pipeline->mainbin);
2154
2155
2156         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2157          * num_dynamic_pad will decreased after creating a sinkbin.
2158          */
2159         player->num_dynamic_pad++;
2160         LOGD("stream count inc : %d\n", player->num_dynamic_pad);
2161
2162         caps = gst_pad_query_caps(pad, NULL);
2163
2164         MMPLAYER_CHECK_NULL(caps);
2165
2166         /* clear  previous result*/
2167         player->have_dynamic_pad = FALSE;
2168
2169         str = gst_caps_get_structure(caps, 0);
2170
2171         if (!str) {
2172                 LOGE("cannot get structure from caps.\n");
2173                 goto ERROR;
2174         }
2175
2176         name = gst_structure_get_name(str);
2177         if (!name) {
2178                 LOGE("cannot get mimetype from structure.\n");
2179                 goto ERROR;
2180         }
2181
2182         if (strstr(name, "video")) {
2183                 gint stype = 0;
2184                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
2185
2186                 if (stype == MM_DISPLAY_SURFACE_NULL || stype == MM_DISPLAY_SURFACE_REMOTE) {
2187                         if (player->v_stream_caps) {
2188                                 gst_caps_unref(player->v_stream_caps);
2189                                 player->v_stream_caps = NULL;
2190                         }
2191
2192                         new_element = gst_element_factory_make("fakesink", NULL);
2193                         player->num_dynamic_pad--;
2194                         goto NEW_ELEMENT;
2195                 }
2196         }
2197
2198         /* clear  previous result*/
2199         player->have_dynamic_pad = FALSE;
2200
2201         if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
2202                 LOGE("failed to autoplug for caps");
2203                 goto ERROR;
2204         }
2205
2206         /* check if there's dynamic pad*/
2207         if (player->have_dynamic_pad) {
2208                 LOGE("using pad caps assums there's no dynamic pad !\n");
2209                 goto ERROR;
2210         }
2211
2212         gst_caps_unref(caps);
2213         caps = NULL;
2214
2215 NEW_ELEMENT:
2216
2217         /* excute new_element if created*/
2218         if (new_element) {
2219                 LOGD("adding new element to pipeline\n");
2220
2221                 /* set state to READY before add to bin */
2222                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_READY);
2223
2224                 /* add new element to the pipeline */
2225                 if (FALSE == gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)) {
2226                         LOGE("failed to add autoplug element to bin\n");
2227                         goto ERROR;
2228                 }
2229
2230                 /* get pad from element */
2231                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(new_element), "sink");
2232                 if (!sinkpad) {
2233                         LOGE("failed to get sinkpad from autoplug element\n");
2234                         goto ERROR;
2235                 }
2236
2237                 /* link it */
2238                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2239                         LOGE("failed to link autoplug element\n");
2240                         goto ERROR;
2241                 }
2242
2243                 gst_object_unref(sinkpad);
2244                 sinkpad = NULL;
2245
2246                 /* run. setting PLAYING here since streamming source is live source */
2247                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_PLAYING);
2248         }
2249
2250         if (caps)
2251                 gst_caps_unref(caps);
2252
2253         MMPLAYER_FLEAVE();
2254
2255         return;
2256
2257 STATE_CHANGE_FAILED:
2258 ERROR:
2259         /* FIXIT : take care if new_element has already added to pipeline */
2260         if (new_element)
2261                 gst_object_unref(GST_OBJECT(new_element));
2262
2263         if (sinkpad)
2264                 gst_object_unref(GST_OBJECT(sinkpad));
2265
2266         if (caps)
2267                 gst_caps_unref(caps);
2268
2269         /* FIXIT : how to inform this error to MSL ????? */
2270         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2271          * then post an error to application
2272          */
2273 }
2274
2275 static GstPadProbeReturn
2276 __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
2277 {
2278         LOGD("pad(%s:%s) is blocked", GST_DEBUG_PAD_NAME(pad));
2279         return GST_PAD_PROBE_OK;
2280 }
2281
2282 static GstPadProbeReturn
2283 __mmplayer_gst_selector_event_probe(GstPad * pad, GstPadProbeInfo * info, gpointer data)
2284 {
2285         GstPadProbeReturn ret = GST_PAD_PROBE_OK;
2286         GstEvent *event = GST_PAD_PROBE_INFO_DATA(info);
2287         mm_player_t* player = (mm_player_t*)data;
2288         GstCaps* caps = NULL;
2289         GstStructure* str = NULL;
2290         const gchar* name = NULL;
2291         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2292
2293
2294         if (GST_EVENT_IS_DOWNSTREAM(event)) {
2295                 if (GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START &&
2296                         GST_EVENT_TYPE(event) != GST_EVENT_FLUSH_STOP &&
2297                         GST_EVENT_TYPE(event) != GST_EVENT_SEGMENT &&
2298                         GST_EVENT_TYPE(event) != GST_EVENT_EOS)
2299                         return ret;
2300         } else if (GST_EVENT_IS_UPSTREAM(event)) {
2301                 if (GST_EVENT_TYPE(event) != GST_EVENT_QOS)
2302                         return ret;
2303         }
2304
2305         caps = gst_pad_query_caps(pad, NULL);
2306         if (!caps) {
2307                 LOGE("failed to get caps from pad[%s:%s]", GST_DEBUG_PAD_NAME(pad));
2308                 return ret;
2309         }
2310
2311         str = gst_caps_get_structure(caps, 0);
2312         if (!str) {
2313                 LOGE("failed to get structure from caps");
2314                 goto ERROR;
2315         }
2316
2317         name = gst_structure_get_name(str);
2318         if (!name) {
2319                 LOGE("failed to get name from str");
2320                 goto ERROR;
2321         }
2322
2323         if (strstr(name, "audio")) {
2324                 stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2325         } else if (strstr(name, "video")) {
2326                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2327         } else {
2328                 /* text track is not supportable */
2329                 LOGE("invalid name %s", name);
2330                 goto ERROR;
2331         }
2332
2333         switch (GST_EVENT_TYPE(event)) {
2334         case GST_EVENT_EOS:
2335                 {
2336                         /* in case of gapless, drop eos event not to send it to sink */
2337                         if (player->gapless.reconfigure && !player->msg_posted) {
2338                                 LOGD("[%d] %s:%s EOS received but will be drop", stream_type, GST_DEBUG_PAD_NAME(pad));
2339                                 ret = GST_PAD_PROBE_DROP;
2340                         }
2341                         break;
2342                 }
2343         case GST_EVENT_STREAM_START:
2344                 {
2345                         gint64 stop_running_time = 0;
2346                         gint64 position_running_time = 0;
2347                         gint64 position = 0;
2348                         gint idx = 0;
2349
2350                         for (idx = MM_PLAYER_TRACK_TYPE_AUDIO; idx < MM_PLAYER_TRACK_TYPE_TEXT; idx++) {
2351                                 if ((player->gapless.update_segment[idx] == TRUE) ||
2352                                         !(player->selector[idx].event_probe_id)) {
2353                                         /* LOGW("[%d] skip", idx); */
2354                                         continue;
2355                                 }
2356
2357                                 if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].stop)) {
2358                                         stop_running_time =
2359                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2360                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].stop);
2361                                 } else if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].duration)) {
2362                                         stop_running_time =
2363                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2364                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].duration);
2365                                 } else {
2366                                         LOGD("duration: %"GST_TIME_FORMAT, GST_TIME_ARGS(player->duration));
2367                                         stop_running_time =
2368                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2369                                                                 GST_FORMAT_TIME, player->duration);
2370                                 }
2371
2372                                 position_running_time =
2373                                         gst_segment_to_running_time(&player->gapless.segment[idx],
2374                                         GST_FORMAT_TIME, player->gapless.segment[idx].position);
2375
2376                                 LOGD("[type:%d] time info %" GST_TIME_FORMAT " , %"
2377                                         GST_TIME_FORMAT" , %" GST_TIME_FORMAT,
2378                                         idx,
2379                                         GST_TIME_ARGS(stop_running_time),
2380                                         GST_TIME_ARGS(position_running_time),
2381                                         GST_TIME_ARGS(gst_segment_to_running_time(&player->gapless.segment[idx],
2382                                         GST_FORMAT_TIME, player->gapless.segment[idx].start)));
2383
2384                                 position_running_time = MAX(position_running_time, stop_running_time);
2385                                 position_running_time -= gst_segment_to_running_time(&player->gapless.segment[idx],
2386                                                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].start);
2387                                 position_running_time = MAX(0, position_running_time);
2388                                 position = MAX(position, position_running_time);
2389                         }
2390
2391                         if (position != 0) {
2392                                 LOGD("[%d]GST_EVENT_STREAM_START: start_time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
2393                                         stream_type, GST_TIME_ARGS(player->gapless.start_time[stream_type]),
2394                                         GST_TIME_ARGS(player->gapless.start_time[stream_type] + position));
2395
2396                                 player->gapless.start_time[stream_type] += position;
2397                         }
2398                         break;
2399                 }
2400         case GST_EVENT_FLUSH_STOP:
2401                 {
2402                         LOGD("[%d] GST_EVENT_FLUSH_STOP", stream_type);
2403                         gst_segment_init(&player->gapless.segment[stream_type], GST_FORMAT_UNDEFINED);
2404                         player->gapless.start_time[stream_type] = 0;
2405                         break;
2406                 }
2407         case GST_EVENT_SEGMENT:
2408                 {
2409                         GstSegment segment;
2410                         GstEvent *tmpev;
2411
2412                         LOGD("[%d] GST_EVENT_SEGMENT", stream_type);
2413                         gst_event_copy_segment(event, &segment);
2414
2415                         if (segment.format == GST_FORMAT_TIME) {
2416                                 LOGD("segment base:%" GST_TIME_FORMAT ", offset:%" GST_TIME_FORMAT
2417                                          ", start:%" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT
2418                                          ", time: %" GST_TIME_FORMAT ", pos: %" GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT,
2419                                         GST_TIME_ARGS(segment.base), GST_TIME_ARGS(segment.offset),
2420                                         GST_TIME_ARGS(segment.start), GST_TIME_ARGS(segment.stop),
2421                                         GST_TIME_ARGS(segment.time), GST_TIME_ARGS(segment.position), GST_TIME_ARGS(segment.duration));
2422
2423                                 /* keep the all the segment ev to cover the seeking */
2424                                 gst_segment_copy_into(&segment, &player->gapless.segment[stream_type]);
2425                                 player->gapless.update_segment[stream_type] = TRUE;
2426
2427                                 if (!player->gapless.running)
2428                                         break;
2429
2430                                 player->gapless.segment[stream_type].base = player->gapless.start_time[stream_type];
2431
2432                                 LOGD("[%d] new base: %" GST_TIME_FORMAT, stream_type, GST_TIME_ARGS(player->gapless.segment[stream_type].base));
2433
2434                                 tmpev = gst_event_new_segment(&player->gapless.segment[stream_type]);
2435                                 gst_event_set_seqnum(tmpev, gst_event_get_seqnum(event));
2436                                 gst_event_unref(event);
2437                                 GST_PAD_PROBE_INFO_DATA(info) = tmpev;
2438                         }
2439                         break;
2440                 }
2441         case GST_EVENT_QOS:
2442                 {
2443                         gdouble proportion = 0.0;
2444                         GstClockTimeDiff diff = 0;
2445                         GstClockTime timestamp = 0;
2446                         gint64 running_time_diff = -1;
2447                         GstQOSType type = 0;
2448                         GstEvent *tmpev = NULL;
2449
2450                         running_time_diff = player->gapless.segment[stream_type].base;
2451
2452                         if (running_time_diff <= 0) /* don't need to adjust */
2453                                 break;
2454
2455                         gst_event_parse_qos(event, &type, &proportion, &diff, &timestamp);
2456                         gst_event_unref(event);
2457
2458                         if (timestamp < running_time_diff) {
2459                                 LOGW("QOS event from previous group");
2460                                 ret = GST_PAD_PROBE_DROP;
2461                                 break;
2462                         }
2463
2464                         LOGD("[%d] Adjusting QOS event: %" GST_TIME_FORMAT
2465                                  " - %" GST_TIME_FORMAT " = %" GST_TIME_FORMAT,
2466                                                 stream_type, GST_TIME_ARGS(timestamp),
2467                                                 GST_TIME_ARGS(running_time_diff),
2468                                                 GST_TIME_ARGS(timestamp - running_time_diff));
2469
2470                         timestamp -= running_time_diff;
2471
2472                         /* That case is invalid for QoS events */
2473                         if (diff < 0 && -diff > timestamp) {
2474                                 LOGW("QOS event from previous group");
2475                                 ret = GST_PAD_PROBE_DROP;
2476                                 break;
2477                         }
2478
2479                         tmpev = gst_event_new_qos(GST_QOS_TYPE_UNDERFLOW, proportion, diff, timestamp);
2480                         GST_PAD_PROBE_INFO_DATA(info) = tmpev;
2481
2482                         break;
2483                 }
2484         default:
2485                 break;
2486         }
2487
2488 ERROR:
2489         if (caps)
2490                 gst_caps_unref(caps);
2491         return ret;
2492 }
2493
2494 static void
2495 __mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
2496 {
2497         mm_player_t* player = NULL;
2498         GstElement* pipeline = NULL;
2499         GstElement* selector = NULL;
2500         GstElement* fakesink = NULL;
2501         GstCaps* caps = NULL;
2502         GstStructure* str = NULL;
2503         const gchar* name = NULL;
2504         GstPad* sinkpad = NULL;
2505         GstPad* srcpad = NULL;
2506         gboolean first_track = FALSE;
2507
2508         enum MainElementID elemId = MMPLAYER_M_NUM;
2509         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2510
2511         /* check handles */
2512         player = (mm_player_t*)data;
2513
2514         MMPLAYER_RETURN_IF_FAIL(elem && pad);
2515         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2516
2517         //LOGD("pad-added signal handling\n");
2518
2519         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
2520
2521         /* get mimetype from caps */
2522         caps = gst_pad_query_caps(pad, NULL);
2523         if (!caps) {
2524                 LOGE("cannot get caps from pad.\n");
2525                 goto ERROR;
2526         }
2527
2528         str = gst_caps_get_structure(caps, 0);
2529         if (!str) {
2530                 LOGE("cannot get structure from caps.\n");
2531                 goto ERROR;
2532         }
2533
2534         name = gst_structure_get_name(str);
2535         if (!name) {
2536                 LOGE("cannot get mimetype from structure.\n");
2537                 goto ERROR;
2538         }
2539
2540         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
2541         //LOGD("detected mimetype : %s\n", name);
2542
2543         if (strstr(name, "video")) {
2544                 gint stype = 0;
2545
2546                 mm_attrs_set_int_by_name(player->attrs, "content_video_found", TRUE);
2547                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
2548
2549                 /* don't make video because of not required, and not support multiple track */
2550                 if (stype == MM_DISPLAY_SURFACE_NULL) {
2551                         LOGD("no video sink by null surface");
2552
2553                         gchar *caps_str = gst_caps_to_string(caps);
2554                         if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
2555                                 strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
2556                                 player->set_mode.video_zc = TRUE;
2557
2558                         MMPLAYER_FREEIF(caps_str);
2559
2560                         if (player->v_stream_caps) {
2561                                 gst_caps_unref(player->v_stream_caps);
2562                                 player->v_stream_caps = NULL;
2563                         }
2564
2565                         LOGD("create fakesink instead of videobin");
2566
2567                         /* fake sink */
2568                         fakesink = gst_element_factory_make("fakesink", NULL);
2569                         if (fakesink == NULL) {
2570                                 LOGE("ERROR : fakesink create error\n");
2571                                 goto ERROR;
2572                         }
2573
2574                         if (player->ini.set_dump_element_flag)
2575                                 __mmplayer_add_dump_buffer_probe(player, fakesink);
2576
2577                         player->video_fakesink = fakesink;
2578
2579                         /* store it as it's sink element */
2580                         __mmplayer_add_sink(player, player->video_fakesink);
2581
2582                         gst_bin_add(GST_BIN(pipeline), fakesink);
2583
2584                         // link
2585                         sinkpad = gst_element_get_static_pad(fakesink, "sink");
2586
2587                         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2588                                 LOGW("failed to link fakesink\n");
2589                                 gst_object_unref(GST_OBJECT(fakesink));
2590                                 goto ERROR;
2591                         }
2592
2593                         if (stype == MM_DISPLAY_SURFACE_REMOTE) {
2594                                 MMPLAYER_SIGNAL_CONNECT(player, sinkpad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2595                                                 "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
2596                         }
2597
2598                         if (player->set_mode.media_packet_video_stream) {
2599                                 g_object_set(G_OBJECT(fakesink), "signal-handoffs", TRUE, NULL);
2600
2601                                 MMPLAYER_SIGNAL_CONNECT(player,
2602                                                                                 G_OBJECT(fakesink),
2603                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2604                                                                                 "handoff",
2605                                                                                 G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
2606                                                                                 (gpointer)player);
2607
2608                                 MMPLAYER_SIGNAL_CONNECT(player,
2609                                                                                 G_OBJECT(fakesink),
2610                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2611                                                                                 "preroll-handoff",
2612                                                                                 G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
2613                                                                                 (gpointer)player);
2614                         }
2615
2616                         g_object_set(G_OBJECT(fakesink), "async", TRUE, "sync", TRUE, NULL);
2617                         gst_element_set_state(fakesink, GST_STATE_PAUSED);
2618                         goto DONE;
2619                 }
2620
2621                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
2622                         __mmplayer_gst_decode_callback(elem, pad, player);
2623                         goto DONE;
2624                 }
2625
2626                 LOGD("video selector \n");
2627                 elemId = MMPLAYER_M_V_INPUT_SELECTOR;
2628                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2629         } else {
2630                 if (strstr(name, "audio")) {
2631                         gint samplerate = 0;
2632                         gint channels = 0;
2633
2634                         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
2635                                 __mmplayer_gst_decode_callback(elem, pad, player);
2636                                 goto DONE;
2637                         }
2638
2639                         LOGD("audio selector \n");
2640                         elemId = MMPLAYER_M_A_INPUT_SELECTOR;
2641                         stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2642
2643                         gst_structure_get_int(str, "rate", &samplerate);
2644                         gst_structure_get_int(str, "channels", &channels);
2645
2646                         if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
2647                                 /* fake sink */
2648                                 fakesink = gst_element_factory_make("fakesink", NULL);
2649                                 if (fakesink == NULL) {
2650                                         LOGE("ERROR : fakesink create error\n");
2651                                         goto ERROR;
2652                                 }
2653
2654                                 gst_bin_add(GST_BIN(pipeline), fakesink);
2655
2656                                 /* link */
2657                                 sinkpad = gst_element_get_static_pad(fakesink, "sink");
2658
2659                                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2660                                         LOGW("failed to link fakesink\n");
2661                                         gst_object_unref(GST_OBJECT(fakesink));
2662                                         goto ERROR;
2663                                 }
2664
2665                                 g_object_set(G_OBJECT(fakesink), "async", TRUE, NULL);
2666                                 g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL);
2667                                 gst_element_set_state(fakesink, GST_STATE_PAUSED);
2668
2669                                 goto DONE;
2670                         }
2671                 } else if (strstr(name, "text")) {
2672                         LOGD("text selector \n");
2673                         elemId = MMPLAYER_M_T_INPUT_SELECTOR;
2674                         stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
2675                 } else {
2676                         LOGE("wrong elem id \n");
2677                         goto ERROR;
2678                 }
2679         }
2680
2681         selector = player->pipeline->mainbin[elemId].gst;
2682         if (selector == NULL) {
2683                 selector = gst_element_factory_make("input-selector", NULL);
2684                 LOGD("Creating input-selector\n");
2685                 if (selector == NULL) {
2686                         LOGE("ERROR : input-selector create error\n");
2687                         goto ERROR;
2688                 }
2689                 g_object_set(selector, "sync-streams", TRUE, NULL);
2690
2691                 player->pipeline->mainbin[elemId].id = elemId;
2692                 player->pipeline->mainbin[elemId].gst = selector;
2693
2694                 first_track = TRUE;
2695                 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK;      // default
2696
2697                 srcpad = gst_element_get_static_pad(selector, "src");
2698
2699                 LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
2700                 player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
2701                         __mmplayer_gst_selector_blocked, NULL, NULL);
2702                 player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
2703                         __mmplayer_gst_selector_event_probe, player, NULL);
2704
2705                 gst_element_set_state(selector, GST_STATE_PAUSED);
2706                 gst_bin_add(GST_BIN(pipeline), selector);
2707         } else
2708                 LOGD("input-selector is already created.\n");
2709
2710         // link
2711         LOGD("Calling request pad with selector %p \n", selector);
2712         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
2713
2714         LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(sinkpad));
2715
2716         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2717                 LOGW("failed to link selector\n");
2718                 gst_object_unref(GST_OBJECT(selector));
2719                 goto ERROR;
2720         }
2721
2722         if (first_track) {
2723                 LOGD("this is first track --> active track \n");
2724                 g_object_set(selector, "active-pad", sinkpad, NULL);
2725         }
2726
2727         _mmplayer_track_update_info(player, stream_type, sinkpad);
2728
2729
2730 DONE:
2731 ERROR:
2732
2733         if (caps)
2734                 gst_caps_unref(caps);
2735
2736         if (sinkpad) {
2737                 gst_object_unref(GST_OBJECT(sinkpad));
2738                 sinkpad = NULL;
2739         }
2740
2741         if (srcpad) {
2742                 gst_object_unref(GST_OBJECT(srcpad));
2743                 srcpad = NULL;
2744         }
2745
2746         return;
2747 }
2748
2749 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
2750 {
2751         GstPad* srcpad = NULL;
2752         MMHandleType attrs = 0;
2753         gint active_index = 0;
2754
2755         // [link] input-selector :: textbin
2756         srcpad = gst_element_get_static_pad(text_selector, "src");
2757         if (!srcpad) {
2758                 LOGE("failed to get srcpad from selector\n");
2759                 return;
2760         }
2761
2762         LOGD("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
2763
2764         active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
2765         if ((active_index != DEFAULT_TRACK) &&
2766                 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE)) {
2767                 LOGW("failed to change text track\n");
2768                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
2769         }
2770
2771         player->no_more_pad = TRUE;
2772         __mmplayer_gst_decode_callback(text_selector, srcpad, player);
2773
2774         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
2775         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id) {
2776                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id);
2777                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id = 0;
2778         }
2779
2780         LOGD("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
2781
2782         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
2783                 player->has_closed_caption = TRUE;
2784
2785         attrs = MMPLAYER_GET_ATTRS(player);
2786         if (attrs) {
2787                 mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
2788                 if (mmf_attrs_commit(attrs))
2789                         LOGE("failed to commit.\n");
2790         } else
2791                 LOGE("cannot get content attribute");
2792
2793         if (srcpad) {
2794                 gst_object_unref(GST_OBJECT(srcpad));
2795                 srcpad = NULL;
2796         }
2797 }
2798
2799 static void
2800 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
2801 {
2802         mm_player_t* player = (mm_player_t*)data;
2803         GstElement* selector = NULL;
2804         GstElement* queue = NULL;
2805
2806         GstPad* srcpad = NULL;
2807         GstPad* sinkpad = NULL;
2808         GstCaps* caps = NULL;
2809         gchar* caps_str = NULL;
2810
2811         MMPLAYER_FENTER();
2812         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2813
2814         caps = gst_pad_get_current_caps(pad);
2815         caps_str = gst_caps_to_string(caps);
2816         LOGD("deinterleave new caps : %s\n", caps_str);
2817         MMPLAYER_FREEIF(caps_str);
2818         gst_caps_unref(caps);
2819
2820         if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL) {
2821                 LOGE("ERROR : queue create error\n");
2822                 goto ERROR;
2823         }
2824
2825         g_object_set(G_OBJECT(queue),
2826                                 "max-size-buffers", 10,
2827                                 "max-size-bytes", 0,
2828                                 "max-size-time", (guint64)0,
2829                                 NULL);
2830
2831         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
2832
2833         if (!selector) {
2834                 LOGE("there is no audio channel selector.\n");
2835                 goto ERROR;
2836         }
2837
2838         srcpad = gst_element_get_static_pad(queue, "src");
2839         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
2840
2841         LOGD("link(%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
2842
2843         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
2844                 LOGW("failed to link deinterleave - selector\n");
2845                 goto ERROR;
2846         }
2847
2848         gst_element_set_state(queue, GST_STATE_PAUSED);
2849         player->audio_mode.total_track_num++;
2850
2851 ERROR:
2852
2853         if (srcpad) {
2854                 gst_object_unref(GST_OBJECT(srcpad));
2855                 srcpad = NULL;
2856         }
2857
2858         if (sinkpad) {
2859                 gst_object_unref(GST_OBJECT(sinkpad));
2860                 sinkpad = NULL;
2861         }
2862
2863         MMPLAYER_FLEAVE();
2864         return;
2865 }
2866
2867 static void
2868 __mmplayer_gst_deinterleave_no_more_pads(GstElement *elem, gpointer data)
2869 {
2870         mm_player_t* player = NULL;
2871         GstElement* selector = NULL;
2872         GstPad* sinkpad = NULL;
2873         gint active_index = 0;
2874         gchar* change_pad_name = NULL;
2875         GstCaps* caps = NULL;   // no need to unref
2876         gint default_audio_ch = 0;
2877
2878         MMPLAYER_FENTER();
2879         player = (mm_player_t*) data;
2880
2881         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
2882
2883         if (!selector) {
2884                 LOGE("there is no audio channel selector.\n");
2885                 goto ERROR;
2886         }
2887
2888         active_index = player->audio_mode.active_pad_index;
2889
2890         if (active_index != default_audio_ch) {
2891                 gint audio_ch = default_audio_ch;
2892
2893                 /*To get the new pad from the selector*/
2894                 change_pad_name = g_strdup_printf("sink%d", active_index);
2895                 if (change_pad_name != NULL) {
2896                         sinkpad = gst_element_get_static_pad(selector, change_pad_name);
2897                         if (sinkpad != NULL) {
2898                                 LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
2899                                 g_object_set(selector, "active-pad", sinkpad, NULL);
2900
2901                                 audio_ch = active_index;
2902
2903                                 caps = gst_pad_get_current_caps(sinkpad);
2904                                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
2905
2906                                 __mmplayer_set_audio_attrs(player, caps);
2907                                 gst_caps_unref(caps);
2908                         }
2909                         MMPLAYER_FREEIF(change_pad_name);
2910                 }
2911
2912                 player->audio_mode.active_pad_index = audio_ch;
2913                 LOGD("audio LR info(0:stereo) = %d\n", player->audio_mode.active_pad_index);
2914         }
2915
2916 ERROR:
2917
2918         if (sinkpad)
2919                 gst_object_unref(sinkpad);
2920
2921         MMPLAYER_FLEAVE();
2922         return;
2923 }
2924
2925 static void
2926 __mmplayer_gst_build_deinterleave_path(GstElement *elem, GstPad *pad, gpointer data)
2927 {
2928         mm_player_t* player = NULL;
2929         MMPlayerGstElement *mainbin = NULL;
2930
2931         GstElement* tee = NULL;
2932         GstElement* stereo_queue = NULL;
2933         GstElement* mono_queue = NULL;
2934         GstElement* conv = NULL;
2935         GstElement* filter = NULL;
2936         GstElement* deinterleave = NULL;
2937         GstElement* selector = NULL;
2938
2939         GstPad* srcpad = NULL;
2940         GstPad* selector_srcpad = NULL;
2941         GstPad* sinkpad = NULL;
2942         GstCaps* caps = NULL;
2943         gulong block_id = 0;
2944
2945         MMPLAYER_FENTER();
2946
2947         /* check handles */
2948         player = (mm_player_t*) data;
2949
2950         MMPLAYER_RETURN_IF_FAIL(elem && pad);
2951         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2952
2953         mainbin = player->pipeline->mainbin;
2954
2955         /* tee */
2956         if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL) {
2957                 LOGE("ERROR : tee create error\n");
2958                 goto ERROR;
2959         }
2960
2961         mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
2962         mainbin[MMPLAYER_M_A_TEE].gst = tee;
2963
2964         gst_element_set_state(tee, GST_STATE_PAUSED);
2965
2966         /* queue */
2967         srcpad = gst_element_get_request_pad(tee, "src_%u");
2968         if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL) {
2969                 LOGE("ERROR : stereo queue create error\n");
2970                 goto ERROR;
2971         }
2972
2973         g_object_set(G_OBJECT(stereo_queue),
2974                                 "max-size-buffers", 10,
2975                                 "max-size-bytes", 0,
2976                                 "max-size-time", (guint64)0,
2977                                 NULL);
2978
2979         player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
2980         player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
2981
2982         if (srcpad) {
2983                 gst_object_unref(GST_OBJECT(srcpad));
2984                 srcpad = NULL;
2985         }
2986
2987         srcpad = gst_element_get_request_pad(tee, "src_%u");
2988
2989         if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL) {
2990                 LOGE("ERROR : mono queue create error\n");
2991                 goto ERROR;
2992         }
2993
2994         g_object_set(G_OBJECT(mono_queue),
2995                                 "max-size-buffers", 10,
2996                                 "max-size-bytes", 0,
2997                                 "max-size-time", (guint64)0,
2998                                 NULL);
2999
3000         player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3001         player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3002
3003         gst_element_set_state(stereo_queue, GST_STATE_PAUSED);
3004         gst_element_set_state(mono_queue, GST_STATE_PAUSED);
3005
3006         /* audioconvert */
3007         srcpad = gst_element_get_static_pad(mono_queue, "src");
3008         if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL) {
3009                 LOGE("ERROR : audioconvert create error\n");
3010                 goto ERROR;
3011         }
3012
3013         player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3014         player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3015
3016         /* caps filter */
3017         if (srcpad) {
3018                 gst_object_unref(GST_OBJECT(srcpad));
3019                 srcpad = NULL;
3020         }
3021         srcpad = gst_element_get_static_pad(conv, "src");
3022
3023         if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL) {
3024                 LOGE("ERROR : capsfilter create error\n");
3025                 goto ERROR;
3026         }
3027
3028         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3029         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3030
3031         caps = gst_caps_from_string("audio/x-raw-int, "
3032                                 "width = (int) 16, "
3033                                 "depth = (int) 16, "
3034                                 "channels = (int) 2");
3035
3036         g_object_set(GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL);
3037         gst_caps_unref(caps);
3038
3039         gst_element_set_state(conv, GST_STATE_PAUSED);
3040         gst_element_set_state(filter, GST_STATE_PAUSED);
3041
3042         /* deinterleave */
3043         if (srcpad) {
3044                 gst_object_unref(GST_OBJECT(srcpad));
3045                 srcpad = NULL;
3046         }
3047         srcpad = gst_element_get_static_pad(filter, "src");
3048
3049         if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL) {
3050                 LOGE("ERROR : deinterleave create error\n");
3051                 goto ERROR;
3052         }
3053
3054         g_object_set(deinterleave, "keep-positions", TRUE, NULL);
3055
3056         MMPLAYER_SIGNAL_CONNECT(player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3057                                                         G_CALLBACK(__mmplayer_gst_deinterleave_pad_added), player);
3058
3059         MMPLAYER_SIGNAL_CONNECT(player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3060                                                         G_CALLBACK(__mmplayer_gst_deinterleave_no_more_pads), player);
3061
3062         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3063         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3064
3065         /* selector */
3066         selector = gst_element_factory_make("input-selector", "audio-channel-selector");
3067         if (selector == NULL) {
3068                 LOGE("ERROR : audio-selector create error\n");
3069                 goto ERROR;
3070         }
3071
3072         g_object_set(selector, "sync-streams", TRUE, NULL);
3073         gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3074
3075         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3076         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3077
3078         selector_srcpad = gst_element_get_static_pad(selector, "src");
3079
3080         LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3081         block_id =
3082                 gst_pad_add_probe(selector_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3083                         __mmplayer_gst_selector_blocked, NULL, NULL);
3084
3085         if (srcpad) {
3086                 gst_object_unref(GST_OBJECT(srcpad));
3087                 srcpad = NULL;
3088         }
3089
3090         srcpad = gst_element_get_static_pad(stereo_queue, "src");
3091         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
3092
3093         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
3094                 LOGW("failed to link queue_stereo - selector\n");
3095                 goto ERROR;
3096         }
3097
3098         player->audio_mode.total_track_num++;
3099
3100         g_object_set(selector, "active-pad", sinkpad, NULL);
3101         gst_element_set_state(deinterleave, GST_STATE_PAUSED);
3102         gst_element_set_state(selector, GST_STATE_PAUSED);
3103
3104         __mmplayer_gst_decode_callback(selector, selector_srcpad, player);
3105
3106 ERROR:
3107
3108         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3109         if (block_id != 0) {
3110                 gst_pad_remove_probe(selector_srcpad, block_id);
3111                 block_id = 0;
3112         }
3113
3114         if (sinkpad) {
3115                 gst_object_unref(GST_OBJECT(sinkpad));
3116                 sinkpad = NULL;
3117         }
3118
3119         if (srcpad) {
3120                 gst_object_unref(GST_OBJECT(srcpad));
3121                 srcpad = NULL;
3122         }
3123
3124         if (selector_srcpad) {
3125                 gst_object_unref(GST_OBJECT(selector_srcpad));
3126                 selector_srcpad = NULL;
3127         }
3128
3129         MMPLAYER_FLEAVE();
3130         return;
3131 }
3132
3133 static void
3134 __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
3135 {
3136         mm_player_t* player = NULL;
3137         GstPad* srcpad = NULL;
3138         GstElement* video_selector = NULL;
3139         GstElement* audio_selector = NULL;
3140         GstElement* text_selector = NULL;
3141         MMHandleType attrs = 0;
3142         gint active_index = 0;
3143         gint64 dur_bytes = 0L;
3144
3145         player = (mm_player_t*) data;
3146
3147         LOGD("no-more-pad signal handling\n");
3148
3149         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3150                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE)) {
3151                 LOGW("no need to go more");
3152
3153                 if (player->gapless.reconfigure) {
3154                         player->gapless.reconfigure = FALSE;
3155                         MMPLAYER_PLAYBACK_UNLOCK(player);
3156                 }
3157
3158                 return;
3159         }
3160
3161         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3162                 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3163                 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3164                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
3165                 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
3166
3167                 if (NULL == player->streamer) {
3168                         LOGW("invalid state for buffering");
3169                         goto ERROR;
3170                 }
3171
3172                 gint init_buffering_time = player->streamer->buffering_req.prebuffer_time;
3173                 guint buffer_bytes = (guint)(init_buffering_time/1000) * ESTIMATED_BUFFER_UNIT;
3174
3175                 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
3176                 LOGD("[Decodebin2] set use-buffering on Q2(pre buffer time: %d ms, buffer size : %d)\n", init_buffering_time, buffer_bytes);
3177
3178                 init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
3179
3180                 if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
3181                         LOGE("fail to get duration.\n");
3182
3183                 // enable use-buffering on queue2 instead of multiqueue(ex)audio only streaming
3184                 // use file information was already set on Q2 when it was created.
3185                 __mm_player_streaming_set_queue2(player->streamer,
3186                                                 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
3187                                                 TRUE,                                                           // use_buffering
3188                                                 buffer_bytes,
3189                                                 init_buffering_time,
3190                                                 1.0,                                                            // low percent
3191                                                 player->ini.http_buffering_limit,       // high percent
3192                                                 MUXED_BUFFER_TYPE_MEM_QUEUE,
3193                                                 NULL,
3194                                                 ((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
3195         }
3196
3197         video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
3198         audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
3199         text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3200         if (video_selector) {
3201                 // [link] input-selector :: videobin
3202                 srcpad = gst_element_get_static_pad(video_selector, "src");
3203                 if (!srcpad) {
3204                         LOGE("failed to get srcpad from video selector\n");
3205                         goto ERROR;
3206                 }
3207
3208                 LOGD("got pad %s:%s from video selector\n", GST_DEBUG_PAD_NAME(srcpad));
3209                 if (!text_selector && !audio_selector)
3210                         player->no_more_pad = TRUE;
3211
3212                 __mmplayer_gst_decode_callback(video_selector, srcpad, player);
3213
3214                 LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3215                 if (player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id) {
3216                         gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id);
3217                         player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id = 0;
3218                 }
3219         }
3220
3221         if (audio_selector) {
3222                 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
3223                 if ((active_index != DEFAULT_TRACK) &&
3224                         (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE)) {
3225                         LOGW("failed to change audio track\n");
3226                         player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
3227                 }
3228
3229                 // [link] input-selector :: audiobin
3230                 srcpad = gst_element_get_static_pad(audio_selector, "src");
3231                 if (!srcpad) {
3232                         LOGE("failed to get srcpad from selector\n");
3233                         goto ERROR;
3234                 }
3235
3236                 LOGD("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3237                 if (!text_selector)
3238                         player->no_more_pad = TRUE;
3239
3240                 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2)) {
3241                         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3242                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id) {
3243                                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3244                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3245                         }
3246
3247                         __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
3248                 } else {
3249                         __mmplayer_gst_decode_callback(audio_selector, srcpad, player);
3250
3251                         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3252                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id) {
3253                                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3254                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3255                         }
3256                 }
3257
3258                 LOGD("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3259
3260                 attrs = MMPLAYER_GET_ATTRS(player);
3261                 if (attrs) {
3262                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", (gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3263                         if (mmf_attrs_commit(attrs))
3264                                 LOGE("failed to commit.\n");
3265                 } else
3266                         LOGE("cannot get content attribute");
3267         } else {
3268                 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst)) {
3269                         LOGD("There is no audio track : remove audiobin");
3270
3271                         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
3272                         __mmplayer_del_sink(player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
3273
3274                         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->audiobin, MMPLAYER_A_BIN);
3275                         MMPLAYER_FREEIF(player->pipeline->audiobin);
3276                 }
3277
3278                 if (player->num_dynamic_pad == 0)
3279                         __mmplayer_pipeline_complete(NULL, player);
3280         }
3281
3282         if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
3283                 if (text_selector)
3284                         __mmplayer_handle_text_decode_path(player, text_selector);
3285         }
3286
3287         MMPLAYER_FLEAVE();
3288
3289 ERROR:
3290         if (srcpad) {
3291                 gst_object_unref(GST_OBJECT(srcpad));
3292                 srcpad = NULL;
3293         }
3294
3295         if (player->gapless.reconfigure) {
3296                 player->gapless.reconfigure = FALSE;
3297                 MMPLAYER_PLAYBACK_UNLOCK(player);
3298         }
3299 }
3300
3301 static void
3302 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data)
3303 {
3304         mm_player_t* player = NULL;
3305         MMHandleType attrs = 0;
3306         GstElement* pipeline = NULL;
3307         GstCaps* caps = NULL;
3308         gchar* caps_str = NULL;
3309         GstStructure* str = NULL;
3310         const gchar* name = NULL;
3311         GstPad* sinkpad = NULL;
3312         GstElement* sinkbin = NULL;
3313         gboolean reusing = FALSE;
3314         GstElement *text_selector = NULL;
3315
3316         /* check handles */
3317         player = (mm_player_t*) data;
3318
3319         MMPLAYER_RETURN_IF_FAIL(elem && pad);
3320         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
3321
3322         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3323
3324         attrs = MMPLAYER_GET_ATTRS(player);
3325         if (!attrs) {
3326                 LOGE("cannot get content attribute\n");
3327                 goto ERROR;
3328         }
3329
3330         /* get mimetype from caps */
3331         caps = gst_pad_query_caps(pad, NULL);
3332         if (!caps) {
3333                 LOGE("cannot get caps from pad.\n");
3334                 goto ERROR;
3335         }
3336         caps_str = gst_caps_to_string(caps);
3337
3338         str = gst_caps_get_structure(caps, 0);
3339         if (!str) {
3340                 LOGE("cannot get structure from caps.\n");
3341                 goto ERROR;
3342         }
3343
3344         name = gst_structure_get_name(str);
3345         if (!name) {
3346                 LOGE("cannot get mimetype from structure.\n");
3347                 goto ERROR;
3348         }
3349
3350         //LOGD("detected mimetype : %s\n", name);
3351
3352         if (strstr(name, "audio")) {
3353                 if (player->pipeline->audiobin == NULL) {
3354                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player)) {
3355                                 LOGE("failed to create audiobin. continuing without audio\n");
3356                                 goto ERROR;
3357                         }
3358
3359                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3360                         LOGD("creating audiosink bin success\n");
3361                 } else {
3362                         reusing = TRUE;
3363                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3364                         LOGD("reusing audiobin\n");
3365                         _mmplayer_update_content_attrs(player, ATTR_AUDIO);
3366                 }
3367
3368                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
3369                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
3370
3371                 player->audiosink_linked  = 1;
3372
3373                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
3374                 if (!sinkpad) {
3375                         LOGE("failed to get pad from sinkbin\n");
3376                         goto ERROR;
3377                 }
3378         } else if (strstr(name, "video")) {
3379                 if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
3380                         strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
3381                         player->set_mode.video_zc = TRUE;
3382
3383                 if (player->pipeline->videobin == NULL) {
3384                         /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
3385                         /* get video surface type */
3386                         int surface_type = 0;
3387                         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
3388                         LOGD("display_surface_type(%d)\n", surface_type);
3389
3390                         if (surface_type == MM_DISPLAY_SURFACE_NULL) {
3391                                 LOGD("not make videobin because it dose not want\n");
3392                                 goto ERROR;
3393                         }
3394
3395                         if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
3396                                 /* mark video overlay for acquire */
3397                                 if (player->video_overlay_resource == NULL) {
3398                                         if (mm_resource_manager_mark_for_acquire(player->resource_manager,
3399                                                         MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
3400                                                         MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
3401                                                         &player->video_overlay_resource)
3402                                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
3403                                                 LOGE("could not mark video_overlay resource for acquire\n");
3404                                                 goto ERROR;
3405                                         }
3406                                 }
3407                         }
3408
3409                         player->interrupted_by_resource = FALSE;
3410                         /* acquire resources for video overlay */
3411                         if (mm_resource_manager_commit(player->resource_manager) !=
3412                                         MM_RESOURCE_MANAGER_ERROR_NONE) {
3413                                 LOGE("could not acquire resources for video playing\n");
3414                                 goto ERROR;
3415                         }
3416
3417                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type)) {
3418                                 LOGE("failed to create videobin. continuing without video\n");
3419                                 goto ERROR;
3420                         }
3421
3422                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3423                         LOGD("creating videosink bin success\n");
3424                 } else {
3425                         reusing = TRUE;
3426                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3427                         LOGD("re-using videobin\n");
3428                         _mmplayer_update_content_attrs(player, ATTR_VIDEO);
3429                 }
3430
3431                 player->videosink_linked  = 1;
3432
3433                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
3434                 if (!sinkpad) {
3435                         LOGE("failed to get pad from sinkbin\n");
3436                         goto ERROR;
3437                 }
3438         } else if (strstr(name, "text")) {
3439                 if (player->pipeline->textbin == NULL) {
3440                         MMPlayerGstElement* mainbin = NULL;
3441
3442                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_sink_bin(player)) {
3443                                 LOGE("failed to create text sink bin. continuing without text\n");
3444                                 goto ERROR;
3445                         }
3446
3447                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3448                         LOGD("creating textsink bin success\n");
3449
3450                         /* FIXIT : track number shouldn't be hardcoded */
3451                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
3452
3453                         player->textsink_linked  = 1;
3454                         LOGI("player->textsink_linked set to 1\n");
3455
3456                         sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "text_sink");
3457                         if (!sinkpad) {
3458                                 LOGE("failed to get pad from sinkbin\n");
3459                                 goto ERROR;
3460                         }
3461
3462                         mainbin = player->pipeline->mainbin;
3463
3464                         if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst) {
3465                                 /* input selector */
3466                                 text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
3467                                 if (!text_selector) {
3468                                         LOGE("failed to create subtitle input selector element\n");
3469                                         goto ERROR;
3470                                 }
3471                                 g_object_set(text_selector, "sync-streams", TRUE, NULL);
3472
3473                                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
3474                                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
3475
3476                                 /* warm up */
3477                                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_READY)) {
3478                                         LOGE("failed to set state(READY) to sinkbin\n");
3479                                         goto ERROR;
3480                                 }
3481
3482                                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector)) {
3483                                         LOGW("failed to add subtitle input selector\n");
3484                                         goto ERROR;
3485                                 }
3486
3487                                 LOGD("created element input-selector");
3488
3489                         } else {
3490                                 LOGD("already having subtitle input selector");
3491                                 text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3492                         }
3493                 } else {
3494                         if (!player->textsink_linked) {
3495                                 LOGD("re-using textbin\n");
3496
3497                                 reusing = TRUE;
3498                                 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3499
3500                                 player->textsink_linked  = 1;
3501                                 LOGI("player->textsink_linked set to 1\n");
3502                         } else
3503                                 LOGD("ignoring internal subtutle since external subtitle is available");
3504                 }
3505         } else {
3506                 LOGW("unknown type of elementary stream!ignoring it...\n");
3507                 goto ERROR;
3508         }
3509
3510         if (sinkbin) {
3511                 if (!reusing) {
3512                         /* warm up */
3513                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_READY)) {
3514                                 LOGE("failed to set state(READY) to sinkbin\n");
3515                                 goto ERROR;
3516                         }
3517
3518                         /* Added for multi audio support to avoid adding audio bin again*/
3519                         /* add */
3520                         if (FALSE == gst_bin_add(GST_BIN(pipeline), sinkbin)) {
3521                                 LOGE("failed to add sinkbin to pipeline\n");
3522                                 goto ERROR;
3523                         }
3524                 }
3525
3526                 /* link */
3527                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
3528                         LOGE("failed to get pad from sinkbin\n");
3529                         goto ERROR;
3530                 }
3531
3532                 if (!reusing) {
3533                         /* run */
3534                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_PAUSED)) {
3535                                 LOGE("failed to set state(PAUSED) to sinkbin\n");
3536                                 goto ERROR;
3537                         }
3538
3539                         if (text_selector) {
3540                                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_PAUSED)) {
3541                                         LOGE("failed to set state(PAUSED) to sinkbin\n");
3542                                         goto ERROR;
3543                                 }
3544                         }
3545                 }
3546
3547                 gst_object_unref(sinkpad);
3548                 sinkpad = NULL;
3549         }
3550
3551         LOGD("[handle: %p] linking sink bin success", player);
3552
3553         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
3554          * streaming task. if the task blocked, then buffer will not flow to the next element
3555          *(autoplugging element). so this is special hack for streaming. please try to remove it
3556          */
3557         /* dec stream count. we can remove fakesink if it's zero */
3558         if (player->num_dynamic_pad)
3559                 player->num_dynamic_pad--;
3560
3561         LOGD("no more pads: %d stream count dec : %d(num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
3562
3563         if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
3564                 __mmplayer_pipeline_complete(NULL, player);
3565
3566 ERROR:
3567
3568         MMPLAYER_FREEIF(caps_str);
3569
3570         if (caps)
3571                 gst_caps_unref(caps);
3572
3573         if (sinkpad)
3574                 gst_object_unref(GST_OBJECT(sinkpad));
3575
3576         /* flusing out new attributes */
3577         if (mmf_attrs_commit(attrs))
3578                 LOGE("failed to comit attributes\n");
3579
3580         return;
3581 }
3582
3583 static gboolean
3584 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
3585 {
3586         int pro_value = 0; // in the case of expection, default will be returned.
3587         int dest_angle = rotation_angle;
3588         int rotation_type = -1;
3589
3590         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
3591         MMPLAYER_RETURN_VAL_IF_FAIL(value, FALSE);
3592         MMPLAYER_RETURN_VAL_IF_FAIL(rotation_angle >= 0, FALSE);
3593
3594         if (rotation_angle >= 360)
3595                 dest_angle = rotation_angle - 360;
3596
3597         /* chech if supported or not */
3598         if (dest_angle % 90) {
3599                 LOGD("not supported rotation angle = %d", rotation_angle);
3600                 return FALSE;
3601         }
3602
3603         /*
3604           * tizenwlsink (A)
3605           * custom_convert - none (B)
3606           * videoflip - none (C)
3607           */
3608         if (player->set_mode.video_zc) {
3609                 if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
3610                         rotation_type = ROTATION_USING_CUSTOM;
3611                 else // A
3612                         rotation_type = ROTATION_USING_SINK;
3613         } else {
3614                 int surface_type = 0;
3615                 rotation_type = ROTATION_USING_FLIP;
3616
3617                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
3618                 LOGD("check display surface type attribute: %d", surface_type);
3619
3620                 if (surface_type == MM_DISPLAY_SURFACE_OVERLAY)
3621                         rotation_type = ROTATION_USING_SINK;
3622                 else
3623                         rotation_type = ROTATION_USING_FLIP; //C
3624
3625                 LOGD("using %d type for rotation", rotation_type);
3626         }
3627
3628         /* get property value for setting */
3629         switch (rotation_type) {
3630         case ROTATION_USING_SINK: // tizenwlsink
3631                 {
3632                         switch (dest_angle) {
3633                         case 0:
3634                                 break;
3635                         case 90:
3636                                 pro_value = 3; // clockwise 90
3637                                 break;
3638                         case 180:
3639                                 pro_value = 2;
3640                                 break;
3641                         case 270:
3642                                 pro_value = 1; // counter-clockwise 90
3643                                 break;
3644                         }
3645                 }
3646                 break;
3647         case ROTATION_USING_CUSTOM:
3648                 {
3649                         gchar *ename = NULL;
3650                         ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
3651
3652                         if (g_strrstr(ename, "fimcconvert")) {
3653                                 switch (dest_angle) {
3654                                 case 0:
3655                                         break;
3656                                 case 90:
3657                                         pro_value = 90; // clockwise 90
3658                                         break;
3659                                 case 180:
3660                                         pro_value = 180;
3661                                         break;
3662                                 case 270:
3663                                         pro_value = 270; // counter-clockwise 90
3664                                         break;
3665                                 }
3666                         }
3667                 }
3668                 break;
3669         case ROTATION_USING_FLIP: // videoflip
3670                 {
3671                                 switch (dest_angle) {
3672                                 case 0:
3673                                         break;
3674                                 case 90:
3675                                         pro_value = 1; // clockwise 90
3676                                         break;
3677                                 case 180:
3678                                         pro_value = 2;
3679                                         break;
3680                                 case 270:
3681                                         pro_value = 3; // counter-clockwise 90
3682                                         break;
3683                                 }
3684                 }
3685                 break;
3686         }
3687
3688         LOGD("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
3689
3690         *value = pro_value;
3691
3692         return TRUE;
3693 }
3694
3695 int
3696 __mmplayer_video_param_check_video_sink_bin(mm_player_t* player)
3697 {
3698         /* check video sinkbin is created */
3699         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
3700                 player->pipeline &&
3701                 player->pipeline->videobin &&
3702                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
3703                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
3704                 MM_ERROR_PLAYER_NOT_INITIALIZED);
3705
3706         return MM_ERROR_NONE;
3707 }
3708
3709 void
3710 __mmplayer_video_param_set_display_rotation(mm_player_t* player)
3711 {
3712         int rotation_value = 0;
3713         int org_angle = 0; // current supported angle values are 0, 90, 180, 270
3714         int user_angle = 0;
3715         MMPLAYER_FENTER();
3716
3717         /* check video sinkbin is created */
3718         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3719                 return;
3720
3721         __mmplayer_get_video_angle(player, &user_angle, &org_angle);
3722
3723         /* get rotation value to set */
3724         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
3725         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "rotate", rotation_value, NULL);
3726         LOGD("set video param : rotate %d", rotation_value);
3727 }
3728
3729 void
3730 __mmplayer_video_param_set_display_visible(mm_player_t* player)
3731 {
3732         MMHandleType attrs = 0;
3733         int visible = 0;
3734         MMPLAYER_FENTER();
3735
3736         /* check video sinkbin is created */
3737         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3738                 return;
3739
3740         attrs = MMPLAYER_GET_ATTRS(player);
3741         MMPLAYER_RETURN_IF_FAIL(attrs);
3742
3743         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
3744         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "visible", visible, NULL);
3745         LOGD("set video param : visible %d", visible);
3746 }
3747
3748 void
3749 __mmplayer_video_param_set_display_method(mm_player_t* player)
3750 {
3751         MMHandleType attrs = 0;
3752         int display_method = 0;
3753         MMPLAYER_FENTER();
3754
3755         /* check video sinkbin is created */
3756         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3757                 return;
3758
3759         attrs = MMPLAYER_GET_ATTRS(player);
3760         MMPLAYER_RETURN_IF_FAIL(attrs);
3761
3762         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
3763         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "display-geometry-method", display_method, NULL);
3764         LOGD("set video param : method %d", display_method);
3765 }
3766
3767 void
3768 __mmplayer_video_param_set_render_rectangle(mm_player_t* player)
3769 {
3770         MMHandleType attrs = 0;
3771         void *handle = NULL;
3772         /*set wl_display*/
3773         int wl_window_x = 0;
3774         int wl_window_y = 0;
3775         int wl_window_width = 0;
3776         int wl_window_height = 0;
3777         MMPLAYER_FENTER();
3778
3779         /* check video sinkbin is created */
3780         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3781                 return;
3782
3783         attrs = MMPLAYER_GET_ATTRS(player);
3784         MMPLAYER_RETURN_IF_FAIL(attrs);
3785
3786         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
3787
3788         if (handle) {
3789                 /*It should be set after setting window*/
3790                 mm_attrs_get_int_by_name(attrs, "wl_window_render_x", &wl_window_x);
3791                 mm_attrs_get_int_by_name(attrs, "wl_window_render_y", &wl_window_y);
3792                 mm_attrs_get_int_by_name(attrs, "wl_window_render_width", &wl_window_width);
3793                 mm_attrs_get_int_by_name(attrs, "wl_window_render_height", &wl_window_height);
3794
3795                 /* After setting window handle, set render      rectangle */
3796                 gst_video_overlay_set_render_rectangle(
3797                          GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
3798                          wl_window_x, wl_window_y, wl_window_width, wl_window_height);
3799                 LOGD("set video param : render rectangle : x(%d) y(%d) width(%d) height(%d)",
3800                         wl_window_x, wl_window_y, wl_window_width, wl_window_height);
3801
3802         }
3803 }
3804 void
3805 __mmplayer_video_param_set_display_overlay(mm_player_t* player)
3806 {
3807         MMHandleType attrs = 0;
3808         void *handle = NULL;
3809
3810         /* check video sinkbin is created */
3811         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3812                 return;
3813
3814         attrs = MMPLAYER_GET_ATTRS(player);
3815         MMPLAYER_RETURN_IF_FAIL(attrs);
3816
3817         /* common case if using overlay surface */
3818         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
3819
3820         if (handle) {
3821                 /* default is using wl_surface_id */
3822                 unsigned int wl_surface_id      = 0;
3823                 wl_surface_id = *(int*)handle;
3824                 LOGD("set video param : wl_surface_id %d %p", wl_surface_id, *(int*)handle);
3825                 gst_video_overlay_set_wl_window_wl_surface_id(
3826                                 GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
3827                                 *(int*)handle);
3828         } else
3829                 /* FIXIT : is it error case? */
3830                 LOGW("still we don't have a window handle on player attribute. create it's own surface.");
3831 }
3832
3833
3834 int
3835 __mmplayer_update_wayland_videosink_video_param(mm_player_t* player, char *param_name)
3836 {
3837         bool update_all_param = FALSE;
3838         MMPLAYER_FENTER();
3839
3840         /* check video sinkbin is created */
3841         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3842                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
3843
3844         if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) {
3845                 LOGE("can not find tizenwlsink");
3846                 return MM_ERROR_PLAYER_INTERNAL;
3847         }
3848
3849         LOGD("param_name : %s", param_name);
3850         if (!g_strcmp0(param_name, "update_all_param"))
3851                 update_all_param = TRUE;
3852
3853         if (update_all_param || !g_strcmp0(param_name, "display_overlay"))
3854                 __mmplayer_video_param_set_display_overlay(player);
3855         if (update_all_param || !g_strcmp0(param_name, "display_method"))
3856                 __mmplayer_video_param_set_display_method(player);
3857         if (update_all_param || !g_strcmp0(param_name, "wl_window_render_x"))
3858                 __mmplayer_video_param_set_render_rectangle(player);
3859         if (update_all_param || !g_strcmp0(param_name, "display_visible"))
3860                 __mmplayer_video_param_set_display_visible(player);
3861         if (update_all_param || !g_strcmp0(param_name, "display_rotation"))
3862                 __mmplayer_video_param_set_display_rotation(player);
3863
3864         return MM_ERROR_NONE;
3865 }
3866
3867 int
3868 _mmplayer_update_video_param(mm_player_t* player, char *param_name)
3869 {
3870         MMHandleType attrs = 0;
3871         int surface_type = 0;
3872         int ret = MM_ERROR_NONE;
3873
3874         MMPLAYER_FENTER();
3875
3876         /* check video sinkbin is created */
3877         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3878                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
3879
3880         attrs = MMPLAYER_GET_ATTRS(player);
3881         if (!attrs) {
3882                 LOGE("cannot get content attribute");
3883                 return MM_ERROR_PLAYER_INTERNAL;
3884         }
3885         LOGD("param_name : %s", param_name);
3886
3887         /* update display surface */
3888         mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
3889         LOGD("check display surface type attribute: %d", surface_type);
3890
3891         /* configuring display */
3892         switch (surface_type) {
3893         case MM_DISPLAY_SURFACE_OVERLAY:
3894                 {
3895                         ret = __mmplayer_update_wayland_videosink_video_param(player, param_name);
3896                         if (ret != MM_ERROR_NONE)
3897                                 return ret;
3898                 }
3899                 break;
3900         }
3901
3902         MMPLAYER_FLEAVE();
3903
3904         return MM_ERROR_NONE;
3905 }
3906
3907 int
3908 _mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
3909 {
3910         gboolean disable_overlay = FALSE;
3911         mm_player_t* player = (mm_player_t*) hplayer;
3912         int ret = MM_ERROR_NONE;
3913
3914         MMPLAYER_FENTER();
3915         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3916         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
3917                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
3918                                                                 MM_ERROR_PLAYER_NO_OP); /* invalid op */
3919
3920         if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
3921                 LOGW("Display control is not supported");
3922                 return MM_ERROR_PLAYER_INTERNAL;
3923         }
3924
3925         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
3926
3927         if (audio_only == (bool)disable_overlay) {
3928                 LOGE("It's the same with current setting: (%d)", audio_only);
3929                 return MM_ERROR_NONE;
3930         }
3931
3932         if (audio_only) {
3933                 LOGE("disable overlay");
3934                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", TRUE, NULL);
3935
3936                 /* release overlay resource */
3937                 if (player->video_overlay_resource != NULL) {
3938                         ret = mm_resource_manager_mark_for_release(player->resource_manager,
3939                                         player->video_overlay_resource);
3940                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3941                                 LOGE("failed to mark overlay resource for release, ret(0x%x)\n", ret);
3942                                 goto ERROR;
3943                         }
3944                         player->video_overlay_resource = NULL;
3945                 }
3946
3947                 ret = mm_resource_manager_commit(player->resource_manager);
3948                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3949                         LOGE("failed to commit acquiring of overlay resource, ret(0x%x)\n", ret);
3950                         goto ERROR;
3951                 }
3952         } else {
3953                 /* mark video overlay for acquire */
3954                 if (player->video_overlay_resource == NULL) {
3955                         ret = mm_resource_manager_mark_for_acquire(player->resource_manager,
3956                                         MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
3957                                         MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
3958                                         &player->video_overlay_resource);
3959                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3960                                 LOGE("could not prepare for video_overlay resource\n");
3961                                 goto ERROR;
3962                         }
3963                 }
3964
3965                 player->interrupted_by_resource = FALSE;
3966                 /* acquire resources for video overlay */
3967                 ret = mm_resource_manager_commit(player->resource_manager);
3968                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3969                         LOGE("could not acquire resources for video playing\n");
3970                         goto ERROR;
3971                 }
3972
3973                 LOGD("enable overlay");
3974                 __mmplayer_video_param_set_display_overlay(player);
3975                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", FALSE, NULL);
3976         }
3977
3978 ERROR:
3979         MMPLAYER_FLEAVE();
3980         return MM_ERROR_NONE;
3981 }
3982
3983 int
3984 _mmplayer_get_audio_only(MMHandleType hplayer, bool *paudio_only)
3985 {
3986         mm_player_t* player = (mm_player_t*) hplayer;
3987         gboolean disable_overlay = FALSE;
3988
3989         MMPLAYER_FENTER();
3990
3991         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3992         MMPLAYER_RETURN_VAL_IF_FAIL(paudio_only, MM_ERROR_INVALID_ARGUMENT);
3993         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
3994                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
3995                                                                 MM_ERROR_PLAYER_NO_OP); /* invalid op */
3996
3997         if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
3998                 LOGW("Display control is not supported");
3999                 return MM_ERROR_PLAYER_INTERNAL;
4000         }
4001
4002         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
4003
4004         *paudio_only = (bool)(disable_overlay);
4005
4006         LOGD("audio_only : %d", *paudio_only);
4007
4008         MMPLAYER_FLEAVE();
4009
4010         return MM_ERROR_NONE;
4011 }
4012
4013 static int
4014 __mmplayer_gst_element_link_bucket(GList* element_bucket)
4015 {
4016         GList* bucket = element_bucket;
4017         MMPlayerGstElement* element = NULL;
4018         MMPlayerGstElement* prv_element = NULL;
4019         gint successful_link_count = 0;
4020
4021         MMPLAYER_FENTER();
4022
4023         MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, -1);
4024
4025         prv_element = (MMPlayerGstElement*)bucket->data;
4026         bucket = bucket->next;
4027
4028         for (; bucket; bucket = bucket->next) {
4029                 element = (MMPlayerGstElement*)bucket->data;
4030
4031                 if (element && element->gst) {
4032                         /* If next element is audio appsrc then make a separate audio pipeline */
4033                         if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "audio_appsrc") ||
4034                                 !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "subtitle_appsrc")) {
4035                                 prv_element = element;
4036                                 continue;
4037                         }
4038
4039                         if (prv_element && prv_element->gst) {
4040                                 if (gst_element_link(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst))) {
4041                                         LOGD("linking [%s] to [%s] success\n",
4042                                                 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4043                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
4044                                         successful_link_count++;
4045                                 } else {
4046                                         LOGD("linking [%s] to [%s] failed\n",
4047                                                 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4048                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
4049                                         return -1;
4050                                 }
4051                         }
4052                 }
4053
4054                 prv_element = element;
4055         }
4056
4057         MMPLAYER_FLEAVE();
4058
4059         return successful_link_count;
4060 }
4061
4062 static int
4063 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket)
4064 {
4065         GList* bucket = element_bucket;
4066         MMPlayerGstElement* element = NULL;
4067         int successful_add_count = 0;
4068
4069         MMPLAYER_FENTER();
4070
4071         MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, 0);
4072         MMPLAYER_RETURN_VAL_IF_FAIL(bin, 0);
4073
4074         for (; bucket; bucket = bucket->next) {
4075                 element = (MMPlayerGstElement*)bucket->data;
4076
4077                 if (element && element->gst) {
4078                         if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
4079                                 LOGD("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
4080                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
4081                                         GST_ELEMENT_NAME(GST_ELEMENT(bin)));
4082                                 return 0;
4083                         }
4084                         successful_add_count++;
4085                 }
4086         }
4087
4088         MMPLAYER_FLEAVE();
4089
4090         return successful_add_count;
4091 }
4092
4093 static void __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data)
4094 {
4095         mm_player_t* player = (mm_player_t*) data;
4096         GstCaps *caps = NULL;
4097         GstStructure *str = NULL;
4098         const char *name;
4099
4100         MMPLAYER_FENTER();
4101
4102         MMPLAYER_RETURN_IF_FAIL(pad)
4103         MMPLAYER_RETURN_IF_FAIL(unused)
4104         MMPLAYER_RETURN_IF_FAIL(data)
4105
4106         caps = gst_pad_get_current_caps(pad);
4107         if (!caps)
4108                 return;
4109
4110         str = gst_caps_get_structure(caps, 0);
4111         if (!str)
4112                 goto ERROR;
4113
4114         name = gst_structure_get_name(str);
4115         if (!name)
4116                 goto ERROR;
4117
4118         LOGD("name = %s\n", name);
4119
4120         if (strstr(name, "audio")) {
4121                 _mmplayer_update_content_attrs(player, ATTR_AUDIO);
4122
4123                 if (player->audio_stream_changed_cb) {
4124                         LOGE("call the audio stream changed cb\n");
4125                         player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
4126                 }
4127         } else if (strstr(name, "video")) {
4128                 if ((name = gst_structure_get_string(str, "format")))
4129                         player->set_mode.video_zc = name[0] == 'S';
4130
4131                 _mmplayer_update_content_attrs(player, ATTR_VIDEO);
4132
4133                 if (player->video_stream_changed_cb) {
4134                         LOGE("call the video stream changed cb\n");
4135                         player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
4136                 }
4137         } else
4138                 goto ERROR;
4139
4140 ERROR:
4141
4142         gst_caps_unref(caps);
4143
4144         MMPLAYER_FLEAVE();
4145
4146         return;
4147 }
4148
4149
4150
4151 /**
4152  * This function is to create audio pipeline for playing.
4153  *
4154  * @param       player          [in]    handle of player
4155  *
4156  * @return      This function returns zero on success.
4157  * @remark
4158  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
4159  */
4160 /* macro for code readability. just for sinkbin-creation functions */
4161 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
4162 do {\
4163         x_bin[x_id].id = x_id;\
4164         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4165         if (!x_bin[x_id].gst) {\
4166                 LOGE("failed to create %s \n", x_factory);\
4167                 goto ERROR;\
4168         } else {\
4169                 if (x_player->ini.set_dump_element_flag)\
4170                         __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
4171         } \
4172         if (x_add_bucket)\
4173                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
4174 } while (0);
4175
4176 static void
4177 __mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all)
4178 {
4179         GList *l = NULL;
4180
4181         MMPLAYER_FENTER();
4182         MMPLAYER_RETURN_IF_FAIL(player);
4183
4184         if (player->audio_stream_buff_list) {
4185                 for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
4186                         mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
4187                         if (tmp) {
4188                                 if (send_all) {
4189                                         LOGD("[%"G_GUINT64_FORMAT"] send remained data.", tmp->channel_mask);
4190                                         __mmplayer_audio_stream_send_data(player, tmp);
4191                                 }
4192                                 if (tmp->pcm_data)
4193                                         g_free(tmp->pcm_data);
4194                                 g_free(tmp);
4195                         }
4196                 }
4197                 g_list_free(player->audio_stream_buff_list);
4198                 player->audio_stream_buff_list = NULL;
4199         }
4200
4201         MMPLAYER_FLEAVE();
4202 }
4203
4204 static void
4205 __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer)
4206 {
4207         MMPlayerAudioStreamDataType audio_stream = { 0, };
4208
4209         MMPLAYER_FENTER();
4210         MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
4211
4212         audio_stream.bitrate = a_buffer->bitrate;
4213         audio_stream.channel = a_buffer->channel;
4214         audio_stream.depth = a_buffer->depth;
4215         audio_stream.is_little_endian = a_buffer->is_little_endian;
4216         audio_stream.channel_mask = a_buffer->channel_mask;
4217         audio_stream.data_size = a_buffer->data_size;
4218         audio_stream.data = a_buffer->pcm_data;
4219
4220         /* LOGD("[%"G_GUINT64_FORMAT"] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_stream_cb_user_param); */
4221         player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param);
4222
4223         MMPLAYER_FLEAVE();
4224 }
4225
4226 static void
4227 __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
4228 {
4229         mm_player_t* player = (mm_player_t*) data;
4230
4231         gint channel = 0;
4232         gint rate = 0;
4233         gint depth = 0;
4234         gint endianness = 0;
4235         guint64 channel_mask = 0;
4236         void *a_data = NULL;
4237         gint a_size = 0;
4238         mm_player_audio_stream_buff_t *a_buffer = NULL;
4239         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
4240         GList *l = NULL;
4241
4242         MMPLAYER_FENTER();
4243         MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
4244
4245         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
4246         a_data = mapinfo.data;
4247         a_size = mapinfo.size;
4248
4249         GstCaps *caps = gst_pad_get_current_caps(pad);
4250         GstStructure *structure = gst_caps_get_structure(caps, 0);
4251
4252         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
4253         gst_structure_get_int(structure, "rate", &rate);
4254         gst_structure_get_int(structure, "channels", &channel);
4255         gst_structure_get_int(structure, "depth", &depth);
4256         gst_structure_get_int(structure, "endianness", &endianness);
4257         gst_structure_get(structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
4258         gst_caps_unref(GST_CAPS(caps));
4259
4260         /* In case of the sync is false, use buffer list.              *
4261          * The num of buffer list depends on the num of audio channels */
4262         if (player->audio_stream_buff_list) {
4263                 for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
4264                         mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
4265                         if (tmp) {
4266                                 if (channel_mask == tmp->channel_mask) {
4267                                         /* LOGD("[%"G_GUINT64_FORMAT"] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size); */
4268                                         if (tmp->data_size + a_size < tmp->buff_size) {
4269                                                 memcpy(tmp->pcm_data + tmp->data_size, a_data, a_size);
4270                                                 tmp->data_size += a_size;
4271                                         } else {
4272                                                 /* send data to client */
4273                                                 __mmplayer_audio_stream_send_data(player, tmp);
4274
4275                                                 if (a_size > tmp->buff_size) {
4276                                                         LOGD("[%"G_GUINT64_FORMAT"] adj buffer size %d -> %d", channel_mask, tmp->buff_size, a_size);
4277                                                         tmp->pcm_data = g_realloc(tmp->pcm_data, a_size);
4278                                                         if (tmp->pcm_data == NULL) {
4279                                                                 LOGE("failed to realloc data.");
4280                                                                 goto DONE;
4281                                                         }
4282                                                         tmp->buff_size = a_size;
4283                                                 }
4284                                                 memset(tmp->pcm_data, 0x00, tmp->buff_size);
4285                                                 memcpy(tmp->pcm_data, a_data, a_size);
4286                                                 tmp->data_size = a_size;
4287                                         }
4288                                         goto DONE;
4289                                 }
4290                         } else {
4291                                 LOGE("data is empty in list.");
4292                                 goto DONE;
4293                         }
4294                 }
4295         }
4296
4297         /* create new audio stream data */
4298         a_buffer = (mm_player_audio_stream_buff_t*)g_malloc0(sizeof(mm_player_audio_stream_buff_t));
4299         if (a_buffer == NULL) {
4300                 LOGE("failed to alloc data.");
4301                 goto DONE;
4302         }
4303         a_buffer->bitrate = rate;
4304         a_buffer->channel = channel;
4305         a_buffer->depth = depth;
4306         a_buffer->is_little_endian = (endianness == 1234 ? 1 : 0);
4307         a_buffer->channel_mask = channel_mask;
4308         a_buffer->data_size = a_size;
4309
4310         if (!player->audio_stream_sink_sync) {
4311                 /* If sync is FALSE, use buffer list to reduce the IPC. */
4312                 a_buffer->buff_size = (a_size > player->ini.pcm_buffer_size) ? (a_size) : (player->ini.pcm_buffer_size);
4313                 a_buffer->pcm_data = g_malloc(a_buffer->buff_size);
4314                 if (a_buffer->pcm_data == NULL) {
4315                         LOGE("failed to alloc data.");
4316                         g_free(a_buffer);
4317                         goto DONE;
4318                 }
4319                 memcpy(a_buffer->pcm_data, a_data, a_size);
4320                 /* LOGD("new [%"G_GUINT64_FORMAT"] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size); */
4321                 player->audio_stream_buff_list = g_list_append(player->audio_stream_buff_list, a_buffer);
4322         } else {
4323                 /* If sync is TRUE, send data directly. */
4324                 a_buffer->pcm_data = a_data;
4325                 __mmplayer_audio_stream_send_data(player, a_buffer);
4326                 g_free(a_buffer);
4327         }
4328
4329 DONE:
4330         gst_buffer_unmap(buffer, &mapinfo);
4331         MMPLAYER_FLEAVE();
4332 }
4333
4334 static void
4335 __mmplayer_gst_audio_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
4336 {
4337         mm_player_t* player = (mm_player_t*)data;
4338         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
4339         GstPad* sinkpad = NULL;
4340         GstElement *queue = NULL, *sink = NULL;
4341
4342         MMPLAYER_FENTER();
4343         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
4344
4345         queue = gst_element_factory_make("queue", NULL);
4346         if (queue == NULL) {
4347                 LOGD("fail make queue\n");
4348                 goto ERROR;
4349         }
4350
4351         sink = gst_element_factory_make("fakesink", NULL);
4352         if (sink == NULL) {
4353                 LOGD("fail make fakesink\n");
4354                 goto ERROR;
4355         }
4356
4357         gst_bin_add_many(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
4358
4359         if (!gst_element_link_pads_full(queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING)) {
4360                 LOGW("failed to link queue & sink\n");
4361                 goto ERROR;
4362         }
4363
4364         sinkpad = gst_element_get_static_pad(queue, "sink");
4365
4366         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
4367                 LOGW("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
4368                 goto ERROR;
4369         }
4370
4371         LOGE("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
4372
4373         gst_object_unref(sinkpad);
4374         g_object_set(sink, "sync", player->audio_stream_sink_sync, NULL);
4375         g_object_set(sink, "signal-handoffs", TRUE, NULL);
4376
4377         gst_element_set_state(sink, GST_STATE_PAUSED);
4378         gst_element_set_state(queue, GST_STATE_PAUSED);
4379
4380         MMPLAYER_SIGNAL_CONNECT(player,
4381                 G_OBJECT(sink),
4382                 MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4383                 "handoff",
4384                 G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
4385                 (gpointer)player);
4386
4387         MMPLAYER_FLEAVE();
4388         return;
4389
4390 ERROR:
4391         LOGE("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
4392         if (queue) {
4393                 gst_object_unref(GST_OBJECT(queue));
4394                 queue = NULL;
4395         }
4396         if (sink) {
4397                 gst_object_unref(GST_OBJECT(sink));
4398                 sink = NULL;
4399         }
4400         if (sinkpad) {
4401                 gst_object_unref(GST_OBJECT(sinkpad));
4402                 sinkpad = NULL;
4403         }
4404
4405         return;
4406 }
4407
4408 void __mmplayer_gst_set_audiosink_property(mm_player_t* player, MMHandleType attrs)
4409 {
4410         #define MAX_PROPS_LEN 128
4411         gint latency_mode = 0;
4412         gchar *stream_type = NULL;
4413         gchar *latency = NULL;
4414         gint stream_id = 0;
4415         gchar stream_props[MAX_PROPS_LEN] = {0,};
4416         GstStructure *props = NULL;
4417
4418         /* set volume table
4419          * It should be set after player creation through attribute.
4420          * But, it can not be changed during playing.
4421          */
4422         MMPLAYER_FENTER();
4423         mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
4424         mm_attrs_get_string_by_name(attrs, "sound_stream_type", &stream_type);
4425
4426         if (!stream_type) {
4427                 LOGE("stream_type is null.\n");
4428         } else {
4429                 if (player->sound.focus_id)
4430                         snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d, media.focus_id=%d",
4431                                         stream_type, stream_id, player->sound.focus_id);
4432                 else
4433                         snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d",
4434                                         stream_type, stream_id);
4435                 props = gst_structure_from_string(stream_props, NULL);
4436                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
4437                 LOGI("stream_type[%s], stream_id[%d], focus_id[%d], result[%s].\n",
4438                         stream_type, stream_id, player->sound.focus_id, stream_props);
4439                 gst_structure_free(props);
4440         }
4441
4442         mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
4443
4444         switch (latency_mode) {
4445         case AUDIO_LATENCY_MODE_LOW:
4446                 latency = g_strndup("low", 3);
4447                 break;
4448         case AUDIO_LATENCY_MODE_MID:
4449                 latency = g_strndup("mid", 3);
4450                 break;
4451         case AUDIO_LATENCY_MODE_HIGH:
4452                 latency = g_strndup("high", 4);
4453                 break;
4454         };
4455
4456         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
4457                         "latency", latency,
4458                         NULL);
4459
4460         LOGD("audiosink property - latency=%s \n", latency);
4461
4462         g_free(latency);
4463
4464         MMPLAYER_FLEAVE();
4465 }
4466
4467 static int
4468 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
4469 {
4470         MMPlayerGstElement* first_element = NULL;
4471         MMPlayerGstElement* audiobin = NULL;
4472         MMHandleType attrs = 0;
4473         GstPad *pad = NULL;
4474         GstPad *ghostpad = NULL;
4475         GList* element_bucket = NULL;
4476         gboolean link_audio_sink_now = TRUE;
4477         int i = 0;
4478         GstCaps *acaps;
4479
4480         MMPLAYER_FENTER();
4481
4482         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4483
4484         /* alloc handles */
4485         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
4486         if (!audiobin) {
4487                 LOGE("failed to allocate memory for audiobin\n");
4488                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
4489         }
4490
4491         attrs = MMPLAYER_GET_ATTRS(player);
4492
4493         /* create bin */
4494         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
4495         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
4496         if (!audiobin[MMPLAYER_A_BIN].gst) {
4497                 LOGE("failed to create audiobin\n");
4498                 goto ERROR;
4499         }
4500
4501         /* take it */
4502         player->pipeline->audiobin = audiobin;
4503
4504         player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
4505
4506         /* Adding audiotp plugin for reverse trickplay feature */
4507 //      MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
4508
4509         /* converter */
4510         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
4511
4512         /* replaygain volume */
4513         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RGVOL, "rgvolume", "audio rgvolume", TRUE, player);
4514         if (player->sound.rg_enable)
4515                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", TRUE, NULL);
4516         else
4517                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", FALSE, NULL);
4518
4519         /* resampler */
4520         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER,  player->ini.audioresampler_element, "audio resampler", TRUE, player);
4521
4522         if (player->set_mode.pcm_extraction) {
4523                 // pcm extraction only and no sound output
4524                 if (player->audio_stream_render_cb_ex) {
4525                         char *caps_str = NULL;
4526                         GstCaps* caps = NULL;
4527                         gchar *format = NULL;
4528
4529                         /* capsfilter */
4530                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4531
4532                         mm_attrs_get_string_by_name(player->attrs, "pcm_audioformat", &format);
4533
4534                         LOGD("contents : format: %s samplerate : %d pcm_channel: %d", format, player->pcm_samplerate, player->pcm_channel);
4535
4536                         caps = gst_caps_new_simple("audio/x-raw",
4537                                         "format", G_TYPE_STRING, format,
4538                                         "rate", G_TYPE_INT, player->pcm_samplerate,
4539                                         "channels", G_TYPE_INT, player->pcm_channel,
4540                                         NULL);
4541                         caps_str = gst_caps_to_string(caps);
4542                         LOGD("new caps : %s\n", caps_str);
4543
4544                         g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4545
4546                         /* clean */
4547                         gst_caps_unref(caps);
4548                         MMPLAYER_FREEIF(caps_str);
4549
4550                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
4551
4552                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
4553                         /* raw pad handling signal */
4554                         MMPLAYER_SIGNAL_CONNECT(player,
4555                                 (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
4556                                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
4557                                                                                                 G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
4558                 } else {
4559                         int dst_samplerate = 0;
4560                         int dst_channels = 0;
4561                         int dst_depth = 0;
4562                         char *caps_str = NULL;
4563                         GstCaps* caps = NULL;
4564
4565                         /* get conf. values */
4566                         mm_attrs_multiple_get(player->attrs,
4567                                                 NULL,
4568                                                 "pcm_extraction_samplerate", &dst_samplerate,
4569                                                 "pcm_extraction_channels", &dst_channels,
4570                                                 "pcm_extraction_depth", &dst_depth,
4571                                                 NULL);
4572
4573                         /* capsfilter */
4574                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4575                         caps = gst_caps_new_simple("audio/x-raw",
4576                                         "rate", G_TYPE_INT, dst_samplerate,
4577                                         "channels", G_TYPE_INT, dst_channels,
4578                                         "depth", G_TYPE_INT, dst_depth,
4579                                         NULL);
4580                         caps_str = gst_caps_to_string(caps);
4581                         LOGD("new caps : %s\n", caps_str);
4582
4583                         g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4584
4585                         /* clean */
4586                         gst_caps_unref(caps);
4587                         MMPLAYER_FREEIF(caps_str);
4588
4589                         /* fake sink */
4590                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
4591
4592                         /* set sync */
4593                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
4594                 }
4595         } else {
4596                 // normal playback
4597                 //GstCaps* caps = NULL;
4598                 gint channels = 0;
4599
4600                 /* for logical volume control */
4601                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
4602                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
4603
4604                 if (player->sound.mute) {
4605                         LOGD("mute enabled\n");
4606                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
4607                 }
4608
4609 #if 0
4610                 /*capsfilter */
4611                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
4612                 caps = gst_caps_from_string("audio/x-raw-int, "
4613                                         "endianness = (int) LITTLE_ENDIAN, "
4614                                         "signed = (boolean) true, "
4615                                         "width = (int) 16, "
4616                                         "depth = (int) 16");
4617                 g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4618                 gst_caps_unref(caps);
4619 #endif
4620
4621                 /* check if multi-channels */
4622                 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) {
4623                         GstPad *srcpad = NULL;
4624                         GstCaps *caps = NULL;
4625
4626                         if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src"))) {
4627                                 if ((caps = gst_pad_query_caps(srcpad, NULL))) {
4628                                         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
4629                                         GstStructure *str = gst_caps_get_structure(caps, 0);
4630                                         if (str)
4631                                                 gst_structure_get_int(str, "channels", &channels);
4632                                         gst_caps_unref(caps);
4633                                 }
4634                                 gst_object_unref(srcpad);
4635                         }
4636                 }
4637
4638                 /* audio effect element. if audio effect is enabled */
4639                 if ((strcmp(player->ini.audioeffect_element, ""))
4640                         && (channels <= 2)
4641                         && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
4642                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.audioeffect_element, "audio effect filter", TRUE, player);
4643
4644                         LOGD("audio effect config. bypass = %d, effect type  = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
4645
4646                         if ((!player->bypass_audio_effect)
4647                                 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
4648                                 if (MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type) {
4649                                         if (!_mmplayer_audio_effect_custom_apply(player))
4650                                                 LOGI("apply audio effect(custom) setting success\n");
4651                                 }
4652                         }
4653
4654                         if ((strcmp(player->ini.audioeffect_element_custom, ""))
4655                                 && (player->set_mode.rich_audio))
4656                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.audioeffect_element_custom, "audio effect filter custom", TRUE, player);
4657                 }
4658
4659                 /* create audio sink */
4660                 LOGD("360 spherical %d, channels %d, ambisonic type %d, format %d, order %d",
4661                                 player->is_content_spherical, channels, player->video360_metadata.ambisonic_type,
4662                                 player->video360_metadata.ambisonic_format, player->video360_metadata.ambisonic_order);
4663
4664                 /* Note: qtdemux converts audio metadata defaults to openalsink defaults. */
4665                 if (player->is_360_feature_enabled &&
4666                         player->is_content_spherical &&
4667                         channels == 4 &&
4668                         player->video360_metadata.ambisonic_type == MMFILE_AMBISONIC_TYPE_PERIPHONIC &&
4669                         player->video360_metadata.ambisonic_format == MMFILE_AMBISONIC_FORMAT_AMB &&
4670                         player->video360_metadata.ambisonic_order == MMFILE_AMBISONIC_ORDER_FOA) {
4671
4672                         strncpy(player->ini.audiosink_element, "openalsink", PLAYER_INI_MAX_STRLEN - 1);
4673
4674                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_BFORMAT, "audioconvert", "audio-converter-bformat", link_audio_sink_now, player);
4675
4676                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_360, "capsfilter", "audio-caps-filter", link_audio_sink_now, player);
4677                         acaps = gst_caps_from_string(SPATIAL_AUDIO_CAPS);
4678                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_CAPS_360].gst), "caps", acaps, NULL);
4679                         gst_caps_unref(acaps);
4680
4681                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "openalsink", "audiosink", link_audio_sink_now, player);
4682                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "source-ambisonics-type", 1, NULL);
4683                         sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info);
4684                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL);
4685
4686                         player->is_openal_plugin_used = TRUE;
4687
4688                         if (player->video360_yaw_radians <= M_PI &&
4689                                         player->video360_yaw_radians >= -M_PI &&
4690                                         player->video360_pitch_radians <= M_PI_2 &&
4691                                         player->video360_pitch_radians >= -M_PI_2) {
4692                                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
4693                                                 "source-orientation-y", (int) (player->video360_yaw_radians * 180.0 / M_PI),
4694                                                 "source-orientation-x", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
4695                         } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
4696                                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
4697                                                 "source-orientation-y", player->video360_metadata.init_view_heading,
4698                                                 "source-orientation-x", player->video360_metadata.init_view_pitch, NULL);
4699                         }
4700                 } else {
4701                         if (player->is_360_feature_enabled && player->is_content_spherical)
4702                                 LOGW("Audio track isn't of the ambisonic type and can't be played back as a spatial sound.\n");
4703                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", link_audio_sink_now, player);
4704                 }
4705
4706                 /* qos on */
4707                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);       /* qos on */
4708                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
4709
4710
4711                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) ||
4712                         (player->videodec_linked && player->ini.use_system_clock)) {
4713                         LOGD("system clock will be used.\n");
4714                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE,  NULL);
4715                 }
4716
4717                 if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
4718                         __mmplayer_gst_set_audiosink_property(player, attrs);
4719         }
4720
4721         if (audiobin[MMPLAYER_A_SINK].gst) {
4722                 GstPad *sink_pad = NULL;
4723                 sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
4724                 MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4725                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
4726                 gst_object_unref(GST_OBJECT(sink_pad));
4727         }
4728
4729         __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
4730
4731         /* adding created elements to bin */
4732         LOGD("adding created elements to bin\n");
4733         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket)) {
4734                 LOGE("failed to add elements\n");
4735                 goto ERROR;
4736         }
4737
4738         /* linking elements in the bucket by added order. */
4739         LOGD("Linking elements in the bucket by added order.\n");
4740         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
4741                 LOGE("failed to link elements\n");
4742                 goto ERROR;
4743         }
4744
4745         /* get first element's sinkpad for creating ghostpad */
4746         first_element = (MMPlayerGstElement *)element_bucket->data;
4747         if (!first_element) {
4748                 LOGE("failed to get first elem\n");
4749                 goto ERROR;
4750         }
4751
4752         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
4753         if (!pad) {
4754                 LOGE("failed to get pad from first element of audiobin\n");
4755                 goto ERROR;
4756         }
4757
4758         ghostpad = gst_ghost_pad_new("sink", pad);
4759         if (!ghostpad) {
4760                 LOGE("failed to create ghostpad\n");
4761                 goto ERROR;
4762         }
4763
4764         if (FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad)) {
4765                 LOGE("failed to add ghostpad to audiobin\n");
4766                 goto ERROR;
4767         }
4768
4769         gst_object_unref(pad);
4770
4771         g_list_free(element_bucket);
4772         MMPLAYER_FLEAVE();
4773
4774         return MM_ERROR_NONE;
4775
4776 ERROR:
4777
4778         LOGD("ERROR : releasing audiobin\n");
4779
4780         if (pad)
4781                 gst_object_unref(GST_OBJECT(pad));
4782
4783         if (ghostpad)
4784                 gst_object_unref(GST_OBJECT(ghostpad));
4785
4786         if (element_bucket)
4787                 g_list_free(element_bucket);
4788
4789         /* release element which are not added to bin */
4790         for (i = 1; i < MMPLAYER_A_NUM; i++) {
4791                 /* NOTE : skip bin */
4792                 if (audiobin[i].gst) {
4793                         GstObject* parent = NULL;
4794                         parent = gst_element_get_parent(audiobin[i].gst);
4795
4796                         if (!parent) {
4797                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
4798                                 audiobin[i].gst = NULL;
4799                         } else
4800                                 gst_object_unref(GST_OBJECT(parent));
4801                 }
4802         }
4803
4804         /* release audiobin with it's childs */
4805         if (audiobin[MMPLAYER_A_BIN].gst)
4806                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
4807
4808         MMPLAYER_FREEIF(audiobin);
4809
4810         player->pipeline->audiobin = NULL;
4811
4812         return MM_ERROR_PLAYER_INTERNAL;
4813 }
4814
4815 static GstPadProbeReturn
4816 __mmplayer_audio_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
4817 {
4818         mm_player_t* player = (mm_player_t*) u_data;
4819         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
4820         GstMapInfo probe_info = GST_MAP_INFO_INIT;
4821
4822         gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
4823
4824         if (player->audio_stream_cb && probe_info.size && probe_info.data)
4825                 player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
4826
4827         return GST_PAD_PROBE_OK;
4828 }
4829
4830 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
4831 {
4832         return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
4833 }
4834
4835 int _mmplayer_video_stream_release_bo(mm_player_t* player, void* bo)
4836 {
4837         int ret = MM_ERROR_NONE;
4838         GList *l = NULL;
4839         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4840         MMPLAYER_RETURN_VAL_IF_FAIL(bo, MM_ERROR_INVALID_ARGUMENT);
4841
4842         MMPLAYER_VIDEO_BO_LOCK(player);
4843
4844         if (player->video_bo_list) {
4845                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4846                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4847                         if (tmp && tmp->bo == bo) {
4848                                 tmp->using = FALSE;
4849                                 LOGD("release bo %p", bo);
4850                                 tbm_bo_unref(tmp->bo);
4851                                 MMPLAYER_VIDEO_BO_UNLOCK(player);
4852                                 MMPLAYER_VIDEO_BO_SIGNAL(player);
4853                                 return ret;
4854                         }
4855                 }
4856         } else {
4857                 /* hw codec is running or the list was reset for DRC. */
4858                 LOGW("there is no bo list.");
4859         }
4860         MMPLAYER_VIDEO_BO_UNLOCK(player);
4861
4862         LOGW("failed to find bo %p", bo);
4863         return ret;
4864 }
4865
4866 static void
4867 __mmplayer_video_stream_destroy_bo_list(mm_player_t* player)
4868 {
4869         GList *l = NULL;
4870
4871         MMPLAYER_FENTER();
4872         MMPLAYER_RETURN_IF_FAIL(player);
4873
4874         MMPLAYER_VIDEO_BO_LOCK(player);
4875         if (player->video_bo_list) {
4876                 LOGD("destroy video_bo_list : %d", g_list_length(player->video_bo_list));
4877                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4878                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4879                         if (tmp) {
4880                                 if (tmp->bo)
4881                                         tbm_bo_unref(tmp->bo);
4882                                 g_free(tmp);
4883                         }
4884                 }
4885                 g_list_free(player->video_bo_list);
4886                 player->video_bo_list = NULL;
4887         }
4888         player->video_bo_size = 0;
4889         MMPLAYER_VIDEO_BO_UNLOCK(player);
4890
4891         MMPLAYER_FLEAVE();
4892         return;
4893 }
4894
4895 static void*
4896 __mmplayer_video_stream_get_bo(mm_player_t* player, int size)
4897 {
4898         GList *l = NULL;
4899         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
4900         gboolean ret = TRUE;
4901
4902         /* check DRC, if it is, destroy the prev bo list to create again */
4903         if (player->video_bo_size != size) {
4904                 LOGD("video size is changed: %d -> %d", player->video_bo_size, size);
4905                 __mmplayer_video_stream_destroy_bo_list(player);
4906                 player->video_bo_size = size;
4907         }
4908
4909         MMPLAYER_VIDEO_BO_LOCK(player);
4910
4911         if ((!player->video_bo_list) ||
4912                 (g_list_length(player->video_bo_list) < player->ini.num_of_video_bo)) {
4913
4914                 /* create bo list */
4915                 int idx = 0;
4916                 LOGD("Create bo list for decoded video stream(num:%d)", player->ini.num_of_video_bo);
4917
4918                 if (player->video_bo_list) {
4919                         /* if bo list did not created all, try it again. */
4920                         idx = g_list_length(player->video_bo_list);
4921                         LOGD("bo list exist(len: %d)", idx);
4922                 }
4923
4924                 for (; idx < player->ini.num_of_video_bo; idx++) {
4925                         mm_player_video_bo_info_t* bo_info = g_new(mm_player_video_bo_info_t, 1);
4926                         if (!bo_info) {
4927                                 LOGE("Fail to alloc bo_info.");
4928                                 break;
4929                         }
4930                         bo_info->bo = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
4931                         if (!bo_info->bo) {
4932                                 LOGE("Fail to tbm_bo_alloc.");
4933                                 g_free(bo_info);
4934                                 break;
4935                         }
4936                         bo_info->using = FALSE;
4937                         player->video_bo_list = g_list_append(player->video_bo_list, bo_info);
4938                 }
4939
4940                 /* update video num buffers */
4941                 player->video_num_buffers = idx;
4942                 if (idx == player->ini.num_of_video_bo)
4943                         player->video_extra_num_buffers = player->ini.num_of_video_bo/2;
4944
4945                 if (idx == 0) {
4946                         MMPLAYER_VIDEO_BO_UNLOCK(player);
4947                         return NULL;
4948                 }
4949
4950                 LOGD("Num of video buffers(%d/%d)", player->video_num_buffers, player->video_extra_num_buffers);
4951         }
4952
4953         while (TRUE) {
4954                 /* get bo from list*/
4955                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4956                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4957                         if (tmp && (tmp->using == FALSE)) {
4958                                 LOGD("found bo %p to use", tmp->bo);
4959                                 tmp->using = TRUE;
4960                                 MMPLAYER_VIDEO_BO_UNLOCK(player);
4961                                 return tbm_bo_ref(tmp->bo);
4962                         }
4963                 }
4964                 if (!ret) {
4965                         LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
4966                         MMPLAYER_VIDEO_BO_UNLOCK(player);
4967                         return NULL;
4968                 }
4969
4970                 if (player->ini.video_bo_timeout <= 0) {
4971                         MMPLAYER_VIDEO_BO_WAIT(player);
4972                 } else {
4973                         gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout*G_TIME_SPAN_SECOND;
4974                         ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, timeout);
4975                 }
4976                 continue;
4977         }
4978 }
4979
4980 static void
4981 __mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
4982 {
4983         mm_player_t* player = (mm_player_t*)data;
4984         MMPLAYER_FENTER();
4985         MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
4986
4987         /* send prerolled pkt */
4988         player->video_stream_prerolled = FALSE;
4989
4990         __mmplayer_video_stream_decoded_render_cb(object, buffer, pad, data);
4991
4992         /* not to send prerolled pkt again */
4993         player->video_stream_prerolled = TRUE;
4994 }
4995
4996 static void
4997 __mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
4998 {
4999         mm_player_t* player = (mm_player_t*)data;
5000         GstCaps *caps = NULL;
5001         MMPlayerVideoStreamDataType *stream = NULL;
5002         MMVideoBuffer *video_buffer = NULL;
5003         GstMemory *dataBlock = NULL;
5004         GstMemory *metaBlock = NULL;
5005         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5006         GstStructure *structure = NULL;
5007         const gchar *string_format = NULL;
5008         unsigned int fourcc = 0;
5009
5010         MMPLAYER_FENTER();
5011         MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
5012
5013         if (player->video_stream_prerolled) {
5014                 player->video_stream_prerolled = FALSE;
5015                 LOGD("skip the prerolled pkt not to send it again");
5016                 return;
5017         }
5018
5019         caps = gst_pad_get_current_caps(pad);
5020         if (caps == NULL) {
5021                 LOGE("Caps is NULL.");
5022                 return;
5023         }
5024
5025         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
5026
5027         /* clear stream data structure */
5028         stream = (MMPlayerVideoStreamDataType *)g_malloc0(sizeof(MMPlayerVideoStreamDataType));
5029         if (!stream) {
5030                 LOGE("failed to alloc mem for video data");
5031                 return;
5032         }
5033
5034         structure = gst_caps_get_structure(caps, 0);
5035         gst_structure_get_int(structure, "width", &(stream->width));
5036         gst_structure_get_int(structure, "height", &(stream->height));
5037         string_format = gst_structure_get_string(structure, "format");
5038         if (string_format)
5039                 fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
5040         stream->format = util_get_pixtype(fourcc);
5041         gst_caps_unref(caps);
5042         caps = NULL;
5043
5044         __mmplayer_get_video_angle(player, NULL, &stream->orientation);
5045
5046     /*
5047         LOGD("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
5048                 GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format);
5049     */
5050
5051         if (stream->width == 0 || stream->height == 0 || stream->format == MM_PIXEL_FORMAT_INVALID) {
5052                 LOGE("Wrong condition!!");
5053                 goto ERROR;
5054         }
5055
5056         /* set size and timestamp */
5057         dataBlock = gst_buffer_peek_memory(buffer, 0);
5058         stream->length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
5059         stream->timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/GST_MSECOND); /* nano sec -> mili sec */
5060
5061         /* check zero-copy */
5062         if (player->set_mode.video_zc &&
5063                 player->set_mode.media_packet_video_stream &&
5064                 gst_buffer_n_memory(buffer) > 1) {
5065                 metaBlock = gst_buffer_peek_memory(buffer, 1);
5066                 gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
5067                 video_buffer = (MMVideoBuffer *)mapinfo.data;
5068         }
5069
5070         if (video_buffer) { /* hw codec */
5071                 /* set tbm bo */
5072                 if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
5073                         int i = 0;
5074
5075                         /* copy pointer of tbm bo, stride, elevation */
5076                         while (i < MM_VIDEO_BUFFER_PLANE_MAX && video_buffer->handle.bo[i]) {
5077                                 stream->bo[i] = tbm_bo_ref(video_buffer->handle.bo[i]);
5078                                 i++;
5079                         }
5080                 } else {
5081                         LOGE("Not support video buffer format");
5082                         goto ERROR;
5083                 }
5084                 memcpy(stream->stride, video_buffer->stride_width,
5085                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5086                 memcpy(stream->elevation, video_buffer->stride_height,
5087                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5088
5089                 /* will be released, by calling _mm_player_video_stream_internal_buffer_unref() */
5090                 stream->internal_buffer = gst_buffer_ref(buffer);
5091         } else { /* sw codec */
5092                 int i = 0;
5093                 int j = 0;
5094                 int k = 0;
5095                 int ret = TBM_SURFACE_ERROR_NONE;
5096                 int src_stride[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
5097                 int src_offset[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
5098                 int size = 0;
5099                 unsigned char *src = NULL;
5100                 unsigned char *dest = NULL;
5101                 tbm_bo_handle thandle;
5102                 tbm_surface_h surface;
5103                 tbm_surface_info_s info;
5104                 gboolean gst_ret;
5105
5106                 gst_ret = gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
5107                 if (!gst_ret) {
5108                         LOGE("fail to gst_memory_map");
5109                         goto ERROR;
5110                 }
5111
5112
5113                 if (stream->format == MM_PIXEL_FORMAT_I420) {
5114                         surface = tbm_surface_create(stream->width, stream->height, TBM_FORMAT_YUV420);
5115
5116                         ret = tbm_surface_get_info(surface, &info);
5117
5118                         if (ret != TBM_SURFACE_ERROR_NONE) {
5119                                 tbm_surface_destroy(surface);
5120                                 goto ERROR;
5121                         }
5122                         tbm_surface_destroy(surface);
5123
5124                         src_stride[0] = GST_ROUND_UP_4(stream->width);
5125                         src_stride[1] = src_stride[2] = GST_ROUND_UP_4(stream->width>>1);
5126                         src_offset[1] = src_stride[0] * GST_ROUND_UP_2(stream->height);
5127                         src_offset[2] = src_offset[1] + (src_stride[1] * (GST_ROUND_UP_2(stream->height)>>1));
5128                         stream->stride[0] = info.planes[0].stride;
5129                         stream->elevation[0] = info.planes[0].size / info.planes[0].stride;
5130                         stream->stride[1] = info.planes[1].stride;
5131                         stream->elevation[1] = info.planes[1].size / info.planes[1].stride;
5132                         stream->stride[2] = info.planes[2].stride;
5133                         stream->elevation[2] = info.planes[2].size / info.planes[2].stride;
5134                         size = info.planes[0].size + info.planes[1].size + info.planes[2].size;
5135                 } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
5136                         stream->stride[0] = stream->width * 4;
5137                         stream->elevation[0] = stream->height;
5138                         size = stream->stride[0] * stream->height;
5139                 } else {
5140                         LOGE("Not support format %d", stream->format);
5141                         goto ERROR;
5142                 }
5143
5144                 stream->bo[0] = __mmplayer_video_stream_get_bo(player, size);
5145                 if (!stream->bo[0]) {
5146                         LOGE("Fail to tbm_bo_alloc!!");
5147                         goto ERROR;
5148                 }
5149
5150                 thandle = tbm_bo_map(stream->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
5151                 if (thandle.ptr && mapinfo.data) {
5152                         if (stream->format == MM_PIXEL_FORMAT_I420) {
5153                                 for (i = 0; i < 3; i++) {
5154                                         src = mapinfo.data + src_offset[i];
5155                                         dest = thandle.ptr + info.planes[i].offset;
5156
5157                                         if (i > 0) k = 1;
5158                                         for (j = 0; j < stream->height>>k; j++) {
5159                                                 memcpy(dest, src, stream->width>>k);
5160                                                 src += src_stride[i];
5161                                                 dest += stream->stride[i];
5162                                         }
5163                                 }
5164                         } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
5165                                 memcpy(thandle.ptr, mapinfo.data, size);
5166                         } else {
5167                                 LOGE("Not support format %d", stream->format);
5168                                 goto ERROR;
5169                         }
5170                 } else {
5171                         LOGE("data pointer is wrong. dest : %p, src : %p",
5172                                         thandle.ptr, mapinfo.data);
5173                         goto ERROR;
5174                 }
5175                 tbm_bo_unmap(stream->bo[0]);
5176         }
5177
5178         if (player->video_stream_cb) { /* This has been already checked at the entry */
5179                 if (!player->video_stream_cb(stream, player->video_stream_cb_user_param)) {
5180                         LOGE("failed to send video stream data.");
5181                         goto ERROR;
5182                 }
5183         }
5184
5185         if (metaBlock)
5186                 gst_memory_unmap(metaBlock, &mapinfo);
5187         else
5188                 gst_memory_unmap(dataBlock, &mapinfo);
5189
5190         return;
5191
5192 ERROR:
5193         LOGE("release video stream resource.");
5194         if (metaBlock) {
5195                 int i = 0;
5196                 for (i = 0 ; i < MM_VIDEO_BUFFER_PLANE_MAX ; i++) {
5197                         if (stream->bo[i])
5198                                 tbm_bo_unref(stream->bo[i]);
5199                 }
5200                 gst_memory_unmap(metaBlock, &mapinfo);
5201
5202                 /* unref gst buffer */
5203                 if (stream->internal_buffer)
5204                         gst_buffer_unref(stream->internal_buffer);
5205         } else if (dataBlock) {
5206                 if (stream->bo[0])
5207                         _mmplayer_video_stream_release_bo(player, stream->bo[0]);
5208                 gst_memory_unmap(dataBlock, &mapinfo);
5209         }
5210
5211         g_free(stream);
5212         return;
5213 }
5214
5215 static int
5216 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket)
5217 {
5218         gchar* video_csc = "videoconvert"; /* default colorspace converter */
5219         GList* element_bucket = NULL;
5220
5221         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5222
5223         MMPLAYER_FENTER();
5224
5225         if (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical)) {
5226                 LOGD("do not need to add video filters.");
5227                 return MM_ERROR_NONE;
5228         }
5229
5230         /* in case of sw codec except 360 playback,
5231          * if libav video decoder is selected, videoconvert is required to render the shm wl-buffer which support RGB only via tizenwlsink. */
5232         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5233         LOGD("using video converter: %s", video_csc);
5234
5235         /* set video rotator */
5236         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5237
5238         *bucket = element_bucket;
5239         MMPLAYER_FLEAVE();
5240         return MM_ERROR_NONE;
5241
5242 ERROR: /* refer MMPLAYER_CREATE_ELEMENT */
5243         g_list_free(element_bucket);
5244
5245         *bucket = NULL;
5246         MMPLAYER_FLEAVE();
5247         return MM_ERROR_PLAYER_INTERNAL;
5248 }
5249
5250 /**
5251  * This function is to create video pipeline.
5252  *
5253  * @param       player          [in]    handle of player
5254  *              caps            [in]    src caps of decoder
5255  *              surface_type    [in]    surface type for video rendering
5256  *
5257  * @return      This function returns zero on success.
5258  * @remark
5259  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5260  */
5261 /**
5262   * VIDEO PIPELINE
5263   * - video overlay surface(arm/x86) : tizenwlsink
5264   */
5265 static int
5266 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5267 {
5268         GstPad *pad = NULL;
5269         MMHandleType attrs;
5270         GList*element_bucket = NULL;
5271         MMPlayerGstElement* first_element = NULL;
5272         MMPlayerGstElement* videobin = NULL;
5273         gchar *videosink_element = NULL;
5274
5275         MMPLAYER_FENTER();
5276
5277         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5278
5279         /* alloc handles */
5280         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5281         if (!videobin)
5282                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5283
5284         player->pipeline->videobin = videobin;
5285
5286         attrs = MMPLAYER_GET_ATTRS(player);
5287         if (!attrs) {
5288                 LOGE("cannot get content attribute");
5289                 return MM_ERROR_PLAYER_INTERNAL;
5290         }
5291
5292         /* create bin */
5293         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
5294         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
5295         if (!videobin[MMPLAYER_V_BIN].gst) {
5296                 LOGE("failed to create videobin");
5297                 goto ERROR;
5298         }
5299
5300         int enable_video_decoded_cb = 0;
5301         mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable_video_decoded_cb);
5302
5303         if (player->is_360_feature_enabled && player->is_content_spherical) {
5304                 LOGD("video360 elem will be added.");
5305
5306                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_360, "video360",
5307                                 "video-360", TRUE, player);
5308
5309                 /* Set spatial media metadata and/or user settings to the element.
5310                  * */
5311                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5312                                 "projection-type", player->video360_metadata.projection_type, NULL);
5313
5314                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5315                                 "stereo-mode", player->video360_metadata.stereo_mode, NULL);
5316
5317                 if (player->video360_metadata.full_pano_width_pixels &&
5318                                 player->video360_metadata.full_pano_height_pixels &&
5319                                 player->video360_metadata.cropped_area_image_width &&
5320                                 player->video360_metadata.cropped_area_image_height) {
5321                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5322                                         "projection-bounds-top", player->video360_metadata.cropped_area_top,
5323                                         "projection-bounds-bottom", player->video360_metadata.full_pano_height_pixels -
5324                                                         player->video360_metadata.cropped_area_top - player->video360_metadata.cropped_area_image_height,
5325                                         "projection-bounds-left", player->video360_metadata.cropped_area_left,
5326                                         "projection-bounds-right", player->video360_metadata.full_pano_width_pixels -
5327                                                         player->video360_metadata.cropped_area_left - player->video360_metadata.cropped_area_image_width,
5328                                         NULL);
5329                 }
5330
5331                 if (player->video360_horizontal_fov && player->video360_vertical_fov) {
5332                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5333                                         "horizontal-fov", player->video360_horizontal_fov,
5334                                         "vertical-fov", player->video360_vertical_fov, NULL);
5335                 }
5336
5337                 if (player->video360_zoom <= VIDEO360_MAX_ZOOM && player->video360_zoom > 1.0f) {
5338                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5339                                         "zoom", 1.0f / player->video360_zoom, NULL);
5340                 }
5341
5342                 if (player->video360_yaw_radians <= M_PI &&
5343                                 player->video360_yaw_radians >= -M_PI &&
5344                                 player->video360_pitch_radians <= M_PI_2 &&
5345                                 player->video360_pitch_radians >= -M_PI_2) {
5346                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5347                                         "pose-yaw", (int) (player->video360_yaw_radians * 180.0 / M_PI),
5348                                         "pose-pitch", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
5349                 } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
5350                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5351                                         "pose-yaw", player->video360_metadata.init_view_heading,
5352                                         "pose-pitch", player->video360_metadata.init_view_pitch, NULL);
5353                 }
5354
5355                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5356                                 "passthrough", !player->is_video360_enabled, NULL);
5357         }
5358
5359         /* set video sink */
5360         switch (surface_type) {
5361         case MM_DISPLAY_SURFACE_OVERLAY:
5362                 if (__mmplayer_gst_create_video_filters(player, &element_bucket) != MM_ERROR_NONE)
5363                         goto ERROR;
5364                 if (strlen(player->ini.videosink_element_overlay) > 0)
5365                         videosink_element = player->ini.videosink_element_overlay;
5366                 else
5367                         goto ERROR;
5368                 break;
5369         case MM_DISPLAY_SURFACE_NULL:
5370                 if (strlen(player->ini.videosink_element_fake) > 0)
5371                         videosink_element = player->ini.videosink_element_fake;
5372                 else
5373                         goto ERROR;
5374                 break;
5375         case MM_DISPLAY_SURFACE_REMOTE:
5376                 if (strlen(player->ini.videosink_element_fake) > 0)
5377                         videosink_element = player->ini.videosink_element_fake;
5378                 else
5379                         goto ERROR;
5380                 break;
5381         default:
5382                 LOGE("unidentified surface type");
5383                 goto ERROR;
5384         }
5385         LOGD("surface_type %d, selected videosink name: %s", surface_type, videosink_element);
5386
5387         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, "videosink", TRUE, player);
5388
5389         /* additional setting for sink plug-in */
5390         switch (surface_type) {
5391         case MM_DISPLAY_SURFACE_OVERLAY:
5392         {
5393                 bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical));
5394                 if (!use_tbm) {
5395                         LOGD("selected videosink name: %s", videosink_element);
5396
5397                         /* support shard memory with S/W codec on HawkP */
5398                         if (strncmp(videosink_element, "tizenwlsink", strlen(videosink_element)) == 0) {
5399                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5400                                         "use-tbm", use_tbm, NULL);
5401                         }
5402                 } else {
5403                         if (attrs) {
5404                                 int gapless = 0;
5405
5406                                 mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
5407
5408                                 if (gapless > 0) {
5409                                         LOGD("disable last-sample");
5410                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
5411                                 }
5412                         }
5413                 }
5414                 if (player->set_mode.media_packet_video_stream) {
5415                         int enable = 0;
5416                         mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable);
5417                         if (enable)
5418                                 g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "signal-handoffs", TRUE, NULL);
5419
5420                         MMPLAYER_SIGNAL_CONNECT(player,
5421                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5422                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5423                                                                         "handoff",
5424                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
5425                                                                         (gpointer)player);
5426
5427                         MMPLAYER_SIGNAL_CONNECT(player,
5428                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5429                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5430                                                                         "preroll-handoff",
5431                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
5432                                                                         (gpointer)player);
5433                 }
5434                 break;
5435         }
5436         case MM_DISPLAY_SURFACE_REMOTE:
5437         {
5438                 if (player->set_mode.media_packet_video_stream) {
5439                         LOGE("add data probe at videosink");
5440                         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5441                                                                                         "sync", TRUE, "signal-handoffs", TRUE, NULL);
5442
5443                         MMPLAYER_SIGNAL_CONNECT(player,
5444                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5445                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5446                                                                         "handoff",
5447                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
5448                                                                         (gpointer)player);
5449
5450                         MMPLAYER_SIGNAL_CONNECT(player,
5451                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5452                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5453                                                                         "preroll-handoff",
5454                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
5455                                                                         (gpointer)player);
5456                         if (attrs) {
5457                                 int gapless = 0;
5458
5459                                 mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
5460
5461                                 if (gapless > 0) {
5462                                         LOGD("disable last-sample");
5463                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
5464                                 }
5465                         }
5466                 }
5467                 break;
5468         }
5469         default:
5470                 break;
5471         }
5472
5473         if (_mmplayer_update_video_param(player, "update_all_param") != MM_ERROR_NONE)
5474                 goto ERROR;
5475
5476         if (videobin[MMPLAYER_V_SINK].gst) {
5477                 GstPad *sink_pad = NULL;
5478                 sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
5479                 if (sink_pad) {
5480                         MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5481                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
5482                         gst_object_unref(GST_OBJECT(sink_pad));
5483                 } else
5484                         LOGW("failed to get sink pad from videosink\n");
5485         }
5486
5487         /* store it as it's sink element */
5488         __mmplayer_add_sink(player, videobin[MMPLAYER_V_SINK].gst);
5489
5490         /* adding created elements to bin */
5491         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket)) {
5492                 LOGE("failed to add elements\n");
5493                 goto ERROR;
5494         }
5495
5496         /* Linking elements in the bucket by added order */
5497         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
5498                 LOGE("failed to link elements\n");
5499                 goto ERROR;
5500         }
5501
5502         /* get first element's sinkpad for creating ghostpad */
5503         if (element_bucket)
5504                 first_element = (MMPlayerGstElement *)element_bucket->data;
5505         if (!first_element) {
5506                 LOGE("failed to get first element from bucket\n");
5507                 goto ERROR;
5508         }
5509
5510         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5511         if (!pad) {
5512                 LOGE("failed to get pad from first element\n");
5513                 goto ERROR;
5514         }
5515
5516         /* create ghostpad */
5517         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
5518         if (FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
5519                 LOGE("failed to add ghostpad to videobin\n");
5520                 goto ERROR;
5521         }
5522         gst_object_unref(pad);
5523
5524         /* done. free allocated variables */
5525         if (element_bucket)
5526                 g_list_free(element_bucket);
5527
5528         MMPLAYER_FLEAVE();
5529
5530         return MM_ERROR_NONE;
5531
5532 ERROR:
5533         LOGE("ERROR : releasing videobin\n");
5534
5535         g_list_free(element_bucket);
5536
5537         if (pad)
5538                 gst_object_unref(GST_OBJECT(pad));
5539
5540         /* release videobin with it's childs */
5541         if (videobin[MMPLAYER_V_BIN].gst)
5542                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
5543
5544
5545         MMPLAYER_FREEIF(videobin);
5546
5547         player->pipeline->videobin = NULL;
5548
5549         return MM_ERROR_PLAYER_INTERNAL;
5550 }
5551
5552 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
5553 {
5554         GList *element_bucket = NULL;
5555         MMPlayerGstElement *textbin = player->pipeline->textbin;
5556
5557         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", TRUE, player);
5558         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", TRUE, player);
5559         g_object_set(G_OBJECT(textbin[MMPLAYER_T_IDENTITY].gst),
5560                                                         "signal-handoffs", FALSE,
5561                                                         NULL);
5562
5563         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
5564         MMPLAYER_SIGNAL_CONNECT(player,
5565                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
5566                                                         MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
5567                                                         "handoff",
5568                                                         G_CALLBACK(__mmplayer_update_subtitle),
5569                                                         (gpointer)player);
5570
5571         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
5572         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
5573         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
5574
5575         if (!player->play_subtitle) {
5576                 LOGD("add textbin sink as sink element of whole pipeline.\n");
5577                 __mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
5578         }
5579
5580         /* adding created elements to bin */
5581         LOGD("adding created elements to bin\n");
5582         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) {
5583                 LOGE("failed to add elements\n");
5584                 goto ERROR;
5585         }
5586
5587         /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
5588         GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
5589         GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
5590
5591         /* linking elements in the bucket by added order. */
5592         LOGD("Linking elements in the bucket by added order.\n");
5593         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
5594                 LOGE("failed to link elements\n");
5595                 goto ERROR;
5596         }
5597
5598         /* done. free allocated variables */
5599         g_list_free(element_bucket);
5600
5601         if (textbin[MMPLAYER_T_QUEUE].gst) {
5602                 GstPad *pad = NULL;
5603                 GstPad *ghostpad = NULL;
5604
5605                 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_QUEUE].gst), "sink");
5606                 if (!pad) {
5607                         LOGE("failed to get sink pad of text queue");
5608                         goto ERROR;
5609                 }
5610
5611                 ghostpad = gst_ghost_pad_new("text_sink", pad);
5612                 gst_object_unref(pad);
5613
5614                 if (!ghostpad) {
5615                         LOGE("failed to create ghostpad of textbin\n");
5616                         goto ERROR;
5617                 }
5618
5619                 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad)) {
5620                         LOGE("failed to add ghostpad to textbin\n");
5621                         gst_object_unref(ghostpad);
5622                         goto ERROR;
5623                 }
5624         }
5625
5626         return MM_ERROR_NONE;
5627
5628 ERROR:
5629         g_list_free(element_bucket);
5630
5631         if (!player->play_subtitle && textbin[MMPLAYER_T_FAKE_SINK].gst) {
5632                 LOGE("remove textbin sink from sink list");
5633                 __mmplayer_del_sink(player, textbin[MMPLAYER_T_FAKE_SINK].gst);
5634         }
5635
5636         /* release element at __mmplayer_gst_create_text_sink_bin */
5637         return MM_ERROR_PLAYER_INTERNAL;
5638 }
5639
5640 static int __mmplayer_gst_create_text_sink_bin(mm_player_t* player)
5641 {
5642         MMPlayerGstElement *textbin = NULL;
5643         GList *element_bucket = NULL;
5644         int surface_type = 0;
5645         gint i = 0;
5646
5647         MMPLAYER_FENTER();
5648
5649         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5650
5651         /* alloc handles */
5652         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
5653         if (!textbin) {
5654                 LOGE("failed to allocate memory for textbin\n");
5655                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5656         }
5657
5658         /* create bin */
5659         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
5660         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
5661         if (!textbin[MMPLAYER_T_BIN].gst) {
5662                 LOGE("failed to create textbin\n");
5663                 goto ERROR;
5664         }
5665
5666         /* take it */
5667         player->pipeline->textbin = textbin;
5668
5669         /* fakesink */
5670         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
5671         LOGD("surface type for subtitle : %d", surface_type);
5672         switch (surface_type) {
5673         case MM_DISPLAY_SURFACE_OVERLAY:
5674         case MM_DISPLAY_SURFACE_NULL:
5675         case MM_DISPLAY_SURFACE_REMOTE:
5676                 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE) {
5677                         LOGE("failed to make plain text elements\n");
5678                         goto ERROR;
5679                 }
5680                 break;
5681         default:
5682                 goto ERROR;
5683                 break;
5684         }
5685
5686         MMPLAYER_FLEAVE();
5687
5688         return MM_ERROR_NONE;
5689
5690 ERROR:
5691
5692         LOGD("ERROR : releasing textbin\n");
5693
5694         g_list_free(element_bucket);
5695
5696         /* release signal */
5697         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
5698
5699         /* release element which are not added to bin */
5700         for (i = 1; i < MMPLAYER_T_NUM; i++) {
5701                 /* NOTE : skip bin */
5702                 if (textbin[i].gst) {
5703                         GstObject* parent = NULL;
5704                         parent = gst_element_get_parent(textbin[i].gst);
5705
5706                         if (!parent) {
5707                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
5708                                 textbin[i].gst = NULL;
5709                         } else {
5710                                 gst_object_unref(GST_OBJECT(parent));
5711                         }
5712                 }
5713         }
5714
5715         /* release textbin with it's childs */
5716         if (textbin[MMPLAYER_T_BIN].gst)
5717                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
5718
5719         MMPLAYER_FREEIF(player->pipeline->textbin);
5720         player->pipeline->textbin = NULL;
5721
5722         MMPLAYER_FLEAVE();
5723         return MM_ERROR_PLAYER_INTERNAL;
5724 }
5725
5726
5727 static int
5728 __mmplayer_gst_create_text_pipeline(mm_player_t* player)
5729 {
5730         MMPlayerGstElement* mainbin = NULL;
5731         MMPlayerGstElement* textbin = NULL;
5732         MMHandleType attrs = 0;
5733         GstElement *subsrc = NULL;
5734         GstElement *subparse = NULL;
5735         gchar *subtitle_uri = NULL;
5736         const gchar *charset = NULL;
5737         GstPad *pad = NULL;
5738
5739         MMPLAYER_FENTER();
5740
5741         /* get mainbin */
5742         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
5743                                                                 player->pipeline &&
5744                                                                 player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5745
5746         mainbin = player->pipeline->mainbin;
5747
5748         attrs = MMPLAYER_GET_ATTRS(player);
5749         if (!attrs) {
5750                 LOGE("cannot get content attribute\n");
5751                 return MM_ERROR_PLAYER_INTERNAL;
5752         }
5753
5754         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
5755         if (!subtitle_uri || strlen(subtitle_uri) < 1) {
5756                 LOGE("subtitle uri is not proper filepath.\n");
5757                 return MM_ERROR_PLAYER_INVALID_URI;
5758         }
5759
5760         if (!util_get_storage_info(subtitle_uri, &player->storage_info[MMPLAYER_PATH_TEXT])) {
5761                 LOGE("failed to get storage info of subtitle path");
5762                 return MM_ERROR_PLAYER_INVALID_URI;
5763         }
5764
5765         SECURE_LOGD("subtitle file path is [%s].\n", subtitle_uri);
5766
5767         MMPLAYER_SUBTITLE_INFO_LOCK(player);
5768         player->subtitle_language_list = NULL;
5769         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
5770
5771         /* create the subtitle source */
5772         subsrc = gst_element_factory_make("filesrc", "subtitle_source");
5773         if (!subsrc) {
5774                 LOGE("failed to create filesrc element\n");
5775                 goto ERROR;
5776         }
5777         g_object_set(G_OBJECT(subsrc), "location", subtitle_uri, NULL);
5778
5779         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
5780         mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
5781
5782         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc)) {
5783                 LOGW("failed to add queue\n");
5784                 gst_object_unref(mainbin[MMPLAYER_M_SUBSRC].gst);
5785                 mainbin[MMPLAYER_M_SUBSRC].gst = NULL;
5786                 mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_NUM;
5787                 goto ERROR;
5788         }
5789
5790         /* subparse */
5791         subparse = gst_element_factory_make("subparse", "subtitle_parser");
5792         if (!subparse) {
5793                 LOGE("failed to create subparse element\n");
5794                 goto ERROR;
5795         }
5796
5797         charset = util_get_charset(subtitle_uri);
5798         if (charset) {
5799                 LOGD("detected charset is %s\n", charset);
5800                 g_object_set(G_OBJECT(subparse), "subtitle-encoding", charset, NULL);
5801         }
5802
5803         mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE;
5804         mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
5805
5806         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse)) {
5807                 LOGW("failed to add subparse\n");
5808                 gst_object_unref(mainbin[MMPLAYER_M_SUBPARSE].gst);
5809                 mainbin[MMPLAYER_M_SUBPARSE].gst = NULL;
5810                 mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_NUM;
5811                 goto ERROR;
5812         }
5813
5814         if (!gst_element_link_pads(subsrc, "src", subparse, "sink")) {
5815                 LOGW("failed to link subsrc and subparse\n");
5816                 goto ERROR;
5817         }
5818
5819         player->play_subtitle = TRUE;
5820         player->adjust_subtitle_pos = 0;
5821
5822         LOGD("play subtitle using subtitle file\n");
5823
5824         if (player->pipeline->textbin == NULL) {
5825                 if (MM_ERROR_NONE != __mmplayer_gst_create_text_sink_bin(player)) {
5826                         LOGE("failed to create text sink bin. continuing without text\n");
5827                         goto ERROR;
5828                 }
5829
5830                 textbin = player->pipeline->textbin;
5831
5832                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(textbin[MMPLAYER_T_BIN].gst))) {
5833                         LOGW("failed to add textbin\n");
5834
5835                         /* release signal */
5836                         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
5837
5838                         /* release textbin with it's childs */
5839                         gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
5840                         MMPLAYER_FREEIF(player->pipeline->textbin);
5841                         player->pipeline->textbin = textbin = NULL;
5842                         goto ERROR;
5843                 }
5844
5845                 LOGD("link text input selector and textbin ghost pad");
5846
5847                 player->textsink_linked = 1;
5848                 player->external_text_idx = 0;
5849                 LOGI("player->textsink_linked set to 1\n");
5850         } else {
5851                 textbin = player->pipeline->textbin;
5852                 LOGD("text bin has been created. reuse it.");
5853                 player->external_text_idx = 1;
5854         }
5855
5856         if (!gst_element_link_pads(subparse, "src", textbin[MMPLAYER_T_BIN].gst, "text_sink")) {
5857                 LOGW("failed to link subparse and textbin\n");
5858                 goto ERROR;
5859         }
5860
5861         pad = gst_element_get_static_pad(textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
5862         if (!pad) {
5863                 LOGE("failed to get sink pad from textsink to probe data");
5864                 goto ERROR;
5865         }
5866
5867         gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
5868                                 __mmplayer_subtitle_adjust_position_probe, player, NULL);
5869
5870         gst_object_unref(pad);
5871         pad = NULL;
5872
5873         /* create dot. for debugging */
5874         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-with-subtitle");
5875         MMPLAYER_FLEAVE();
5876
5877         return MM_ERROR_NONE;
5878
5879 ERROR:
5880         /* release text pipeline resource */
5881         player->textsink_linked = 0;
5882
5883         /* release signal */
5884         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
5885
5886         if (player->pipeline->textbin) {
5887                 LOGE("remove textbin");
5888
5889                 /* release textbin with it's childs */
5890                 MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN);
5891                 MMPLAYER_FREEIF(player->pipeline->textbin);
5892                 player->pipeline->textbin = NULL;
5893
5894         }
5895
5896         /* release subtitle elem */
5897         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBSRC);
5898         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBPARSE);
5899
5900         return MM_ERROR_PLAYER_INTERNAL;
5901 }
5902
5903 gboolean
5904 __mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5905 {
5906         mm_player_t* player = (mm_player_t*) data;
5907         MMMessageParamType msg = {0, };
5908         GstClockTime duration = 0;
5909         gpointer text = NULL;
5910         guint text_size = 0;
5911         gboolean ret = TRUE;
5912         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5913
5914         MMPLAYER_FENTER();
5915
5916         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
5917         MMPLAYER_RETURN_VAL_IF_FAIL(buffer, FALSE);
5918
5919         if (player->is_subtitle_force_drop) {
5920                 LOGW("subtitle is dropped forcedly.");
5921                 return ret;
5922         }
5923
5924         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
5925         text = mapinfo.data;
5926         text_size = mapinfo.size;
5927         duration = GST_BUFFER_DURATION(buffer);
5928
5929         if (player->set_mode.subtitle_off) {
5930                 LOGD("subtitle is OFF.\n");
5931                 return TRUE;
5932         }
5933
5934         if (!text || (text_size == 0)) {
5935                 LOGD("There is no subtitle to be displayed.\n");
5936                 return TRUE;
5937         }
5938
5939         msg.data = (void *) text;
5940         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
5941
5942         LOGD("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data);
5943
5944         MMPLAYER_POST_MSG(player, MM_MESSAGE_UPDATE_SUBTITLE, &msg);
5945         gst_buffer_unmap(buffer, &mapinfo);
5946
5947         MMPLAYER_FLEAVE();
5948
5949         return ret;
5950 }
5951
5952 static GstPadProbeReturn
5953 __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
5954 {
5955         mm_player_t *player = (mm_player_t *) u_data;
5956         GstClockTime cur_timestamp = 0;
5957         gint64 adjusted_timestamp = 0;
5958         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
5959
5960         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
5961
5962         if (player->set_mode.subtitle_off) {
5963                 LOGD("subtitle is OFF.\n");
5964                 return TRUE;
5965         }
5966
5967         if (player->adjust_subtitle_pos == 0) {
5968                 LOGD("nothing to do");
5969                 return TRUE;
5970         }
5971
5972         cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
5973         adjusted_timestamp = (gint64) cur_timestamp +((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
5974
5975         if (adjusted_timestamp < 0) {
5976                 LOGD("adjusted_timestamp under zero");
5977                 MMPLAYER_FLEAVE();
5978                 return FALSE;
5979         }
5980
5981         GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
5982         LOGD("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
5983                                 GST_TIME_ARGS(cur_timestamp),
5984                                 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
5985
5986         return GST_PAD_PROBE_OK;
5987 }
5988 static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
5989 {
5990         MMPLAYER_FENTER();
5991
5992         /* check player and subtitlebin are created */
5993         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5994         MMPLAYER_RETURN_VAL_IF_FAIL(player->play_subtitle, MM_ERROR_NOT_SUPPORT_API);
5995
5996         if (position == 0) {
5997                 LOGD("nothing to do\n");
5998                 MMPLAYER_FLEAVE();
5999                 return MM_ERROR_NONE;
6000         }
6001
6002         switch (format) {
6003         case MM_PLAYER_POS_FORMAT_TIME:
6004                 {
6005                         /* check current postion */
6006                         player->adjust_subtitle_pos = position;
6007
6008                         LOGD("save adjust_subtitle_pos in player") ;
6009                 }
6010                 break;
6011
6012         default:
6013                 {
6014                         LOGW("invalid format.\n");
6015                         MMPLAYER_FLEAVE();
6016                         return MM_ERROR_INVALID_ARGUMENT;
6017                 }
6018         }
6019
6020         MMPLAYER_FLEAVE();
6021
6022         return MM_ERROR_NONE;
6023 }
6024
6025 static void
6026 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data)
6027 {
6028         GstElement *appsrc = element;
6029         MMPlayerInputBuffer *buf = (MMPlayerInputBuffer *)user_data;
6030         GstBuffer *buffer = NULL;
6031         GstFlowReturn ret = GST_FLOW_OK;
6032         gint len = size;
6033
6034         MMPLAYER_RETURN_IF_FAIL(element);
6035         MMPLAYER_RETURN_IF_FAIL(buf);
6036
6037         buffer = gst_buffer_new();
6038
6039         if (buf->offset >= buf->len) {
6040                 LOGD("call eos appsrc\n");
6041                 g_signal_emit_by_name(appsrc, "end-of-stream", &ret);
6042                 return;
6043         }
6044
6045         if (buf->len - buf->offset < size)
6046                 len = buf->len - buf->offset;
6047
6048         gst_buffer_insert_memory(buffer, -1, gst_memory_new_wrapped(0, (guint8 *)(buf->buf + buf->offset), len, 0, len, NULL, NULL));
6049         GST_BUFFER_OFFSET(buffer) = (guint64)buf->offset;
6050         GST_BUFFER_OFFSET_END(buffer) = (guint64)(buf->offset + len);
6051
6052         //LOGD("feed buffer %p, offset %u-%u length %u", buffer, buf->offset, (buf->offset+len), len);
6053         g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
6054
6055         buf->offset += len;
6056 }
6057
6058 static gboolean
6059 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data)
6060 {
6061         MMPlayerInputBuffer *buf = (MMPlayerInputBuffer *)user_data;
6062
6063         MMPLAYER_RETURN_VAL_IF_FAIL(buf, FALSE);
6064
6065         buf->offset  = (int)size;
6066
6067         return TRUE;
6068 }
6069
6070 static GstBusSyncReply
6071 __mmplayer_bus_sync_callback(GstBus * bus, GstMessage * message, gpointer data)
6072 {
6073         mm_player_t *player = (mm_player_t *)data;
6074         GstBusSyncReply reply = GST_BUS_DROP;
6075
6076         if (!(player->pipeline && player->pipeline->mainbin)) {
6077                 LOGE("player pipeline handle is null");
6078                 return GST_BUS_PASS;
6079         }
6080
6081         if (!__mmplayer_check_useful_message(player, message)) {
6082                 gst_message_unref(message);
6083                 return GST_BUS_DROP;
6084         }
6085
6086         switch (GST_MESSAGE_TYPE(message)) {
6087         case GST_MESSAGE_STATE_CHANGED:
6088                 /* post directly for fast launch */
6089                 if (player->sync_handler) {
6090                         __mmplayer_gst_callback(message, player);
6091                         reply = GST_BUS_DROP;
6092                 } else
6093                         reply = GST_BUS_PASS;
6094                 break;
6095         case GST_MESSAGE_TAG:
6096                 __mmplayer_gst_extract_tag_from_msg(player, message);
6097
6098                 #if 0 // debug
6099                 {
6100                         GstTagList *tags = NULL;
6101
6102                         gst_message_parse_tag(message, &tags);
6103                         if (tags) {
6104                                 LOGE("TAGS received from element \"%s\".\n",
6105                                 GST_STR_NULL(GST_ELEMENT_NAME(GST_MESSAGE_SRC(message))));
6106
6107                                 gst_tag_list_foreach(tags, print_tag, NULL);
6108                                 gst_tag_list_free(tags);
6109                                 tags = NULL;
6110                         }
6111                         break;
6112                 }
6113                 #endif
6114                 break;
6115
6116         case GST_MESSAGE_DURATION_CHANGED:
6117                 __mmplayer_gst_handle_duration(player, message);
6118                 break;
6119         case GST_MESSAGE_ASYNC_DONE:
6120                 /* NOTE:Don't call gst_callback directly
6121                  * because previous frame can be showed even though this message is received for seek.
6122                  */
6123         default:
6124                 reply = GST_BUS_PASS;
6125                 break;
6126         }
6127
6128         if (reply == GST_BUS_DROP)
6129                 gst_message_unref(message);
6130
6131         return reply;
6132 }
6133
6134 static gboolean
6135 __mmplayer_gst_create_decoder(mm_player_t *player,
6136                                                                 MMPlayerTrackType track,
6137                                                                 GstPad* srcpad,
6138                                                                 enum MainElementID elemId,
6139                                                                 const gchar* name)
6140 {
6141         gboolean ret = TRUE;
6142         GstPad *sinkpad = NULL;
6143
6144         MMPLAYER_FENTER();
6145
6146         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
6147                                                 player->pipeline &&
6148                                                 player->pipeline->mainbin, FALSE);
6149         MMPLAYER_RETURN_VAL_IF_FAIL((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE);
6150         MMPLAYER_RETURN_VAL_IF_FAIL(srcpad, FALSE);
6151         MMPLAYER_RETURN_VAL_IF_FAIL((player->pipeline->mainbin[elemId].gst == NULL), FALSE);
6152
6153         GstElement *decodebin = NULL;
6154         GstCaps *dec_caps = NULL;
6155
6156         /* create decodebin */
6157         decodebin = gst_element_factory_make("decodebin", name);
6158
6159         if (!decodebin) {
6160                 LOGE("error : fail to create decodebin for %d decoder\n", track);
6161                 ret = FALSE;
6162                 goto ERROR;
6163         }
6164
6165         /* raw pad handling signal */
6166         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6167                                                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
6168
6169         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
6170         before looking for any elements that can handle that stream.*/
6171         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
6172                                                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
6173
6174         /* This signal is emitted when a element is added to the bin.*/
6175         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
6176                                                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
6177
6178         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
6179                 LOGE("failed to add new decodebin\n");
6180                 ret = FALSE;
6181                 goto ERROR;
6182         }
6183
6184         dec_caps = gst_pad_query_caps(srcpad, NULL);
6185         if (dec_caps) {
6186                 //LOGD("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
6187                 g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
6188                 gst_caps_unref(dec_caps);
6189         }
6190
6191         player->pipeline->mainbin[elemId].id = elemId;
6192         player->pipeline->mainbin[elemId].gst = decodebin;
6193
6194         sinkpad = gst_element_get_static_pad(decodebin, "sink");
6195
6196         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
6197                 LOGW("failed to link [%s:%s] to decoder\n", GST_DEBUG_PAD_NAME(srcpad));
6198                 gst_object_unref(GST_OBJECT(decodebin));
6199         }
6200
6201         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin))
6202                 LOGE("failed to sync second level decodebin state with parent\n");
6203
6204         LOGD("Total num of %d tracks = %d \n", track, player->selector[track].total_track_num);
6205
6206 ERROR:
6207         if (sinkpad) {
6208                 gst_object_unref(GST_OBJECT(sinkpad));
6209                 sinkpad = NULL;
6210         }
6211         MMPLAYER_FLEAVE();
6212
6213         return ret;
6214 }
6215
6216 /**
6217  * This function is to create  audio or video pipeline for playing.
6218  *
6219  * @param       player          [in]    handle of player
6220  *
6221  * @return      This function returns zero on success.
6222  * @remark
6223  * @see
6224  */
6225 static int
6226 __mmplayer_gst_create_pipeline(mm_player_t* player)
6227 {
6228         GstBus  *bus = NULL;
6229         MMPlayerGstElement *mainbin = NULL;
6230         MMHandleType attrs = 0;
6231         GstElement* element = NULL;
6232         GstElement* elem_src_audio = NULL;
6233         GstElement* elem_src_subtitle = NULL;
6234         GstElement* es_video_queue = NULL;
6235         GstElement* es_audio_queue = NULL;
6236         GstElement* es_subtitle_queue = NULL;
6237         GList* element_bucket = NULL;
6238         gboolean need_state_holder = TRUE;
6239         gint i = 0;
6240 #ifdef SW_CODEC_ONLY
6241         int surface_type = 0;
6242 #endif
6243         MMPLAYER_FENTER();
6244
6245         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6246
6247         /* get profile attribute */
6248         attrs = MMPLAYER_GET_ATTRS(player);
6249         if (!attrs) {
6250                 LOGE("cannot get content attribute\n");
6251                 goto INIT_ERROR;
6252         }
6253
6254         /* create pipeline handles */
6255         if (player->pipeline) {
6256                 LOGW("pipeline should be released before create new one\n");
6257                 goto INIT_ERROR;
6258         }
6259
6260         player->video360_metadata.is_spherical = -1;
6261         player->is_openal_plugin_used = FALSE;
6262
6263         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0(sizeof(MMPlayerGstPipelineInfo));
6264         if (player->pipeline == NULL)
6265                 goto INIT_ERROR;
6266
6267         memset(player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo)); /* g_malloc0 did this job already */
6268
6269         /* create mainbin */
6270         mainbin = (MMPlayerGstElement*) g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
6271         if (mainbin == NULL)
6272                 goto INIT_ERROR;
6273
6274         memset(mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM); /* g_malloc0 did this job already */
6275
6276         /* create pipeline */
6277         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
6278         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
6279         if (!mainbin[MMPLAYER_M_PIPE].gst) {
6280                 LOGE("failed to create pipeline\n");
6281                 goto INIT_ERROR;
6282         }
6283         player->demux_pad_index = 0;
6284         player->subtitle_language_list = NULL;
6285
6286         player->is_subtitle_force_drop = FALSE;
6287         player->last_multiwin_status = FALSE;
6288
6289         _mmplayer_track_initialize(player);
6290         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
6291
6292         /* create source element */
6293         switch (player->profile.uri_type) {
6294         /* rtsp streamming */
6295         case MM_PLAYER_URI_TYPE_URL_RTSP:
6296                 {
6297                         gchar *user_agent;
6298
6299                         element = gst_element_factory_make("rtspsrc", "rtsp source");
6300
6301                         if (!element) {
6302                                 LOGE("failed to create streaming source element\n");
6303                                 break;
6304                         }
6305
6306                         /* make it zero */
6307                         user_agent = NULL;
6308
6309                         /* get attribute */
6310                         mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
6311
6312                         SECURE_LOGD("user_agent : %s\n", user_agent);
6313
6314                         /* setting property to streaming source */
6315                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6316                         if (user_agent)
6317                                 g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6318
6319                         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6320                                 G_CALLBACK(__mmplayer_gst_rtp_dynamic_pad), player);
6321                         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
6322                                 G_CALLBACK(__mmplayer_gst_rtp_no_more_pads), player);
6323                 }
6324                 break;
6325
6326         /* http streaming*/
6327         case MM_PLAYER_URI_TYPE_URL_HTTP:
6328                 {
6329                         gchar *user_agent, *cookies, **cookie_list;
6330                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6331                         user_agent = cookies = NULL;
6332                         cookie_list = NULL;
6333                         gint mode = MM_PLAYER_PD_MODE_NONE;
6334
6335                         mm_attrs_get_int_by_name(attrs, "pd_mode", &mode);
6336
6337                         player->pd_mode = mode;
6338
6339                         LOGD("http playback, PD mode : %d\n", player->pd_mode);
6340
6341                         if (!MMPLAYER_IS_HTTP_PD(player)) {
6342                                 element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
6343                                 if (!element) {
6344                                         LOGE("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
6345                                         break;
6346                                 }
6347                                 LOGD("using http streamming source [%s].\n", player->ini.httpsrc_element);
6348
6349                                 /* get attribute */
6350                                 mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
6351                                 mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
6352
6353                                 if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
6354                                         LOGD("get timeout from ini\n");
6355                                         http_timeout = player->ini.http_timeout;
6356                                 }
6357
6358                                 /* get attribute */
6359                                 SECURE_LOGD("location : %s\n", player->profile.uri);
6360                                 SECURE_LOGD("cookies : %s\n", cookies);
6361                                 SECURE_LOGD("user_agent :  %s\n",  user_agent);
6362                                 LOGD("timeout : %d\n",  http_timeout);
6363
6364                                 /* setting property to streaming source */
6365                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6366                                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6367                                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
6368
6369                                 /* parsing cookies */
6370                                 if ((cookie_list = util_get_cookie_list((const char*)cookies))) {
6371                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
6372                                         g_strfreev(cookie_list);
6373                                 }
6374                                 if (user_agent)
6375                                         g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6376
6377                                 if (MMPLAYER_URL_HAS_DASH_SUFFIX(player))
6378                                         LOGW("it's dash. and it's still experimental feature.");
6379                         } else {
6380                                 // progressive download
6381                                 gchar* location = NULL;
6382
6383                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI) {
6384                                         gchar *path = NULL;
6385
6386                                         mm_attrs_get_string_by_name(attrs, "pd_location", &path);
6387
6388                                         MMPLAYER_FREEIF(player->pd_file_save_path);
6389
6390                                         LOGD("PD Location : %s\n", path);
6391
6392                                         if (path) {
6393                                                 if (!util_get_storage_info(path, &player->storage_info[MMPLAYER_PATH_VOD])) {
6394                                                         LOGE("failed to get storage info");
6395                                                         break;
6396                                                 }
6397                                                 player->pd_file_save_path = g_strdup(path);
6398                                         } else {
6399                                                 LOGE("can't find pd location so, it should be set \n");
6400                                                 break;
6401                                         }
6402                                 }
6403
6404                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
6405                                 if (!element) {
6406                                         LOGE("failed to create PD push source element[%s].\n", "pdpushsrc");
6407                                         break;
6408                                 }
6409
6410                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
6411                                         g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
6412                                 else
6413                                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6414                                 g_object_get(element, "location", &location, NULL);
6415                                 LOGD("PD_LOCATION [%s].\n", location);
6416                                 if (location)
6417                                         g_free(location);
6418                         }
6419                 }
6420                 break;
6421
6422         /* file source */
6423         case MM_PLAYER_URI_TYPE_FILE:
6424                 {
6425                         LOGD("using filesrc for 'file://' handler.\n");
6426                         if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
6427                                 LOGE("failed to get storage info");
6428                                 break;
6429                         }
6430
6431                         element = gst_element_factory_make("filesrc", "source");
6432                         if (!element) {
6433                                 LOGE("failed to create filesrc\n");
6434                                 break;
6435                         }
6436
6437                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
6438                 }
6439                 break;
6440
6441         case MM_PLAYER_URI_TYPE_SS:
6442                 {
6443                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6444                         element = gst_element_factory_make("souphttpsrc", "http streaming source");
6445                         if (!element) {
6446                                 LOGE("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
6447                                 break;
6448                         }
6449
6450                         if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
6451                                 LOGD("get timeout from ini\n");
6452                                 http_timeout = player->ini.http_timeout;
6453                         }
6454
6455                         /* setting property to streaming source */
6456                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6457                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6458                 }
6459                 break;
6460         case MM_PLAYER_URI_TYPE_MS_BUFF:
6461                 {
6462                         LOGD("MS buff src is selected\n");
6463
6464                         if (player->v_stream_caps) {
6465                                 element = gst_element_factory_make("appsrc", "video_appsrc");
6466                                 if (!element) {
6467                                         LOGF("failed to create video app source element[appsrc].\n");
6468                                         break;
6469                                 }
6470
6471                                 if (player->a_stream_caps) {
6472                                         elem_src_audio = gst_element_factory_make("appsrc", "audio_appsrc");
6473                                         if (!elem_src_audio) {
6474                                                 LOGF("failed to create audio app source element[appsrc].\n");
6475                                                 break;
6476                                         }
6477                                 }
6478                         } else if (player->a_stream_caps) {
6479                                 /* no video, only audio pipeline*/
6480                                 element = gst_element_factory_make("appsrc", "audio_appsrc");
6481                                 if (!element) {
6482                                         LOGF("failed to create audio app source element[appsrc].\n");
6483                                         break;
6484                                 }
6485                         }
6486
6487                         if (player->s_stream_caps) {
6488                                 elem_src_subtitle = gst_element_factory_make("appsrc", "subtitle_appsrc");
6489                                 if (!elem_src_subtitle) {
6490                                         LOGF("failed to create subtitle app source element[appsrc].\n");
6491                                         break;
6492                                 }
6493                         }
6494
6495                         LOGD("setting app sources properties.\n");
6496                         LOGD("location : %s\n", player->profile.uri);
6497
6498                         if (player->v_stream_caps && element) {
6499                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6500                                                                                             "blocksize", (guint)1048576,        /* size of many video frames are larger than default blocksize as 4096 */
6501                                                                                                 "caps", player->v_stream_caps, NULL);
6502
6503                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6504                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6505                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6506                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6507
6508                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6509                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6510                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6511                                                                                                                 G_CALLBACK(__gst_seek_video_data), player);
6512
6513                                 if (player->a_stream_caps && elem_src_audio) {
6514                                         g_object_set(G_OBJECT(elem_src_audio), "format", GST_FORMAT_TIME,
6515                                                                                                                         "caps", player->a_stream_caps, NULL);
6516
6517                                         if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6518                                                 g_object_set(G_OBJECT(elem_src_audio), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6519                                         if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6520                                                 g_object_set(G_OBJECT(elem_src_audio), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6521
6522                                         /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6523                                         gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_audio), GST_APP_STREAM_TYPE_SEEKABLE);
6524                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6525                                                                                                                 G_CALLBACK(__gst_seek_audio_data), player);
6526                                 }
6527                         } else if (player->a_stream_caps && element) {
6528                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6529                                                                                                 "caps", player->a_stream_caps, NULL);
6530
6531                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6532                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6533                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6534                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6535
6536                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6537                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6538                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6539                                                                                                                         G_CALLBACK(__gst_seek_audio_data), player);
6540                         }
6541
6542                         if (player->s_stream_caps && elem_src_subtitle) {
6543                                 g_object_set(G_OBJECT(elem_src_subtitle), "format", GST_FORMAT_TIME,
6544                                                                                                                  "caps", player->s_stream_caps, NULL);
6545
6546                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6547                                         g_object_set(G_OBJECT(elem_src_subtitle), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6548                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6549                                         g_object_set(G_OBJECT(elem_src_subtitle), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6550
6551                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_subtitle), GST_APP_STREAM_TYPE_SEEKABLE);
6552
6553                                 MMPLAYER_SIGNAL_CONNECT(player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6554                                                                                                                                 G_CALLBACK(__gst_seek_subtitle_data), player);
6555                         }
6556
6557                         if (player->v_stream_caps && element) {
6558                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6559                                                                                                                 G_CALLBACK(__gst_appsrc_feed_video_data), player);
6560                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6561                                                                                                                 G_CALLBACK(__gst_appsrc_enough_video_data), player);
6562
6563                                 if (player->a_stream_caps && elem_src_audio) {
6564                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6565                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6566                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6567                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6568                                 }
6569                         } else if (player->a_stream_caps && element) {
6570                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6571                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6572                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6573                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6574                         }
6575
6576                         if (player->s_stream_caps && elem_src_subtitle)
6577                                 MMPLAYER_SIGNAL_CONNECT(player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6578                                                                                                                 G_CALLBACK(__gst_appsrc_feed_subtitle_data), player);
6579
6580                         need_state_holder = FALSE;
6581
6582                         mm_attrs_set_int_by_name(attrs, "profile_prepare_async", TRUE);
6583                         if (mmf_attrs_commit(attrs)) /* return -1 if error */
6584                                 LOGE("failed to commit\n");
6585                 }
6586                 break;
6587         /* appsrc */
6588         case MM_PLAYER_URI_TYPE_MEM:
6589                 {
6590                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
6591
6592                         LOGD("mem src is selected\n");
6593
6594                         element = gst_element_factory_make("appsrc", "mem-source");
6595                         if (!element) {
6596                                 LOGE("failed to create appsrc element\n");
6597                                 break;
6598                         }
6599
6600                         g_object_set(element, "stream-type", stream_type, NULL);
6601                         g_object_set(element, "size", player->profile.input_mem.len, NULL);
6602                         g_object_set(element, "blocksize", (guint64)20480, NULL);
6603
6604                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6605                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->profile.input_mem);
6606                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6607                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->profile.input_mem);
6608                 }
6609                 break;
6610         case MM_PLAYER_URI_TYPE_URL:
6611                 break;
6612
6613         case MM_PLAYER_URI_TYPE_TEMP:
6614                 break;
6615
6616         case MM_PLAYER_URI_TYPE_NONE:
6617         default:
6618                 break;
6619         }
6620
6621         /* check source element is OK */
6622         if (!element) {
6623                 LOGE("no source element was created.\n");
6624                 goto INIT_ERROR;
6625         }
6626
6627         /* take source element */
6628         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
6629         mainbin[MMPLAYER_M_SRC].gst = element;
6630         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
6631
6632         if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL)) {
6633                 player->streamer = __mm_player_streaming_create();
6634                 __mm_player_streaming_initialize(player->streamer);
6635         }
6636
6637         if (MMPLAYER_IS_HTTP_PD(player)) {
6638                 gint pre_buffering_time = player->streamer->buffering_req.prebuffer_time;
6639
6640                 LOGD("Picked queue2 element(pre buffer : %d ms)....\n", pre_buffering_time);
6641                 element = gst_element_factory_make("queue2", "queue2");
6642                 if (!element) {
6643                         LOGE("failed to create http streaming buffer element\n");
6644                         goto INIT_ERROR;
6645                 }
6646
6647                 /* take it */
6648                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
6649                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
6650                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
6651
6652                 pre_buffering_time = (pre_buffering_time > 0) ? (pre_buffering_time) : (player->ini.http_buffering_time);
6653
6654                 player->streamer->is_pd_mode = TRUE;
6655
6656                 __mm_player_streaming_set_queue2(player->streamer,
6657                                 element,
6658                                 TRUE,
6659                                 player->ini.http_max_size_bytes, // + PLAYER_PD_EXT_MAX_SIZE_BYTE,
6660                                 pre_buffering_time,
6661                                 1.0,
6662                                 player->ini.http_buffering_limit,
6663                                 MUXED_BUFFER_TYPE_MEM_QUEUE,
6664                                 NULL,
6665                                 0);
6666         }
6667         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
6668                 if (player->v_stream_caps) {
6669                         es_video_queue = gst_element_factory_make("queue2", "video_queue");
6670                         if (!es_video_queue) {
6671                                 LOGE("create es_video_queue for es player failed\n");
6672                                 goto INIT_ERROR;
6673                         }
6674                         g_object_set(G_OBJECT(es_video_queue), "max-size-buffers", 2, NULL);
6675                         mainbin[MMPLAYER_M_V_BUFFER].id = MMPLAYER_M_V_BUFFER;
6676                         mainbin[MMPLAYER_M_V_BUFFER].gst = es_video_queue;
6677                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_V_BUFFER]);
6678
6679                         /* Adding audio appsrc to bucket */
6680                         if (player->a_stream_caps && elem_src_audio) {
6681                                 mainbin[MMPLAYER_M_2ND_SRC].id = MMPLAYER_M_2ND_SRC;
6682                                 mainbin[MMPLAYER_M_2ND_SRC].gst = elem_src_audio;
6683                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_2ND_SRC]);
6684
6685                                 es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6686                                 if (!es_audio_queue) {
6687                                         LOGE("create es_audio_queue for es player failed\n");
6688                                         goto INIT_ERROR;
6689                                 }
6690                                 g_object_set(G_OBJECT(es_audio_queue), "max-size-buffers", 2, NULL);
6691
6692                                 mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6693                                 mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6694                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6695                         }
6696                 } else if (player->a_stream_caps) {
6697                         /* Only audio stream, no video */
6698                         es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6699                         if (!es_audio_queue) {
6700                                 LOGE("create es_audio_queue for es player failed\n");
6701                                 goto INIT_ERROR;
6702                         }
6703                         mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6704                         mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6705                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6706                 }
6707
6708                 if (player->s_stream_caps && elem_src_subtitle) {
6709                         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6710                         mainbin[MMPLAYER_M_SUBSRC].gst = elem_src_subtitle;
6711                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SUBSRC]);
6712
6713                         es_subtitle_queue = gst_element_factory_make("queue2", "subtitle_queue");
6714                         if (!es_subtitle_queue) {
6715                                 LOGE("create es_subtitle_queue for es player failed\n");
6716                                 goto INIT_ERROR;
6717                         }
6718                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_V_BUFFER;
6719                         mainbin[MMPLAYER_M_S_BUFFER].gst = es_subtitle_queue;
6720                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
6721                 }
6722         }
6723
6724         /* create autoplugging element if src element is not a rtsp src */
6725         if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
6726                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_MS_BUFF)) {
6727                 element = NULL;
6728                 enum MainElementID elemId = MMPLAYER_M_NUM;
6729
6730                 if (((MMPLAYER_IS_HTTP_PD(player)) ||
6731                         (!MMPLAYER_IS_HTTP_STREAMING(player)))) {
6732                         elemId = MMPLAYER_M_AUTOPLUG;
6733                         element = __mmplayer_create_decodebin(player);
6734                         if (element) {
6735                                 /* default size of mq in decodebin is 2M
6736                                  * but it can cause blocking issue during seeking depends on content. */
6737                                 g_object_set(G_OBJECT(element), "max-size-bytes", (5*1024*1024), NULL);
6738                         }
6739                         need_state_holder = FALSE;
6740                 } else {
6741                         elemId = MMPLAYER_M_TYPEFIND;
6742                         element = gst_element_factory_make("typefind", "typefinder");
6743                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
6744                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
6745                 }
6746
6747
6748                 /* check autoplug element is OK */
6749                 if (!element) {
6750                         LOGE("can not create element(%d)\n", elemId);
6751                         goto INIT_ERROR;
6752                 }
6753
6754                 mainbin[elemId].id = elemId;
6755                 mainbin[elemId].gst = element;
6756
6757                 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
6758         }
6759
6760         /* add elements to pipeline */
6761         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket)) {
6762                 LOGE("Failed to add elements to pipeline\n");
6763                 goto INIT_ERROR;
6764         }
6765
6766
6767         /* linking elements in the bucket by added order. */
6768         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
6769                 LOGE("Failed to link some elements\n");
6770                 goto INIT_ERROR;
6771         }
6772
6773
6774         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
6775         if (need_state_holder) {
6776                 /* create */
6777                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
6778                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
6779
6780                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst) {
6781                         LOGE("fakesink element could not be created\n");
6782                         goto INIT_ERROR;
6783                 }
6784                 GST_OBJECT_FLAG_UNSET(mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
6785
6786                 /* take ownership of fakesink. we are reusing it */
6787                 gst_object_ref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
6788
6789                 /* add */
6790                 if (FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
6791                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst)) {
6792                         LOGE("failed to add fakesink to bin\n");
6793                         goto INIT_ERROR;
6794                 }
6795         }
6796
6797         /* now we have completed mainbin. take it */
6798         player->pipeline->mainbin = mainbin;
6799
6800         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
6801                 GstPad *srcpad = NULL;
6802
6803                 if (mainbin[MMPLAYER_M_V_BUFFER].gst) {
6804                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_V_BUFFER].gst, "src");
6805                         if (srcpad) {
6806                                 __mmplayer_gst_create_decoder(player,
6807                                                                                                 MM_PLAYER_TRACK_TYPE_VIDEO,
6808                                                                                                 srcpad,
6809                                                                                                 MMPLAYER_M_AUTOPLUG_V_DEC,
6810                                                                                                 "video_decodebin");
6811
6812                                 gst_object_unref(GST_OBJECT(srcpad));
6813                                 srcpad = NULL;
6814                         }
6815                 }
6816
6817                 if ((player->a_stream_caps) && (mainbin[MMPLAYER_M_A_BUFFER].gst)) {
6818                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_BUFFER].gst, "src");
6819                         if (srcpad) {
6820                                 __mmplayer_gst_create_decoder(player,
6821                                                                                                 MM_PLAYER_TRACK_TYPE_AUDIO,
6822                                                                                                 srcpad,
6823                                                                                                 MMPLAYER_M_AUTOPLUG_A_DEC,
6824                                                                                                 "audio_decodebin");
6825
6826                                 gst_object_unref(GST_OBJECT(srcpad));
6827                                 srcpad = NULL;
6828                         } // else error
6829                 } //  else error
6830
6831                 if (mainbin[MMPLAYER_M_S_BUFFER].gst)
6832                         __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
6833         }
6834
6835         /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
6836         if (__mmplayer_check_subtitle(player)) {
6837                 if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player))
6838                         LOGE("fail to create text pipeline");
6839         }
6840
6841         /* connect bus callback */
6842         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
6843         if (!bus) {
6844                 LOGE("cannot get bus from pipeline.\n");
6845                 goto INIT_ERROR;
6846         }
6847
6848         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_msg_push, player);
6849
6850         player->context.thread_default = g_main_context_get_thread_default();
6851
6852         if (player->context.thread_default == NULL) {
6853                 player->context.thread_default = g_main_context_default();
6854                 LOGD("thread-default context is the global default context");
6855         }
6856         LOGW("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
6857
6858         /* set sync handler to get tag synchronously */
6859         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL);
6860
6861         /* finished */
6862         gst_object_unref(GST_OBJECT(bus));
6863         g_list_free(element_bucket);
6864
6865         /* create gst bus_msb_cb thread */
6866         g_mutex_init(&player->bus_msg_thread_mutex);
6867         g_cond_init(&player->bus_msg_thread_cond);
6868         player->bus_msg_thread_exit = FALSE;
6869         player->bus_msg_thread =
6870                 g_thread_try_new("gst_bus_msg_thread", __mmplayer_gst_bus_msg_thread, (gpointer)player, NULL);
6871         if (!player->bus_msg_thread) {
6872                 LOGE("failed to create gst BUS msg thread");
6873                 g_mutex_clear(&player->bus_msg_thread_mutex);
6874                 g_cond_clear(&player->bus_msg_thread_cond);
6875                 goto INIT_ERROR;
6876         }
6877
6878         MMPLAYER_FLEAVE();
6879
6880         return MM_ERROR_NONE;
6881
6882 INIT_ERROR:
6883         __mmplayer_gst_destroy_pipeline(player);
6884         g_list_free(element_bucket);
6885
6886         if (mainbin) {
6887                 /* release element which are not added to bin */
6888                 for (i = 1; i < MMPLAYER_M_NUM; i++) {
6889                         /* NOTE : skip pipeline */
6890                         if (mainbin[i].gst) {
6891                                 GstObject* parent = NULL;
6892                                 parent = gst_element_get_parent(mainbin[i].gst);
6893
6894                                 if (!parent) {
6895                                         gst_object_unref(GST_OBJECT(mainbin[i].gst));
6896                                         mainbin[i].gst = NULL;
6897                                 } else
6898                                         gst_object_unref(GST_OBJECT(parent));
6899                         }
6900                 }
6901
6902                 /* release pipeline with it's childs */
6903                 if (mainbin[MMPLAYER_M_PIPE].gst)
6904                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
6905
6906                 MMPLAYER_FREEIF(mainbin);
6907         }
6908
6909         MMPLAYER_FREEIF(player->pipeline);
6910         return MM_ERROR_PLAYER_INTERNAL;
6911 }
6912
6913 static void
6914 __mmplayer_reset_gapless_state(mm_player_t* player)
6915 {
6916         MMPLAYER_FENTER();
6917         MMPLAYER_RETURN_IF_FAIL(player
6918                 && player->pipeline
6919                 && player->pipeline->audiobin
6920                 && player->pipeline->audiobin[MMPLAYER_A_BIN].gst);
6921
6922         memset(&player->gapless, 0, sizeof(mm_player_gapless_t));
6923
6924         MMPLAYER_FLEAVE();
6925         return;
6926 }
6927
6928 static int
6929 __mmplayer_gst_destroy_pipeline(mm_player_t* player)
6930 {
6931         gint timeout = 0;
6932         int ret = MM_ERROR_NONE;
6933
6934         MMPLAYER_FENTER();
6935
6936         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_INVALID_HANDLE);
6937
6938         /* cleanup stuffs */
6939         MMPLAYER_FREEIF(player->type);
6940         player->have_dynamic_pad = FALSE;
6941         player->no_more_pad = FALSE;
6942         player->num_dynamic_pad = 0;
6943         player->demux_pad_index = 0;
6944         player->use_deinterleave = FALSE;
6945         player->max_audio_channels = 0;
6946         player->video_share_api_delta = 0;
6947         player->video_share_clock_delta = 0;
6948         player->video_hub_download_mode = 0;
6949
6950         MMPLAYER_SUBTITLE_INFO_LOCK(player);
6951         player->subtitle_language_list = NULL;
6952         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
6953
6954         __mmplayer_reset_gapless_state(player);
6955
6956         if (player->streamer) {
6957                 __mm_player_streaming_deinitialize(player->streamer);
6958                 __mm_player_streaming_destroy(player->streamer);
6959                 player->streamer = NULL;
6960         }
6961
6962         /* cleanup unlinked mime type */
6963         MMPLAYER_FREEIF(player->unlinked_audio_mime);
6964         MMPLAYER_FREEIF(player->unlinked_video_mime);
6965         MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
6966
6967         /* cleanup running stuffs */
6968         __mmplayer_cancel_eos_timer(player);
6969
6970         /* cleanup gst stuffs */
6971         if (player->pipeline) {
6972                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
6973                 GstTagList* tag_list = player->pipeline->tag_list;
6974
6975                 /* first we need to disconnect all signal hander */
6976                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_ALL);
6977
6978                 if (mainbin) {
6979                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
6980                         MMPlayerGstElement* videobin = player->pipeline->videobin;
6981                         MMPlayerGstElement* textbin = player->pipeline->textbin;
6982                         GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
6983                         gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
6984                         gst_object_unref(bus);
6985
6986                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
6987                         ret = __mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout);
6988                         if (ret != MM_ERROR_NONE) {
6989                                 LOGE("fail to change state to NULL\n");
6990                                 return MM_ERROR_PLAYER_INTERNAL;
6991                         }
6992
6993                         LOGW("succeeded in chaning state to NULL\n");
6994
6995                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
6996
6997                         /* free fakesink */
6998                         if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
6999                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
7000
7001                         /* free avsysaudiosink
7002                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
7003                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
7004                         */
7005                         MMPLAYER_FREEIF(audiobin);
7006                         MMPLAYER_FREEIF(videobin);
7007                         MMPLAYER_FREEIF(textbin);
7008                         MMPLAYER_FREEIF(mainbin);
7009                 }
7010
7011                 if (tag_list)
7012                         gst_tag_list_free(tag_list);
7013
7014                 MMPLAYER_FREEIF(player->pipeline);
7015         }
7016         MMPLAYER_FREEIF(player->album_art);
7017
7018         if (player->v_stream_caps) {
7019                 gst_caps_unref(player->v_stream_caps);
7020                 player->v_stream_caps = NULL;
7021         }
7022         if (player->a_stream_caps) {
7023                 gst_caps_unref(player->a_stream_caps);
7024                 player->a_stream_caps = NULL;
7025         }
7026
7027         if (player->s_stream_caps) {
7028                 gst_caps_unref(player->s_stream_caps);
7029                 player->s_stream_caps = NULL;
7030         }
7031         _mmplayer_track_destroy(player);
7032
7033         if (player->sink_elements)
7034                 g_list_free(player->sink_elements);
7035         player->sink_elements = NULL;
7036
7037         if (player->bufmgr) {
7038                 tbm_bufmgr_deinit(player->bufmgr);
7039                 player->bufmgr = NULL;
7040         }
7041
7042         LOGW("finished destroy pipeline\n");
7043
7044         MMPLAYER_FLEAVE();
7045
7046         return ret;
7047 }
7048
7049 static int __gst_realize(mm_player_t* player)
7050 {
7051         gint timeout = 0;
7052         int ret = MM_ERROR_NONE;
7053
7054         MMPLAYER_FENTER();
7055
7056         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7057
7058         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7059
7060         ret = __mmplayer_gst_create_pipeline(player);
7061         if (ret) {
7062                 LOGE("failed to create pipeline\n");
7063                 return ret;
7064         }
7065
7066         /* set pipeline state to READY */
7067         /* NOTE : state change to READY must be performed sync. */
7068         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7069         ret = __mmplayer_gst_set_state(player,
7070                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
7071
7072         if (ret != MM_ERROR_NONE) {
7073                 /* return error if failed to set state */
7074                 LOGE("failed to set READY state");
7075                 return ret;
7076         }
7077
7078         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
7079
7080         /* create dot before error-return. for debugging */
7081         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-realize");
7082
7083         MMPLAYER_FLEAVE();
7084
7085         return ret;
7086 }
7087
7088 static int __gst_unrealize(mm_player_t* player)
7089 {
7090         int ret = MM_ERROR_NONE;
7091
7092         MMPLAYER_FENTER();
7093
7094         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7095
7096         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
7097         MMPLAYER_PRINT_STATE(player);
7098
7099         /* release miscellaneous information */
7100         __mmplayer_release_misc(player);
7101
7102         /* destroy pipeline */
7103         ret = __mmplayer_gst_destroy_pipeline(player);
7104         if (ret != MM_ERROR_NONE) {
7105                 LOGE("failed to destory pipeline\n");
7106                 return ret;
7107         }
7108
7109         /* release miscellaneous information.
7110            these info needs to be released after pipeline is destroyed. */
7111         __mmplayer_release_misc_post(player);
7112
7113         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
7114
7115         MMPLAYER_FLEAVE();
7116
7117         return ret;
7118 }
7119
7120 static int __gst_pending_seek(mm_player_t* player)
7121 {
7122         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7123         int ret = MM_ERROR_NONE;
7124
7125         MMPLAYER_FENTER();
7126
7127         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7128
7129         if (!player->pending_seek.is_pending) {
7130                 LOGD("pending seek is not reserved. nothing to do.\n");
7131                 return ret;
7132         }
7133
7134         /* check player state if player could pending seek or not. */
7135         current_state = MMPLAYER_CURRENT_STATE(player);
7136
7137         if (current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING) {
7138                 LOGW("try to pending seek in %s state, try next time. \n",
7139                         MMPLAYER_STATE_GET_NAME(current_state));
7140                 return ret;
7141         }
7142
7143         LOGD("trying to play from(%"G_GINT64_FORMAT") pending position\n", player->pending_seek.pos);
7144
7145         ret = __gst_set_position(player, player->pending_seek.format, player->pending_seek.pos, FALSE);
7146
7147         if (MM_ERROR_NONE != ret)
7148                 LOGE("failed to seek pending postion. just keep staying current position.\n");
7149
7150         player->pending_seek.is_pending = FALSE;
7151
7152         MMPLAYER_FLEAVE();
7153
7154         return ret;
7155 }
7156
7157 static int __gst_start(mm_player_t* player)
7158 {
7159         gboolean sound_extraction = 0;
7160         int ret = MM_ERROR_NONE;
7161         gboolean async = FALSE;
7162
7163         MMPLAYER_FENTER();
7164
7165         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7166
7167         /* get sound_extraction property */
7168         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
7169
7170         /* NOTE : if SetPosition was called before Start. do it now */
7171         /* streaming doesn't support it. so it should be always sync */
7172         /* !!create one more api to check if there is pending seek rather than checking variables */
7173         if ((player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player)) {
7174                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
7175                 ret = __gst_pause(player, FALSE);
7176                 if (ret != MM_ERROR_NONE) {
7177                         LOGE("failed to set state to PAUSED for pending seek\n");
7178                         return ret;
7179                 }
7180
7181                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
7182
7183                 if (sound_extraction) {
7184                         LOGD("setting pcm extraction\n");
7185
7186                         ret = __mmplayer_set_pcm_extraction(player);
7187                         if (MM_ERROR_NONE != ret) {
7188                                 LOGW("failed to set pcm extraction\n");
7189                                 return ret;
7190                         }
7191                 } else {
7192                         if (MM_ERROR_NONE != __gst_pending_seek(player))
7193                                 LOGW("failed to seek pending postion. starting from the begin of content.\n");
7194                 }
7195         }
7196
7197         LOGD("current state before doing transition");
7198         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7199         MMPLAYER_PRINT_STATE(player);
7200
7201         /* set pipeline state to PLAYING  */
7202         if (player->es_player_push_mode)
7203                 async = TRUE;
7204         /* set pipeline state to PLAYING  */
7205         ret = __mmplayer_gst_set_state(player,
7206                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
7207
7208         if (ret == MM_ERROR_NONE) {
7209                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7210         } else {
7211                 LOGE("failed to set state to PLAYING");
7212                 return ret;
7213         }
7214
7215         /* generating debug info before returning error */
7216         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-start");
7217
7218         MMPLAYER_FLEAVE();
7219
7220         return ret;
7221 }
7222
7223 static int __gst_stop(mm_player_t* player)
7224 {
7225         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
7226         MMHandleType attrs = 0;
7227         gboolean rewind = FALSE;
7228         gint timeout = 0;
7229         int ret = MM_ERROR_NONE;
7230         gboolean async = FALSE;
7231
7232         MMPLAYER_FENTER();
7233
7234         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7235         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7236
7237         LOGD("current state before doing transition");
7238         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7239         MMPLAYER_PRINT_STATE(player);
7240
7241         attrs = MMPLAYER_GET_ATTRS(player);
7242         if (!attrs) {
7243                 LOGE("cannot get content attribute\n");
7244                 return MM_ERROR_PLAYER_INTERNAL;
7245         }
7246
7247         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
7248         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7249
7250         if ((!MMPLAYER_IS_STREAMING(player) && !MMPLAYER_IS_MS_BUFF_SRC(player)) ||
7251                 (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked))
7252                 rewind = TRUE;
7253
7254         if (player->es_player_push_mode)
7255                 async = TRUE;
7256         /* set gst state */
7257         ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, timeout);
7258
7259         /* return if set_state has failed */
7260         if (ret != MM_ERROR_NONE) {
7261                 LOGE("failed to set state.\n");
7262                 return ret;
7263         }
7264
7265         /* rewind */
7266         if (rewind) {
7267                 if (!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7268                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
7269                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
7270                         LOGW("failed to rewind\n");
7271                         ret = MM_ERROR_PLAYER_SEEK;
7272                 }
7273         }
7274
7275         /* initialize */
7276         player->sent_bos = FALSE;
7277
7278         if (player->es_player_push_mode) //for cloudgame
7279                 timeout = 0;
7280
7281         /* wait for seek to complete */
7282         change_ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
7283         if (change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL) {
7284                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
7285         } else {
7286                 LOGE("fail to stop player.\n");
7287                 ret = MM_ERROR_PLAYER_INTERNAL;
7288                 __mmplayer_dump_pipeline_state(player);
7289         }
7290
7291         /* generate dot file if enabled */
7292         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-stop");
7293
7294         MMPLAYER_FLEAVE();
7295
7296         return ret;
7297 }
7298
7299 int __gst_pause(mm_player_t* player, gboolean async)
7300 {
7301         int ret = MM_ERROR_NONE;
7302
7303         MMPLAYER_FENTER();
7304
7305         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7306         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7307
7308         LOGD("current state before doing transition");
7309         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
7310         MMPLAYER_PRINT_STATE(player);
7311
7312         /* set pipeline status to PAUSED */
7313         ret = __mmplayer_gst_set_state(player,
7314                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
7315
7316         if (FALSE == async) {
7317                 if (ret != MM_ERROR_NONE) {
7318                         GstMessage *msg = NULL;
7319                         GTimer *timer = NULL;
7320                         gdouble MAX_TIMEOUT_SEC = 3;
7321
7322                         LOGE("failed to set state to PAUSED");
7323
7324                         if (player->msg_posted) {
7325                                 LOGE("error msg is already posted.");
7326                                 return ret;
7327                         }
7328
7329                         timer = g_timer_new();
7330                         g_timer_start(timer);
7331
7332                         GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
7333
7334                         do {
7335                                 msg = gst_bus_timed_pop(bus, 100 * GST_MSECOND);
7336                                 if (msg) {
7337                                         if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
7338                                                 GError *error = NULL;
7339
7340                                                 /* parse error code */
7341                                                 gst_message_parse_error(msg, &error, NULL);
7342
7343                                                 if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
7344                                                         /* Note : the streaming error from the streaming source is handled
7345                                                          *   using __mmplayer_handle_streaming_error.
7346                                                          */
7347                                                         __mmplayer_handle_streaming_error(player, msg);
7348
7349                                                 } else if (error) {
7350                                                         LOGE("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
7351
7352                                                         if (error->domain == GST_STREAM_ERROR)
7353                                                                 ret = __gst_handle_stream_error(player, error, msg);
7354                                                         else if (error->domain == GST_RESOURCE_ERROR)
7355                                                                 ret = __gst_handle_resource_error(player, error->code, NULL);
7356                                                         else if (error->domain == GST_LIBRARY_ERROR)
7357                                                                 ret = __gst_handle_library_error(player, error->code);
7358                                                         else if (error->domain == GST_CORE_ERROR)
7359                                                                 ret = __gst_handle_core_error(player, error->code);
7360
7361                                                         g_error_free(error);
7362                                                 }
7363                                                 player->msg_posted = TRUE;
7364                                         }
7365                                         gst_message_unref(msg);
7366                                 }
7367                         } while (!player->msg_posted && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
7368                         /* clean */
7369                         gst_object_unref(bus);
7370                         g_timer_stop(timer);
7371                         g_timer_destroy(timer);
7372
7373                         return ret;
7374
7375                 } else if ((!MMPLAYER_IS_RTSP_STREAMING(player)) && (!player->video_stream_cb) &&
7376                                    (!player->pipeline->videobin) && (!player->pipeline->audiobin)) {
7377
7378                         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
7379
7380                 } else if (ret == MM_ERROR_NONE) {
7381
7382                         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
7383                 }
7384         }
7385
7386         /* generate dot file before returning error */
7387         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-pause");
7388
7389         MMPLAYER_FLEAVE();
7390
7391         return ret;
7392 }
7393
7394 int __gst_resume(mm_player_t* player, gboolean async)
7395 {
7396         int ret = MM_ERROR_NONE;
7397         gint timeout = 0;
7398
7399         MMPLAYER_FENTER();
7400
7401         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline,
7402                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7403
7404         LOGD("current state before doing transition");
7405         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7406         MMPLAYER_PRINT_STATE(player);
7407
7408         /* generate dot file before returning error */
7409         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-resume");
7410
7411         if (async)
7412                 LOGD("do async state transition to PLAYING.\n");
7413
7414         /* set pipeline state to PLAYING */
7415         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7416
7417         ret = __mmplayer_gst_set_state(player,
7418                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout);
7419         if (ret != MM_ERROR_NONE) {
7420                 LOGE("failed to set state to PLAYING\n");
7421                 return ret;
7422         } else {
7423                 if (async == FALSE) {
7424                         // MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7425                         LOGD("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
7426                         ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
7427                 }
7428         }
7429
7430         /* generate dot file before returning error */
7431         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-resume");
7432
7433         MMPLAYER_FLEAVE();
7434
7435         return ret;
7436 }
7437
7438 static int
7439 __gst_set_position(mm_player_t* player, int format, gint64 position, gboolean internal_called)
7440 {
7441         gint64 dur_nsec = 0;
7442         gint64 pos_nsec = 0;
7443         gboolean ret = TRUE;
7444         gboolean accurated = FALSE;
7445         GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
7446
7447         MMPLAYER_FENTER();
7448         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7449         MMPLAYER_RETURN_VAL_IF_FAIL(!MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP);
7450
7451         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
7452                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
7453                 goto PENDING;
7454
7455         if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
7456                 /* check duration */
7457                 /* NOTE : duration cannot be zero except live streaming.
7458                  *              Since some element could have some timing problemn with quering duration, try again.
7459                  */
7460                 if (player->duration == 0) {
7461                         if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
7462                                 /* For RTSP Streaming , duration is not returned in READY state. So seek to the previous position does not work properly.
7463                                  * Added a patch to postpone the actual seek when state changes to PLAY. Sending a fake SEEK_COMPLETED event to finish the current request. */
7464                                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) && (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
7465                                         player->pending_seek.is_pending = TRUE;
7466                                         player->pending_seek.format = format;
7467                                         player->pending_seek.pos = position;
7468                                         player->doing_seek = FALSE;
7469                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
7470                                         return MM_ERROR_NONE;
7471                                 } else {
7472                                         goto SEEK_ERROR;
7473                                 }
7474                         }
7475                         player->duration = dur_nsec;
7476                 }
7477         }
7478         LOGD("playback rate: %f\n", player->playback_rate);
7479
7480         mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
7481         if (accurated)
7482                 seek_flags |= GST_SEEK_FLAG_ACCURATE;
7483         else
7484                 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
7485
7486         /* do seek */
7487         switch (format) {
7488         case MM_PLAYER_POS_FORMAT_TIME:
7489         {
7490                 if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
7491                         GstQuery *query = NULL;
7492                         gboolean seekable = FALSE;
7493
7494                         /* check position is valid or not */
7495                         if (position > player->duration)
7496                                 goto INVALID_ARGS;
7497
7498                         query = gst_query_new_seeking(GST_FORMAT_TIME);
7499                         if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, query)) {
7500                                 gst_query_parse_seeking(query, NULL, &seekable, NULL, NULL);
7501                                 gst_query_unref(query);
7502
7503                                 if (!seekable) {
7504                                         LOGW("non-seekable content");
7505                                         player->doing_seek = FALSE;
7506                                         return MM_ERROR_PLAYER_NO_OP;
7507                                 }
7508                         } else {
7509                                 LOGW("failed to get seeking query");
7510                                 gst_query_unref(query); /* keep seeking operation */
7511                         }
7512
7513                         LOGD("seeking to(%"G_GINT64_FORMAT") nsec, duration is %"G_GINT64_FORMAT" nsec\n", position, player->duration);
7514
7515                         /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
7516                            But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
7517                            This causes problem is position calculation during normal pause resume scenarios also.
7518                            Currently during seek , we are sending the current position to rtspsrc module for position saving for later use. */
7519                         if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
7520                                 (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
7521                                 if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
7522                                         LOGW("getting current position failed in seek\n");
7523
7524                                 player->last_position = pos_nsec;
7525                                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
7526                         }
7527
7528                         if (player->doing_seek) {
7529                                 LOGD("not completed seek");
7530                                 return MM_ERROR_PLAYER_DOING_SEEK;
7531                         }
7532                 }
7533
7534                 if (!internal_called)
7535                         player->doing_seek = TRUE;
7536
7537                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked)) {
7538                         gint64 cur_time = 0;
7539
7540                         /* get current position */
7541                         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
7542
7543                         /* flush */
7544                         GstEvent *event = gst_event_new_seek(1.0,
7545                                                         GST_FORMAT_TIME,
7546                                                         (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
7547                                                         GST_SEEK_TYPE_SET, cur_time,
7548                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7549                         if (event)
7550                                 __gst_send_event_to_sink(player, event);
7551
7552                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
7553                                 __gst_pause(player, FALSE);
7554                 }
7555
7556                 pos_nsec = position;
7557
7558                 /* rtsp streaming case, there is no sink after READY TO PAUSE state(no preroll state change).
7559                         that's why set position through property. */
7560                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
7561                         (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) &&
7562                         (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY) &&
7563                         (!player->videodec_linked) && (!player->audiodec_linked)) {
7564
7565                         g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "pending-start-position", pos_nsec, NULL);
7566                         LOGD("[%s] set position =%"GST_TIME_FORMAT,
7567                                         GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), GST_TIME_ARGS(pos_nsec));
7568                         player->doing_seek = FALSE;
7569                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
7570                 } else {
7571                         ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7572                                                         GST_FORMAT_TIME, seek_flags,
7573                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7574                 }
7575
7576                 if (!ret) {
7577                         LOGE("failed to set position.");
7578                         goto SEEK_ERROR;
7579                 }
7580         }
7581         break;
7582
7583         case MM_PLAYER_POS_FORMAT_PERCENT:
7584         {
7585                 LOGD("seeking to %"G_GINT64_FORMAT"%%", position);
7586
7587                 if (player->doing_seek) {
7588                         LOGD("not completed seek");
7589                         return MM_ERROR_PLAYER_DOING_SEEK;
7590                 }
7591
7592                 if (!internal_called)
7593                         player->doing_seek = TRUE;
7594
7595                 /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
7596                 pos_nsec = (gint64)((position * player->duration) / 100);
7597                 ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7598                                                 GST_FORMAT_TIME, seek_flags,
7599                                                 GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7600                 if (!ret) {
7601                         LOGE("failed to set position. pos[%"G_GINT64_FORMAT"] dur[%"G_GINT64_FORMAT"] ", pos_nsec, player->duration);
7602                         goto SEEK_ERROR;
7603                 }
7604         }
7605         break;
7606
7607         default:
7608                 goto INVALID_ARGS;
7609         }
7610
7611         /* NOTE : store last seeking point to overcome some bad operation
7612           *     (returning zero when getting current position) of some elements
7613           */
7614         player->last_position = pos_nsec;
7615
7616         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
7617         if (player->playback_rate > 1.0)
7618                 _mmplayer_set_playspeed((MMHandleType)player, player->playback_rate, FALSE);
7619
7620         MMPLAYER_FLEAVE();
7621         return MM_ERROR_NONE;
7622
7623 PENDING:
7624         player->pending_seek.is_pending = TRUE;
7625         player->pending_seek.format = format;
7626         player->pending_seek.pos = position;
7627
7628         LOGW("player current-state : %s, pending-state : %s, just preserve pending position(%"G_GINT64_FORMAT").\n",
7629                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)),
7630                 MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)),
7631                 player->pending_seek.pos);
7632
7633         return MM_ERROR_NONE;
7634
7635 INVALID_ARGS:
7636         LOGE("invalid arguments, position: %"G_GINT64_FORMAT" dur : %"G_GINT64_FORMAT" format : %d \n", position, player->duration, format);
7637         return MM_ERROR_INVALID_ARGUMENT;
7638
7639 SEEK_ERROR:
7640         player->doing_seek = FALSE;
7641         return MM_ERROR_PLAYER_SEEK;
7642 }
7643
7644 #define TRICKPLAY_OFFSET GST_MSECOND
7645
7646 static int
7647 __gst_get_position(mm_player_t* player, int format, gint64* position)
7648 {
7649         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7650         gint64 pos_nsec = 0;
7651         gboolean ret = TRUE;
7652
7653         MMPLAYER_RETURN_VAL_IF_FAIL(player && position && player->pipeline && player->pipeline->mainbin,
7654                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7655
7656         current_state = MMPLAYER_CURRENT_STATE(player);
7657
7658         /* NOTE : query position except paused state to overcome some bad operation
7659          * please refer to below comments in details
7660          */
7661         if (current_state != MM_PLAYER_STATE_PAUSED)
7662                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec);
7663
7664         /* NOTE : get last point to overcome some bad operation of some elements
7665          *(returning zero when getting current position in paused state
7666          * and when failed to get postion during seeking
7667          */
7668         if ((current_state == MM_PLAYER_STATE_PAUSED) || (!ret)) {
7669                 LOGD("pos_nsec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_nsec), ret, current_state);
7670
7671                 if (player->playback_rate < 0.0)
7672                         pos_nsec = player->last_position - TRICKPLAY_OFFSET;
7673                 else
7674                         pos_nsec = player->last_position;
7675
7676                 if (!ret)
7677                         pos_nsec = player->last_position;
7678                 else
7679                         player->last_position = pos_nsec;
7680
7681                 LOGD("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_nsec));
7682
7683         } else {
7684                 if (player->duration > 0 && pos_nsec > player->duration)
7685                         pos_nsec = player->duration;
7686
7687                 player->last_position = pos_nsec;
7688         }
7689
7690         switch (format) {
7691         case MM_PLAYER_POS_FORMAT_TIME:
7692                 *position = pos_nsec;
7693                 break;
7694
7695         case MM_PLAYER_POS_FORMAT_PERCENT:
7696         {
7697                 if (player->duration <= 0) {
7698                         LOGD("duration is [%"G_GINT64_FORMAT"], so returning position 0\n", player->duration);
7699                         *position = 0;
7700                 } else {
7701                         LOGD("position is [%"G_GINT64_FORMAT"] nsec , duration is [%"G_GINT64_FORMAT"] nsec", pos_nsec, player->duration);
7702                         *position = (gint64)(pos_nsec * 100 / player->duration);
7703                 }
7704                 break;
7705         }
7706         default:
7707                 return MM_ERROR_PLAYER_INTERNAL;
7708         }
7709
7710         return MM_ERROR_NONE;
7711 }
7712
7713
7714 static int __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
7715 {
7716 #define STREAMING_IS_FINISHED   0
7717 #define BUFFERING_MAX_PER       100
7718 #define DEFAULT_PER_VALUE       -1
7719 #define CHECK_PERCENT_VALUE(a, min, max)(((a) > (min)) ? (((a) < (max)) ? (a) : (max)) : (min))
7720
7721         MMPlayerGstElement *mainbin = NULL;
7722         gint start_per = DEFAULT_PER_VALUE, stop_per = DEFAULT_PER_VALUE;
7723         gint64 buffered_total = 0;
7724         gint64 position = 0;
7725         gint buffered_sec = -1;
7726         GstBufferingMode mode = GST_BUFFERING_STREAM;
7727         gint64 content_size_time = player->duration;
7728         guint64 content_size_bytes = player->http_content_size;
7729
7730         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
7731                                                 player->pipeline &&
7732                                                 player->pipeline->mainbin,
7733                                                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7734
7735         MMPLAYER_RETURN_VAL_IF_FAIL(start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT);
7736
7737         *start_pos = 0;
7738         *stop_pos = 0;
7739
7740         if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
7741                 /* and rtsp is not ready yet. */
7742                 LOGW("it's only used for http streaming case.\n");
7743                 return MM_ERROR_PLAYER_NO_OP;
7744         }
7745
7746         if (format != MM_PLAYER_POS_FORMAT_PERCENT) {
7747                 LOGW("Time format is not supported yet.\n");
7748                 return MM_ERROR_INVALID_ARGUMENT;
7749         }
7750
7751         if (content_size_time <= 0 || content_size_bytes <= 0) {
7752                 LOGW("there is no content size.");
7753                 return MM_ERROR_NONE;
7754         }
7755
7756         if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position) != MM_ERROR_NONE) {
7757                 LOGW("fail to get current position.");
7758                 return MM_ERROR_NONE;
7759         }
7760
7761         LOGD("pos %"G_GINT64_FORMAT" msec, dur %d sec, len %"G_GUINT64_FORMAT" bytes",
7762                 GST_TIME_AS_MSECONDS(position), (guint)GST_TIME_AS_SECONDS(content_size_time), content_size_bytes);
7763
7764         mainbin = player->pipeline->mainbin;
7765         start_per = (gint)(floor(100 *(gdouble)position / (gdouble)content_size_time));
7766
7767         if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
7768                 GstQuery *query = NULL;
7769                 gint byte_in_rate = 0, byte_out_rate = 0;
7770                 gint64 estimated_total = 0;
7771
7772                 query = gst_query_new_buffering(GST_FORMAT_BYTES);
7773                 if (!query || !gst_element_query(mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query)) {
7774                         LOGW("fail to get buffering query from queue2");
7775                         if (query)
7776                                 gst_query_unref(query);
7777                         return MM_ERROR_NONE;
7778                 }
7779
7780                 gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, NULL);
7781                 LOGD("mode %d, in_rate %d, out_rate %d", mode, byte_in_rate, byte_out_rate);
7782
7783                 if (mode == GST_BUFFERING_STREAM) {
7784                         /* using only queue in case of push mode(ts / mp3) */
7785                         if (gst_element_query_position(mainbin[MMPLAYER_M_SRC].gst,
7786                                 GST_FORMAT_BYTES, &buffered_total)) {
7787                                 LOGD("buffered_total %"G_GINT64_FORMAT, buffered_total);
7788                                 stop_per = 100 * buffered_total / content_size_bytes;
7789                         }
7790                 } else {
7791                         /* GST_BUFFERING_TIMESHIFT or GST_BUFFERING_DOWNLOAD */
7792                         guint idx = 0;
7793                         guint num_of_ranges = 0;
7794                         gint64 start_byte = 0, stop_byte = 0;
7795
7796                         gst_query_parse_buffering_range(query, NULL, NULL, NULL, &estimated_total);
7797                         if (estimated_total != STREAMING_IS_FINISHED) {
7798                                 /* buffered size info from queue2 */
7799                                 num_of_ranges = gst_query_get_n_buffering_ranges(query);
7800                                 for (idx = 0; idx < num_of_ranges; idx++) {
7801                                         gst_query_parse_nth_buffering_range(query, idx, &start_byte, &stop_byte);
7802                                         LOGD("range %d, %"G_GINT64_FORMAT" ~ %"G_GUINT64_FORMAT, idx, start_byte, stop_byte);
7803
7804                                         buffered_total += (stop_byte - start_byte);
7805                                 }
7806                         } else
7807                                 stop_per = BUFFERING_MAX_PER;
7808                 }
7809                 gst_query_unref(query);
7810         }
7811
7812         if (stop_per == DEFAULT_PER_VALUE) {
7813                 guint dur_sec = (guint)(content_size_time/GST_SECOND);
7814                 if (dur_sec > 0) {
7815                         guint avg_byterate = (guint)(content_size_bytes/dur_sec);
7816
7817                         /* buffered size info from multiqueue */
7818                         if (mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) {
7819                                 guint curr_size_bytes = 0;
7820                                 g_object_get(G_OBJECT(mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst),
7821                                         "curr-size-bytes", &curr_size_bytes, NULL);
7822                                 LOGD("curr_size_bytes of multiqueue = %d", curr_size_bytes);
7823                                 buffered_total += curr_size_bytes;
7824                         }
7825
7826                         if (avg_byterate > 0)
7827                                 buffered_sec = (gint)(ceil((gdouble)buffered_total/(gdouble)avg_byterate));
7828                         else if (player->total_maximum_bitrate > 0)
7829                                 buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total)/(gdouble)player->total_maximum_bitrate));
7830                         else if (player->total_bitrate > 0)
7831                                 buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total)/(gdouble)player->total_bitrate));
7832
7833                         if (buffered_sec >= 0)
7834                                 stop_per = start_per +(gint)(ceil)(100*(gdouble)buffered_sec/(gdouble)dur_sec);
7835                 }
7836         }
7837
7838         *start_pos = CHECK_PERCENT_VALUE(start_per, 0, 100);
7839         *stop_pos = CHECK_PERCENT_VALUE(stop_per, *start_pos, 100);
7840
7841         LOGD("buffered info: %"G_GINT64_FORMAT" bytes, %d sec, per %lu~%lu\n",
7842                 buffered_total, buffered_sec, *start_pos, *stop_pos);
7843
7844         return MM_ERROR_NONE;
7845 }
7846
7847 static int
7848 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param)
7849 {
7850         MMPLAYER_FENTER();
7851
7852         if (!player) {
7853                 LOGW("set_message_callback is called with invalid player handle\n");
7854                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
7855         }
7856
7857         player->msg_cb = callback;
7858         player->msg_cb_param = user_param;
7859
7860         LOGD("msg_cb : %p     msg_cb_param : %p\n", callback, user_param);
7861
7862         MMPLAYER_FLEAVE();
7863
7864         return MM_ERROR_NONE;
7865 }
7866
7867 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data)
7868 {
7869         int ret = MM_ERROR_PLAYER_INVALID_URI;
7870         char *path = NULL;
7871
7872         MMPLAYER_FENTER();
7873
7874         MMPLAYER_RETURN_VAL_IF_FAIL(uri , FALSE);
7875         MMPLAYER_RETURN_VAL_IF_FAIL(data , FALSE);
7876         MMPLAYER_RETURN_VAL_IF_FAIL((strlen(uri) <= MM_MAX_URL_LEN), FALSE);
7877
7878         memset(data, 0, sizeof(MMPlayerParseProfile));
7879
7880         if ((path = strstr(uri, "es_buff://"))) {
7881                 if (strlen(path)) {
7882                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7883                         data->uri_type = MM_PLAYER_URI_TYPE_MS_BUFF;
7884                         ret = MM_ERROR_NONE;
7885                 }
7886         } else if ((path = strstr(uri, "rtsp://")) || (path = strstr(uri, "rtsps://"))) {
7887                 if (strlen(path)) {
7888                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7889                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7890                         ret = MM_ERROR_NONE;
7891                 }
7892         } else if ((path = strstr(uri, "http://")) || (path = strstr(uri, "https://"))) {
7893                 if (strlen(path)) {
7894                         gchar *tmp = NULL;
7895                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7896                         tmp = g_ascii_strdown(uri, strlen(uri));
7897
7898                         if (tmp && (g_str_has_suffix(tmp, ".ism/manifest") || g_str_has_suffix(tmp, ".isml/manifest")))
7899                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
7900                         else
7901                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
7902
7903                         ret = MM_ERROR_NONE;
7904                         g_free(tmp);
7905                 }
7906         } else if ((path = strstr(uri, "rtspu://"))) {
7907                 if (strlen(path)) {
7908                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7909                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7910                         ret = MM_ERROR_NONE;
7911                 }
7912         } else if ((path = strstr(uri, "rtspr://"))) {
7913                 strncpy(data->uri, path, MM_MAX_URL_LEN-1);
7914                 char *separater = strstr(path, "*");
7915
7916                 if (separater) {
7917                         int urgent_len = 0;
7918                         char *urgent = separater + strlen("*");
7919
7920                         if ((urgent_len = strlen(urgent))) {
7921                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
7922                                 strncpy(data->urgent, urgent, MM_MAX_FILENAME_LEN-1);
7923                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7924                                 ret = MM_ERROR_NONE;
7925                         }
7926                 }
7927         } else if ((path = strstr(uri, "mms://"))) {
7928                 if (strlen(path)) {
7929                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7930                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
7931                         ret = MM_ERROR_NONE;
7932                 }
7933         } else if ((path = strstr(uri, "mem://"))) {
7934                 if (strlen(path)) {
7935                         int mem_size = 0;
7936                         char *buffer = NULL;
7937                         char *seperator = strchr(path, ',');
7938                         char ext[100] = {0,}, size[100] = {0,};
7939
7940                         if (seperator) {
7941                                 if ((buffer = strstr(path, "ext="))) {
7942                                         buffer += strlen("ext=");
7943
7944                                         if (strlen(buffer)) {
7945                                                 strncpy(ext, buffer, 99);
7946
7947                                                 if ((seperator = strchr(ext, ','))
7948                                                         || (seperator = strchr(ext, ' '))
7949                                                         || (seperator = strchr(ext, '\0'))) {
7950                                                         seperator[0] = '\0';
7951                                                 }
7952                                         }
7953                                 }
7954
7955                                 if ((buffer = strstr(path, "size="))) {
7956                                         buffer += strlen("size=");
7957
7958                                         if (strlen(buffer) > 0) {
7959                                                 strncpy(size, buffer, 99);
7960
7961                                                 if ((seperator = strchr(size, ','))
7962                                                         || (seperator = strchr(size, ' '))
7963                                                         || (seperator = strchr(size, '\0'))) {
7964                                                         seperator[0] = '\0';
7965                                                 }
7966
7967                                                 mem_size = atoi(size);
7968                                         }
7969                                 }
7970                         }
7971
7972                         LOGD("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
7973                         if (mem_size && param) {
7974                                 if (data->input_mem.buf)
7975                                         free(data->input_mem.buf);
7976                                 data->input_mem.buf = malloc(mem_size);
7977
7978                                 if (data->input_mem.buf) {
7979                                         memcpy(data->input_mem.buf, param, mem_size);
7980                                         data->input_mem.len = mem_size;
7981                                         ret = MM_ERROR_NONE;
7982                                 } else {
7983                                         LOGE("failed to alloc mem %d", mem_size);
7984                                         ret = MM_ERROR_PLAYER_INTERNAL;
7985                                 }
7986
7987                                 data->input_mem.offset = 0;
7988                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
7989                         }
7990                 }
7991         } else {
7992                 gchar *location = NULL;
7993                 GError *err = NULL;
7994
7995                 if ((path = strstr(uri, "file://"))) {
7996
7997                         location = g_filename_from_uri(uri, NULL, &err);
7998
7999                         if (!location || (err != NULL)) {
8000                           LOGE("Invalid URI '%s' for filesrc: %s", path,
8001                                  (err != NULL) ? err->message : "unknown error");
8002
8003                           if (err) g_error_free(err);
8004                           if (location) g_free(location);
8005
8006                           data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8007                           goto exit;
8008                         }
8009
8010                         LOGD("path from uri: %s", location);
8011                 }
8012
8013                 path = (location != NULL) ? (location) : ((char*)uri);
8014                 int file_stat = MM_ERROR_NONE;
8015
8016                 file_stat = util_exist_file_path(path);
8017
8018                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
8019                 if (file_stat == MM_ERROR_NONE) {
8020                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", path);
8021
8022                         if (util_is_sdp_file(path)) {
8023                                 LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8024                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8025                         } else {
8026                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8027                         }
8028                         ret = MM_ERROR_NONE;
8029                 } else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED) {
8030                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8031                 } else {
8032                         LOGE("invalid uri, could not play..\n");
8033                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8034                 }
8035
8036                 if (location) g_free(location);
8037         }
8038
8039 exit:
8040         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE)
8041                 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
8042         else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION)
8043                 ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
8044
8045         /* dump parse result */
8046         SECURE_LOGW("incomming uri : %s\n", uri);
8047         LOGD("uri_type : %d, mem : %p, mem_size : %d, urgent : %s\n",
8048                 data->uri_type, data->input_mem.buf, data->input_mem.len, data->urgent);
8049
8050         MMPLAYER_FLEAVE();
8051
8052         return ret;
8053 }
8054
8055 gboolean
8056 __mmplayer_can_do_interrupt(mm_player_t *player)
8057 {
8058         if (!player || !player->pipeline || !player->attrs) {
8059                 LOGW("not initialized");
8060                 goto FAILED;
8061         }
8062
8063         if (player->set_mode.pcm_extraction) {
8064                 LOGW("leave right now, %d", player->set_mode.pcm_extraction);
8065                 goto FAILED;
8066         }
8067
8068         /* check if seeking */
8069         if (player->doing_seek) {
8070                 MMMessageParamType msg_param;
8071                 memset(&msg_param, 0, sizeof(MMMessageParamType));
8072                 msg_param.code = MM_ERROR_PLAYER_SEEK;
8073                 player->doing_seek = FALSE;
8074                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
8075                 goto FAILED;
8076         }
8077
8078         /* check other thread */
8079         if (!MMPLAYER_CMD_TRYLOCK(player)) {
8080                 LOGW("locked already, cmd state : %d", player->cmd);
8081
8082                 /* check application command */
8083                 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) {
8084                         LOGW("playing.. should wait cmd lock then, will be interrupted");
8085
8086                         /* lock will be released at mrp_resource_release_cb() */
8087                         MMPLAYER_CMD_LOCK(player);
8088                         goto INTERRUPT;
8089                 }
8090                 LOGW("nothing to do");
8091                 goto FAILED;
8092         } else {
8093                 LOGW("can interrupt immediately");
8094                 goto INTERRUPT;
8095         }
8096
8097 FAILED:    /* with CMD UNLOCKED */
8098         return FALSE;
8099
8100 INTERRUPT: /* with CMD LOCKED, released at mrp_resource_release_cb() */
8101         return TRUE;
8102 }
8103
8104 static int
8105 __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res,
8106                 void *user_data)
8107 {
8108         mm_player_t *player = NULL;
8109
8110         MMPLAYER_FENTER();
8111
8112         if (user_data == NULL) {
8113                 LOGE("- user_data is null\n");
8114                 return FALSE;
8115         }
8116         player = (mm_player_t *)user_data;
8117
8118         /* do something to release resource here.
8119          * player stop and interrupt forwarding */
8120         if (!__mmplayer_can_do_interrupt(player)) {
8121                 LOGW("no need to interrupt, so leave");
8122         } else {
8123                 MMMessageParamType msg = {0, };
8124                 gint64 pos = 0;
8125
8126                 player->interrupted_by_resource = TRUE;
8127
8128                 /* get last play position */
8129                 if (_mmplayer_get_position((MMHandleType)player, MM_PLAYER_POS_FORMAT_TIME, &pos) != MM_ERROR_NONE) {
8130                         LOGW("failed to get play position.");
8131                 } else {
8132                         msg.union_type = MM_MSG_UNION_TIME;
8133                         msg.time.elapsed = pos;
8134                         MMPLAYER_POST_MSG(player, MM_MESSAGE_PLAY_POSITION, &msg);
8135                 }
8136                 LOGD("video resource conflict so, resource will be freed by unrealizing");
8137                 if (_mmplayer_unrealize((MMHandleType)player))
8138                         LOGW("failed to unrealize");
8139
8140                 /* lock is called in __mmplayer_can_do_interrupt() */
8141                 MMPLAYER_CMD_UNLOCK(player);
8142         }
8143
8144         if (res == player->video_overlay_resource)
8145                 player->video_overlay_resource = FALSE;
8146         else
8147                 player->video_decoder_resource = FALSE;
8148
8149         MMPLAYER_FLEAVE();
8150
8151         return FALSE;
8152 }
8153
8154 int
8155 _mmplayer_create_player(MMHandleType handle)
8156 {
8157         int ret = MM_ERROR_PLAYER_INTERNAL;
8158         bool enabled = false;
8159
8160         mm_player_t* player = MM_PLAYER_CAST(handle);
8161
8162         MMPLAYER_FENTER();
8163
8164         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8165
8166         /* initialize player state */
8167         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
8168         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
8169         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
8170         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
8171
8172         /* check current state */
8173         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_CREATE);
8174
8175         /* construct attributes */
8176         player->attrs = _mmplayer_construct_attribute(handle);
8177
8178         if (!player->attrs) {
8179                 LOGE("Failed to construct attributes\n");
8180                 return ret;
8181         }
8182
8183         /* initialize gstreamer with configured parameter */
8184         if (!__mmplayer_init_gstreamer(player)) {
8185                 LOGE("Initializing gstreamer failed\n");
8186                 _mmplayer_deconstruct_attribute(handle);
8187                 return ret;
8188         }
8189
8190         /* create lock. note that g_tread_init() has already called in gst_init() */
8191         g_mutex_init(&player->fsink_lock);
8192
8193         /* create update tag lock */
8194         g_mutex_init(&player->update_tag_lock);
8195
8196         /* create next play mutex */
8197         g_mutex_init(&player->next_play_thread_mutex);
8198
8199         /* create next play cond */
8200         g_cond_init(&player->next_play_thread_cond);
8201
8202         /* create next play thread */
8203         player->next_play_thread =
8204                 g_thread_try_new("next_play_thread", __mmplayer_next_play_thread, (gpointer)player, NULL);
8205         if (!player->next_play_thread) {
8206                 LOGE("failed to create next play thread");
8207                 ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
8208                 g_mutex_clear(&player->next_play_thread_mutex);
8209                 g_cond_clear(&player->next_play_thread_cond);
8210                 goto ERROR;
8211         }
8212
8213         player->bus_msg_q = g_queue_new();
8214         if (!player->bus_msg_q) {
8215                 LOGE("failed to create queue for bus_msg");
8216                 ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
8217                 goto ERROR;
8218         }
8219
8220         ret = _mmplayer_initialize_video_capture(player);
8221         if (ret != MM_ERROR_NONE) {
8222                 LOGE("failed to initialize video capture\n");
8223                 goto ERROR;
8224         }
8225
8226         /* initialize resource manager */
8227         if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_create(
8228                         MM_RESOURCE_MANAGER_APP_CLASS_MEDIA, __resource_release_cb, player,
8229                         &player->resource_manager)) {
8230                 LOGE("failed to initialize resource manager\n");
8231                 goto ERROR;
8232         }
8233
8234         if (MMPLAYER_IS_HTTP_PD(player)) {
8235                 player->pd_downloader = NULL;
8236                 player->pd_file_save_path = NULL;
8237         }
8238
8239         /* create video bo lock and cond */
8240         g_mutex_init(&player->video_bo_mutex);
8241         g_cond_init(&player->video_bo_cond);
8242
8243         /* create media stream callback mutex */
8244         g_mutex_init(&player->media_stream_cb_lock);
8245
8246         /* create subtitle info lock and cond */
8247         g_mutex_init(&player->subtitle_info_mutex);
8248         g_cond_init(&player->subtitle_info_cond);
8249
8250         player->streaming_type = STREAMING_SERVICE_NONE;
8251
8252         /* give default value of audio effect setting */
8253         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
8254         player->sound.rg_enable = false;
8255         player->playback_rate = DEFAULT_PLAYBACK_RATE;
8256
8257         player->play_subtitle = FALSE;
8258         player->use_deinterleave = FALSE;
8259         player->max_audio_channels = 0;
8260         player->video_share_api_delta = 0;
8261         player->video_share_clock_delta = 0;
8262         player->has_closed_caption = FALSE;
8263         player->video_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
8264         player->video_extra_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
8265         player->pending_resume = FALSE;
8266         if (player->ini.dump_element_keyword[0][0] == '\0')
8267                 player->ini.set_dump_element_flag = FALSE;
8268         else
8269                 player->ini.set_dump_element_flag = TRUE;
8270
8271         player->adaptive_info.limit.bandwidth = ADAPTIVE_VARIANT_DEFAULT_VALUE;
8272         player->adaptive_info.limit.width = ADAPTIVE_VARIANT_DEFAULT_VALUE;
8273         player->adaptive_info.limit.height = ADAPTIVE_VARIANT_DEFAULT_VALUE;
8274
8275         /* Set video360 settings to their defaults for just-created player.
8276          * */
8277
8278         player->is_360_feature_enabled = FALSE;
8279         if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(FEATURE_NAME_SPHERICAL_VIDEO, &enabled)) {
8280                 LOGI("spherical feature info: %d", enabled);
8281                 if (enabled)
8282                         player->is_360_feature_enabled = TRUE;
8283         } else {
8284                 LOGE("failed to get spherical feature info");
8285         }
8286
8287         player->is_content_spherical = FALSE;
8288         player->is_video360_enabled = TRUE;
8289         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
8290         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
8291         player->video360_yaw_radians = PLAYER_SPHERICAL_DEFAULT_YAW;
8292         player->video360_pitch_radians = PLAYER_SPHERICAL_DEFAULT_PITCH;
8293         player->video360_zoom = 1.0f;
8294         player->video360_horizontal_fov = PLAYER_SPHERICAL_DEFAULT_H_FOV;
8295         player->video360_vertical_fov = PLAYER_SPHERICAL_DEFAULT_V_FOV;
8296
8297         /* set player state to null */
8298         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
8299         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
8300
8301         return MM_ERROR_NONE;
8302
8303 ERROR:
8304         /* free lock */
8305         g_mutex_clear(&player->fsink_lock);
8306
8307         /* free update tag lock */
8308         g_mutex_clear(&player->update_tag_lock);
8309
8310         g_queue_free(player->bus_msg_q);
8311
8312         /* free next play thread */
8313         if (player->next_play_thread) {
8314                 MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
8315                 player->next_play_thread_exit = TRUE;
8316                 MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
8317                 MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
8318
8319                 g_thread_join(player->next_play_thread);
8320                 player->next_play_thread = NULL;
8321
8322                 g_mutex_clear(&player->next_play_thread_mutex);
8323                 g_cond_clear(&player->next_play_thread_cond);
8324         }
8325
8326         /* release attributes */
8327         _mmplayer_deconstruct_attribute(handle);
8328
8329         MMPLAYER_FLEAVE();
8330
8331         return ret;
8332 }
8333
8334 static gboolean
8335 __mmplayer_init_gstreamer(mm_player_t* player)
8336 {
8337         static gboolean initialized = FALSE;
8338         static const int max_argc = 50;
8339         gint* argc = NULL;
8340         gchar** argv = NULL;
8341         gchar** argv2 = NULL;
8342         GError *err = NULL;
8343         int i = 0;
8344         int arg_count = 0;
8345
8346         if (initialized) {
8347                 LOGD("gstreamer already initialized.\n");
8348                 return TRUE;
8349         }
8350
8351         /* alloc */
8352         argc = malloc(sizeof(int));
8353         argv = malloc(sizeof(gchar*) * max_argc);
8354         argv2 = malloc(sizeof(gchar*) * max_argc);
8355
8356         if (!argc || !argv || !argv2)
8357                 goto ERROR;
8358
8359         memset(argv, 0, sizeof(gchar*) * max_argc);
8360         memset(argv2, 0, sizeof(gchar*) * max_argc);
8361
8362         /* add initial */
8363         *argc = 1;
8364         argv[0] = g_strdup("mmplayer");
8365
8366         /* add gst_param */
8367         for (i = 0; i < 5; i++) {
8368                 /* FIXIT : num of param is now fixed to 5. make it dynamic */
8369                 if (strlen(player->ini.gst_param[i]) > 0) {
8370                         argv[*argc] = g_strdup(player->ini.gst_param[i]);
8371                         (*argc)++;
8372                 }
8373         }
8374
8375         /* we would not do fork for scanning plugins */
8376         argv[*argc] = g_strdup("--gst-disable-registry-fork");
8377         (*argc)++;
8378
8379         /* check disable registry scan */
8380         if (player->ini.skip_rescan) {
8381                 argv[*argc] = g_strdup("--gst-disable-registry-update");
8382                 (*argc)++;
8383         }
8384
8385         /* check disable segtrap */
8386         if (player->ini.disable_segtrap) {
8387                 argv[*argc] = g_strdup("--gst-disable-segtrap");
8388                 (*argc)++;
8389         }
8390
8391         LOGD("initializing gstreamer with following parameter\n");
8392         LOGD("argc : %d\n", *argc);
8393         arg_count = *argc;
8394
8395         for (i = 0; i < arg_count; i++) {
8396                 argv2[i] = argv[i];
8397                 LOGD("argv[%d] : %s\n", i, argv2[i]);
8398         }
8399
8400         /* initializing gstreamer */
8401         if (!gst_init_check(argc, &argv, &err)) {
8402                 LOGE("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
8403                 if (err)
8404                         g_error_free(err);
8405
8406                 goto ERROR;
8407         }
8408         /* release */
8409         for (i = 0; i < arg_count; i++) {
8410                 //LOGD("release - argv[%d] : %s\n", i, argv2[i]);
8411                 MMPLAYER_FREEIF(argv2[i]);
8412         }
8413
8414         MMPLAYER_FREEIF(argv);
8415         MMPLAYER_FREEIF(argv2);
8416         MMPLAYER_FREEIF(argc);
8417
8418         /* done */
8419         initialized = TRUE;
8420
8421         return TRUE;
8422
8423 ERROR:
8424
8425         /* release */
8426         for (i = 0; i < arg_count; i++) {
8427                 LOGD("free[%d] : %s\n", i, argv2[i]);
8428                 MMPLAYER_FREEIF(argv2[i]);
8429         }
8430
8431         MMPLAYER_FREEIF(argv);
8432         MMPLAYER_FREEIF(argv2);
8433         MMPLAYER_FREEIF(argc);
8434
8435         return FALSE;
8436 }
8437
8438 int
8439 __mmplayer_destroy_streaming_ext(mm_player_t* player)
8440 {
8441         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8442
8443         if (player->pd_downloader || MMPLAYER_IS_HTTP_PD(player)) {
8444                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
8445                 MMPLAYER_FREEIF(player->pd_file_save_path);
8446         }
8447
8448         return MM_ERROR_NONE;
8449 }
8450
8451 static void
8452 __mmplayer_check_async_state_transition(mm_player_t* player)
8453 {
8454         GstState element_state = GST_STATE_VOID_PENDING;
8455         GstState element_pending_state = GST_STATE_VOID_PENDING;
8456         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
8457         GstElement * element = NULL;
8458         gboolean async = FALSE;
8459
8460         /* check player handle */
8461         MMPLAYER_RETURN_IF_FAIL(player &&
8462                                                 player->pipeline &&
8463                                                 player->pipeline->mainbin &&
8464                                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
8465
8466         if (player->attrs)
8467                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
8468
8469         if (!MMPLAYER_IS_MS_BUFF_SRC(player) && (async == FALSE)) {
8470                 LOGD("don't need to check the pipeline state");
8471                 return;
8472         }
8473
8474         MMPLAYER_PRINT_STATE(player);
8475
8476         /* wait for state transition */
8477         element = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
8478         ret = gst_element_get_state(element, &element_state, &element_pending_state, 1*GST_SECOND);
8479
8480         if (ret == GST_STATE_CHANGE_FAILURE) {
8481                 LOGE(" [%s] state : %s   pending : %s \n",
8482                         GST_ELEMENT_NAME(element),
8483                         gst_element_state_get_name(element_state),
8484                         gst_element_state_get_name(element_pending_state));
8485
8486                 /* dump state of all element */
8487                 __mmplayer_dump_pipeline_state(player);
8488
8489                 return;
8490         }
8491
8492         LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
8493         return;
8494 }
8495
8496 int
8497 _mmplayer_destroy(MMHandleType handle)
8498 {
8499         mm_player_t* player = MM_PLAYER_CAST(handle);
8500
8501         MMPLAYER_FENTER();
8502
8503         /* check player handle */
8504         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8505
8506         /* destroy can called at anytime */
8507         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_DESTROY);
8508
8509         /* check async state transition */
8510         __mmplayer_check_async_state_transition(player);
8511
8512         __mmplayer_destroy_streaming_ext(player);
8513
8514         /* release next play thread */
8515         if (player->next_play_thread) {
8516                 MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
8517                 player->next_play_thread_exit = TRUE;
8518                 MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
8519                 MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
8520
8521                 LOGD("waitting for next play thread exit\n");
8522                 g_thread_join(player->next_play_thread);
8523                 g_mutex_clear(&player->next_play_thread_mutex);
8524                 g_cond_clear(&player->next_play_thread_cond);
8525                 LOGD("next play thread released\n");
8526         }
8527
8528         _mmplayer_release_video_capture(player);
8529
8530         /* de-initialize resource manager */
8531         if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_destroy(
8532                         player->resource_manager))
8533                 LOGE("failed to deinitialize resource manager\n");
8534
8535         /* release pipeline */
8536         if (MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline(player)) {
8537                 LOGE("failed to destory pipeline\n");
8538                 return MM_ERROR_PLAYER_INTERNAL;
8539         }
8540
8541         g_queue_free(player->bus_msg_q);
8542
8543         /* release subtitle info lock and cond */
8544         g_mutex_clear(&player->subtitle_info_mutex);
8545         g_cond_clear(&player->subtitle_info_cond);
8546
8547         __mmplayer_release_dump_list(player->dump_list);
8548
8549         /* release miscellaneous information */
8550         __mmplayer_release_misc(player);
8551
8552         /* release miscellaneous information.
8553            these info needs to be released after pipeline is destroyed. */
8554         __mmplayer_release_misc_post(player);
8555
8556         /* release attributes */
8557         _mmplayer_deconstruct_attribute(handle);
8558
8559         /* release lock */
8560         g_mutex_clear(&player->fsink_lock);
8561
8562         /* release lock */
8563         g_mutex_clear(&player->update_tag_lock);
8564
8565         /* release video bo lock and cond */
8566         g_mutex_clear(&player->video_bo_mutex);
8567         g_cond_clear(&player->video_bo_cond);
8568
8569         /* release media stream callback lock */
8570         g_mutex_clear(&player->media_stream_cb_lock);
8571
8572         MMPLAYER_FLEAVE();
8573
8574         return MM_ERROR_NONE;
8575 }
8576
8577 int
8578 __mmplayer_realize_streaming_ext(mm_player_t* player)
8579 {
8580         int ret = MM_ERROR_NONE;
8581
8582         MMPLAYER_FENTER();
8583         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8584
8585         if (MMPLAYER_IS_HTTP_PD(player)) {
8586                 gboolean bret = FALSE;
8587
8588                 player->pd_downloader = _mmplayer_create_pd_downloader();
8589                 if (!player->pd_downloader) {
8590                         LOGE("Unable to create PD Downloader...");
8591                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
8592                 }
8593
8594                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
8595
8596                 if (FALSE == bret) {
8597                         LOGE("Unable to create PD Downloader...");
8598                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
8599                 }
8600         }
8601
8602         MMPLAYER_FLEAVE();
8603         return ret;
8604 }
8605
8606 int
8607 _mmplayer_realize(MMHandleType hplayer)
8608 {
8609         mm_player_t* player = (mm_player_t*)hplayer;
8610         char *uri = NULL;
8611         void *param = NULL;
8612         MMHandleType attrs = 0;
8613         int ret = MM_ERROR_NONE;
8614
8615         MMPLAYER_FENTER();
8616
8617         /* check player handle */
8618         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED)
8619
8620         /* check current state */
8621         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_REALIZE);
8622
8623         attrs = MMPLAYER_GET_ATTRS(player);
8624         if (!attrs) {
8625                 LOGE("fail to get attributes.\n");
8626                 return MM_ERROR_PLAYER_INTERNAL;
8627         }
8628         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
8629         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
8630
8631         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_NONE) {
8632                 ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
8633
8634                 if (ret != MM_ERROR_NONE) {
8635                         LOGE("failed to parse profile\n");
8636                         return ret;
8637                 }
8638         }
8639
8640         if (uri && (strstr(uri, "es_buff://"))) {
8641                 if (strstr(uri, "es_buff://push_mode"))
8642                         player->es_player_push_mode = TRUE;
8643                 else
8644                         player->es_player_push_mode = FALSE;
8645         }
8646
8647         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS) {
8648                 LOGW("mms protocol is not supported format.\n");
8649                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
8650         }
8651
8652         if (MMPLAYER_IS_STREAMING(player))
8653                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
8654         else
8655                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
8656
8657         player->smooth_streaming = FALSE;
8658         player->videodec_linked  = 0;
8659         player->videosink_linked = 0;
8660         player->audiodec_linked  = 0;
8661         player->audiosink_linked = 0;
8662         player->textsink_linked = 0;
8663         player->is_external_subtitle_present = FALSE;
8664         player->is_external_subtitle_added_now = FALSE;
8665         /* set the subtitle ON default */
8666         player->is_subtitle_off = FALSE;
8667
8668         /* realize pipeline */
8669         ret = __gst_realize(player);
8670         if (ret != MM_ERROR_NONE)
8671                 LOGE("fail to realize the player.\n");
8672         else
8673                 ret = __mmplayer_realize_streaming_ext(player);
8674
8675         MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
8676
8677         MMPLAYER_FLEAVE();
8678
8679         return ret;
8680 }
8681
8682 int
8683 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
8684 {
8685         MMPLAYER_FENTER();
8686         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8687
8688         /* destroy can called at anytime */
8689         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
8690                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
8691
8692         MMPLAYER_FLEAVE();
8693         return MM_ERROR_NONE;
8694 }
8695
8696 int
8697 _mmplayer_unrealize(MMHandleType hplayer)
8698 {
8699         mm_player_t* player = (mm_player_t*)hplayer;
8700         int ret = MM_ERROR_NONE;
8701
8702         MMPLAYER_FENTER();
8703
8704         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8705
8706         MMPLAYER_CMD_UNLOCK(player);
8707         /* destroy the gst bus msg thread which is created during realize.
8708            this funct have to be called before getting cmd lock. */
8709         _mmplayer_bus_msg_thread_destroy(player);
8710         MMPLAYER_CMD_LOCK(player);
8711
8712         /* check current state */
8713         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_UNREALIZE);
8714
8715         /* check async state transition */
8716         __mmplayer_check_async_state_transition(player);
8717
8718         __mmplayer_unrealize_streaming_ext(player);
8719
8720         /* unrealize pipeline */
8721         ret = __gst_unrealize(player);
8722
8723         /* set asm stop if success */
8724         if (MM_ERROR_NONE == ret) {
8725                 if (!player->interrupted_by_resource) {
8726                         if (player->video_decoder_resource != NULL) {
8727                                 ret = mm_resource_manager_mark_for_release(player->resource_manager,
8728                                                 player->video_decoder_resource);
8729                                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
8730                                         LOGE("failed to mark decoder resource for release, ret(0x%x)\n", ret);
8731                                 else
8732                                         player->video_decoder_resource = NULL;
8733                         }
8734
8735                         if (player->video_overlay_resource != NULL) {
8736                                 ret = mm_resource_manager_mark_for_release(player->resource_manager,
8737                                                 player->video_overlay_resource);
8738                                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
8739                                         LOGE("failed to mark overlay resource for release, ret(0x%x)\n", ret);
8740                                 else
8741                                         player->video_overlay_resource = NULL;
8742                         }
8743
8744                         ret = mm_resource_manager_commit(player->resource_manager);
8745                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
8746                                 LOGE("failed to commit resource releases, ret(0x%x)\n", ret);
8747                 }
8748         } else
8749                 LOGE("failed and don't change asm state to stop");
8750
8751         MMPLAYER_FLEAVE();
8752
8753         return ret;
8754 }
8755
8756 int
8757 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param)
8758 {
8759         mm_player_t* player = (mm_player_t*)hplayer;
8760
8761         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8762
8763         return __gst_set_message_callback(player, callback, user_param);
8764 }
8765
8766 int
8767 _mmplayer_get_state(MMHandleType hplayer, int* state)
8768 {
8769         mm_player_t *player = (mm_player_t*)hplayer;
8770
8771         MMPLAYER_RETURN_VAL_IF_FAIL(state, MM_ERROR_INVALID_ARGUMENT);
8772
8773         *state = MMPLAYER_CURRENT_STATE(player);
8774
8775         return MM_ERROR_NONE;
8776 }
8777
8778
8779 int
8780 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume)
8781 {
8782         mm_player_t* player = (mm_player_t*) hplayer;
8783         GstElement* vol_element = NULL;
8784         int i = 0;
8785
8786         MMPLAYER_FENTER();
8787
8788         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8789
8790         LOGD("volume [L]=%f:[R]=%f\n",
8791                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
8792
8793         /* invalid factor range or not */
8794         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++) {
8795                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
8796                         LOGE("Invalid factor!(valid factor:0~1.0)\n");
8797                         return MM_ERROR_INVALID_ARGUMENT;
8798                 }
8799         }
8800
8801         /* not support to set other value into each channel */
8802         if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
8803                 return MM_ERROR_INVALID_ARGUMENT;
8804
8805         /* Save volume to handle. Currently the first array element will be saved. */
8806         player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
8807
8808         /* check pipeline handle */
8809         if (!player->pipeline || !player->pipeline->audiobin) {
8810                 LOGD("audiobin is not created yet\n");
8811                 LOGD("but, current stored volume will be set when it's created.\n");
8812
8813                 /* NOTE : stored volume will be used in create_audiobin
8814                  * returning MM_ERROR_NONE here makes application to able to
8815                  * set volume at anytime.
8816                  */
8817                 return MM_ERROR_NONE;
8818         }
8819
8820         /* setting volume to volume element */
8821         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
8822
8823         if (vol_element) {
8824                 LOGD("volume is set [%f]\n", player->sound.volume);
8825                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
8826         }
8827
8828         MMPLAYER_FLEAVE();
8829
8830         return MM_ERROR_NONE;
8831 }
8832
8833
8834 int
8835 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
8836 {
8837         mm_player_t* player = (mm_player_t*) hplayer;
8838         int i = 0;
8839
8840         MMPLAYER_FENTER();
8841
8842         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8843         MMPLAYER_RETURN_VAL_IF_FAIL(volume, MM_ERROR_INVALID_ARGUMENT);
8844
8845         /* returning stored volume */
8846         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
8847                 volume->level[i] = player->sound.volume;
8848
8849         MMPLAYER_FLEAVE();
8850
8851         return MM_ERROR_NONE;
8852 }
8853
8854 int
8855 _mmplayer_set_mute(MMHandleType hplayer, int mute)
8856 {
8857         mm_player_t* player = (mm_player_t*) hplayer;
8858         GstElement* vol_element = NULL;
8859
8860         MMPLAYER_FENTER();
8861
8862         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8863
8864         /* mute value shoud 0 or 1 */
8865         if (mute != 0 && mute != 1) {
8866                 LOGE("bad mute value\n");
8867
8868                 /* FIXIT : definitly, we need _BAD_PARAM error code */
8869                 return MM_ERROR_INVALID_ARGUMENT;
8870         }
8871
8872         player->sound.mute = mute;
8873
8874         /* just hold mute value if pipeline is not ready */
8875         if (!player->pipeline || !player->pipeline->audiobin) {
8876                 LOGD("pipeline is not ready. holding mute value\n");
8877                 return MM_ERROR_NONE;
8878         }
8879
8880         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
8881
8882         /* NOTE : volume will only created when the bt is enabled */
8883         if (vol_element) {
8884                 LOGD("mute : %d\n", mute);
8885                 g_object_set(vol_element, "mute", mute, NULL);
8886         } else
8887                 LOGD("volume elemnet is not created. using volume in audiosink\n");
8888
8889         MMPLAYER_FLEAVE();
8890
8891         return MM_ERROR_NONE;
8892 }
8893
8894 int
8895 _mmplayer_get_mute(MMHandleType hplayer, int* pmute)
8896 {
8897         mm_player_t* player = (mm_player_t*) hplayer;
8898
8899         MMPLAYER_FENTER();
8900
8901         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8902         MMPLAYER_RETURN_VAL_IF_FAIL(pmute, MM_ERROR_INVALID_ARGUMENT);
8903
8904         /* just hold mute value if pipeline is not ready */
8905         if (!player->pipeline || !player->pipeline->audiobin) {
8906                 LOGD("pipeline is not ready. returning stored value\n");
8907                 *pmute = player->sound.mute;
8908                 return MM_ERROR_NONE;
8909         }
8910
8911         *pmute = player->sound.mute;
8912
8913         MMPLAYER_FLEAVE();
8914
8915         return MM_ERROR_NONE;
8916 }
8917
8918 int
8919 _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
8920 {
8921         mm_player_t* player = (mm_player_t*) hplayer;
8922
8923         MMPLAYER_FENTER();
8924
8925         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8926
8927         player->video_stream_changed_cb = callback;
8928         player->video_stream_changed_cb_user_param = user_param;
8929         LOGD("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
8930
8931         MMPLAYER_FLEAVE();
8932
8933         return MM_ERROR_NONE;
8934 }
8935
8936 int
8937 _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
8938 {
8939         mm_player_t* player = (mm_player_t*) hplayer;
8940
8941         MMPLAYER_FENTER();
8942
8943         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8944
8945         player->audio_stream_changed_cb = callback;
8946         player->audio_stream_changed_cb_user_param = user_param;
8947         LOGD("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
8948
8949         MMPLAYER_FLEAVE();
8950
8951         return MM_ERROR_NONE;
8952 }
8953
8954 int
8955 _mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param)
8956 {
8957         mm_player_t* player = (mm_player_t*) hplayer;
8958
8959         MMPLAYER_FENTER();
8960
8961         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8962
8963         player->audio_stream_render_cb_ex = callback;
8964         player->audio_stream_cb_user_param = user_param;
8965         player->audio_stream_sink_sync = sync;
8966         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);
8967
8968         MMPLAYER_FLEAVE();
8969
8970         return MM_ERROR_NONE;
8971 }
8972
8973 int
8974 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param)
8975 {
8976         mm_player_t* player = (mm_player_t*) hplayer;
8977
8978         MMPLAYER_FENTER();
8979
8980         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8981
8982         if (callback && !player->bufmgr)
8983                 player->bufmgr = tbm_bufmgr_init(-1);
8984
8985         player->set_mode.media_packet_video_stream = (callback) ? TRUE : FALSE;
8986         player->video_stream_cb = callback;
8987         player->video_stream_cb_user_param = user_param;
8988
8989         LOGD("Stream cb Handle value is %p : %p, enable:%d\n", player, player->video_stream_cb, player->set_mode.media_packet_video_stream);
8990
8991         MMPLAYER_FLEAVE();
8992
8993         return MM_ERROR_NONE;
8994 }
8995
8996 int
8997 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param)
8998 {
8999         mm_player_t* player = (mm_player_t*) hplayer;
9000
9001         MMPLAYER_FENTER();
9002
9003         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9004
9005         player->audio_stream_cb = callback;
9006         player->audio_stream_cb_user_param = user_param;
9007         LOGD("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
9008
9009         MMPLAYER_FLEAVE();
9010
9011         return MM_ERROR_NONE;
9012 }
9013
9014 static int
9015 __mmplayer_start_streaming_ext(mm_player_t *player)
9016 {
9017         gint ret = MM_ERROR_NONE;
9018
9019         MMPLAYER_FENTER();
9020         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9021
9022         if (MMPLAYER_IS_HTTP_PD(player)) {
9023                 if (!player->pd_downloader) {
9024                         ret = __mmplayer_realize_streaming_ext(player);
9025
9026                         if (ret != MM_ERROR_NONE) {
9027                                 LOGE("failed to realize streaming ext\n");
9028                                 return ret;
9029                         }
9030                 }
9031
9032                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI) {
9033                         ret = _mmplayer_start_pd_downloader((MMHandleType)player);
9034                         if (!ret) {
9035                                 LOGE("ERROR while starting PD...\n");
9036                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
9037                         }
9038                         ret = MM_ERROR_NONE;
9039                 }
9040         }
9041
9042         MMPLAYER_FLEAVE();
9043         return ret;
9044 }
9045
9046 int
9047 _mmplayer_start(MMHandleType hplayer)
9048 {
9049         mm_player_t* player = (mm_player_t*) hplayer;
9050         gint ret = MM_ERROR_NONE;
9051
9052         MMPLAYER_FENTER();
9053
9054         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9055
9056         /* check current state */
9057         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_START);
9058
9059         /* NOTE : we should check and create pipeline again if not created as we destroy
9060          * whole pipeline when stopping in streamming playback
9061          */
9062         if (!player->pipeline) {
9063                 ret = __gst_realize(player);
9064                 if (MM_ERROR_NONE != ret) {
9065                         LOGE("failed to realize before starting. only in streamming\n");
9066                         /* unlock */
9067                         return ret;
9068                 }
9069         }
9070
9071         ret = __mmplayer_start_streaming_ext(player);
9072         if (ret != MM_ERROR_NONE) {
9073                 LOGE("failed to start streaming ext 0x%X", ret);
9074                 return ret;
9075         }
9076
9077         /* start pipeline */
9078         ret = __gst_start(player);
9079         if (ret != MM_ERROR_NONE)
9080                 LOGE("failed to start player.\n");
9081
9082         MMPLAYER_FLEAVE();
9083
9084         return ret;
9085 }
9086
9087 /* NOTE: post "not supported codec message" to application
9088  * when one codec is not found during AUTOPLUGGING in MSL.
9089  * So, it's separated with error of __mmplayer_gst_callback().
9090  * And, if any codec is not found, don't send message here.
9091  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
9092  */
9093 int
9094 __mmplayer_handle_missed_plugin(mm_player_t* player)
9095 {
9096         MMMessageParamType msg_param;
9097         memset(&msg_param, 0, sizeof(MMMessageParamType));
9098         gboolean post_msg_direct = FALSE;
9099
9100         MMPLAYER_FENTER();
9101
9102         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9103
9104         LOGD("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
9105                         player->not_supported_codec, player->can_support_codec);
9106
9107         if (player->not_found_demuxer) {
9108                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9109                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
9110
9111                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9112                 MMPLAYER_FREEIF(msg_param.data);
9113
9114                 return MM_ERROR_NONE;
9115         }
9116
9117         if (player->not_supported_codec) {
9118                 if (player->can_support_codec) {
9119                         // There is one codec to play
9120                         post_msg_direct = TRUE;
9121                 } else {
9122                         if (player->pipeline->audiobin) // Some content has only PCM data in container.
9123                                 post_msg_direct = TRUE;
9124                 }
9125
9126                 if (post_msg_direct) {
9127                         MMMessageParamType msg_param;
9128                         memset(&msg_param, 0, sizeof(MMMessageParamType));
9129
9130                         if (player->not_supported_codec ==  MISSING_PLUGIN_AUDIO) {
9131                                 LOGW("not found AUDIO codec, posting error code to application.\n");
9132
9133                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9134                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9135                         } else if (player->not_supported_codec ==  MISSING_PLUGIN_VIDEO) {
9136                                 LOGW("not found VIDEO codec, posting error code to application.\n");
9137
9138                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9139                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
9140                         }
9141
9142                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9143
9144                         MMPLAYER_FREEIF(msg_param.data);
9145
9146                         return MM_ERROR_NONE;
9147                 } else {
9148                         // no any supported codec case
9149                         LOGW("not found any codec, posting error code to application.\n");
9150
9151                         if (player->not_supported_codec ==  MISSING_PLUGIN_AUDIO) {
9152                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9153                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9154                         } else {
9155                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9156                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
9157                         }
9158
9159                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9160
9161                         MMPLAYER_FREEIF(msg_param.data);
9162                 }
9163         }
9164
9165         MMPLAYER_FLEAVE();
9166
9167         return MM_ERROR_NONE;
9168 }
9169
9170 static void __mmplayer_check_pipeline(mm_player_t* player)
9171 {
9172         GstState element_state = GST_STATE_VOID_PENDING;
9173         GstState element_pending_state = GST_STATE_VOID_PENDING;
9174         gint timeout = 0;
9175         int ret = MM_ERROR_NONE;
9176
9177         if (player->gapless.reconfigure) {
9178                 LOGW("pipeline is under construction.\n");
9179
9180                 MMPLAYER_PLAYBACK_LOCK(player);
9181                 MMPLAYER_PLAYBACK_UNLOCK(player);
9182
9183                 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
9184
9185                 /* wait for state transition */
9186                 ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND);
9187
9188                 if (ret == GST_STATE_CHANGE_FAILURE)
9189                         LOGE("failed to change pipeline state within %d sec\n", timeout);
9190         }
9191 }
9192
9193 /* NOTE : it should be able to call 'stop' anytime*/
9194 int
9195 _mmplayer_stop(MMHandleType hplayer)
9196 {
9197         mm_player_t* player = (mm_player_t*)hplayer;
9198         int ret = MM_ERROR_NONE;
9199
9200         MMPLAYER_FENTER();
9201
9202         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9203
9204         /* check current state */
9205         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_STOP);
9206
9207         /* check pipline building state */
9208         __mmplayer_check_pipeline(player);
9209         __mmplayer_reset_gapless_state(player);
9210
9211         /* NOTE : application should not wait for EOS after calling STOP */
9212         __mmplayer_cancel_eos_timer(player);
9213
9214         __mmplayer_unrealize_streaming_ext(player);
9215
9216         /* reset */
9217         player->doing_seek = FALSE;
9218
9219         /* stop pipeline */
9220         ret = __gst_stop(player);
9221
9222         if (ret != MM_ERROR_NONE)
9223                 LOGE("failed to stop player.\n");
9224
9225         MMPLAYER_FLEAVE();
9226
9227         return ret;
9228 }
9229
9230 int
9231 _mmplayer_pause(MMHandleType hplayer)
9232 {
9233         mm_player_t* player = (mm_player_t*)hplayer;
9234         gint64 pos_nsec = 0;
9235         gboolean async = FALSE;
9236         gint ret = MM_ERROR_NONE;
9237
9238         MMPLAYER_FENTER();
9239
9240         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9241
9242         /* check current state */
9243         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_PAUSE);
9244
9245         /* check pipline building state */
9246         __mmplayer_check_pipeline(player);
9247
9248         switch (MMPLAYER_CURRENT_STATE(player)) {
9249         case MM_PLAYER_STATE_READY:
9250                 {
9251                         /* check prepare async or not.
9252                          * In the case of streaming playback, it's recommned to avoid blocking wait.
9253                          */
9254                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
9255                         LOGD("prepare working mode : %s", (async ? "async" : "sync"));
9256
9257                         /* Changing back sync of rtspsrc to async */
9258                         if (MMPLAYER_IS_RTSP_STREAMING(player)) {
9259                                 LOGD("async prepare working mode for rtsp");
9260                                 async = TRUE;
9261                         }
9262                 }
9263                 break;
9264
9265         case MM_PLAYER_STATE_PLAYING:
9266                 {
9267                         /* NOTE : store current point to overcome some bad operation
9268                         *(returning zero when getting current position in paused state) of some
9269                         * elements
9270                         */
9271                         if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
9272                                 LOGW("getting current position failed in paused\n");
9273
9274                         player->last_position = pos_nsec;
9275
9276                         /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
9277                            But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
9278                            This causes problem is position calculation during normal pause resume scenarios also.
9279                            Currently during pause , we are sending the current position to rtspsrc module for position saving. */
9280                         if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
9281                                 (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
9282                                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
9283                         }
9284                 }
9285                 break;
9286         }
9287
9288         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
9289                 LOGD("doing async pause in case of ms buff src");
9290                 async = TRUE;
9291         }
9292
9293         /* pause pipeline */
9294         ret = __gst_pause(player, async);
9295
9296         if (ret != MM_ERROR_NONE)
9297                 LOGE("failed to pause player. ret : 0x%x\n", ret);
9298
9299         if (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) {
9300                 if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "display_rotation"))
9301                         LOGE("failed to update display_rotation");
9302         }
9303
9304         MMPLAYER_FLEAVE();
9305
9306         return ret;
9307 }
9308
9309 int
9310 _mmplayer_resume(MMHandleType hplayer)
9311 {
9312         mm_player_t* player = (mm_player_t*)hplayer;
9313         int ret = MM_ERROR_NONE;
9314         gboolean async = FALSE;
9315
9316         MMPLAYER_FENTER();
9317
9318         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9319
9320         /* Changing back sync mode rtspsrc to async */
9321         if ((MMPLAYER_IS_RTSP_STREAMING(player))) {
9322                 LOGD("async resume for rtsp case");
9323                 async = TRUE;
9324         }
9325
9326         /* check current state */
9327         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_RESUME);
9328
9329         ret = __gst_resume(player, async);
9330
9331         if (ret != MM_ERROR_NONE)
9332                 LOGE("failed to resume player.\n");
9333
9334         MMPLAYER_FLEAVE();
9335
9336         return ret;
9337 }
9338
9339 static int
9340 __mmplayer_set_pcm_extraction(mm_player_t* player)
9341 {
9342         gint64 start_nsec = 0;
9343         gint64 end_nsec = 0;
9344         gint64 dur_nsec = 0;
9345         gint64 dur_msec = 0;
9346         int required_start = 0;
9347         int required_end = 0;
9348         int ret = 0;
9349
9350         MMPLAYER_FENTER();
9351
9352         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
9353
9354         mm_attrs_multiple_get(player->attrs,
9355                 NULL,
9356                 "pcm_extraction_start_msec", &required_start,
9357                 "pcm_extraction_end_msec", &required_end,
9358                 NULL);
9359
9360         LOGD("pcm extraction required position is from [%d] to [%d](msec)\n", required_start, required_end);
9361
9362         if (required_start == 0 && required_end == 0) {
9363                 LOGD("extracting entire stream");
9364                 return MM_ERROR_NONE;
9365         } else if (required_start < 0 || required_start > required_end || required_end < 0) {
9366                 LOGD("invalid range for pcm extraction");
9367                 return MM_ERROR_INVALID_ARGUMENT;
9368         }
9369
9370         /* get duration */
9371         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
9372         if (!ret) {
9373                 LOGE("failed to get duration");
9374                 return MM_ERROR_PLAYER_INTERNAL;
9375         }
9376         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
9377
9378         if (dur_msec < required_end) {
9379                 // FIXME
9380                 LOGD("invalid end pos for pcm extraction");
9381                 return MM_ERROR_INVALID_ARGUMENT;
9382         }
9383
9384         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
9385         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
9386
9387         if ((!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
9388                                         1.0,
9389                                         GST_FORMAT_TIME,
9390                                         (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
9391                                         GST_SEEK_TYPE_SET, start_nsec,
9392                                         GST_SEEK_TYPE_SET, end_nsec))) {
9393                 LOGE("failed to seek for pcm extraction\n");
9394
9395                 return MM_ERROR_PLAYER_SEEK;
9396         }
9397
9398         LOGD("succeeded to set up segment extraction from [%llu] to [%llu](nsec)\n", start_nsec, end_nsec);
9399
9400         MMPLAYER_FLEAVE();
9401
9402         return MM_ERROR_NONE;
9403 }
9404
9405 int
9406 _mmplayer_set_playspeed(MMHandleType hplayer, float rate, bool streaming)
9407 {
9408         mm_player_t* player = (mm_player_t*)hplayer;
9409         gint64 pos_nsec = 0;
9410         int ret = MM_ERROR_NONE;
9411         int mute = FALSE;
9412         signed long long start = 0, stop = 0;
9413         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
9414         MMPLAYER_FENTER();
9415
9416         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
9417         MMPLAYER_RETURN_VAL_IF_FAIL(streaming || !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API);
9418
9419         /* The sound of video is not supported under 0.0 and over 2.0. */
9420         if (rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN) {
9421                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
9422                         mute = TRUE;
9423         }
9424         _mmplayer_set_mute(hplayer, mute);
9425
9426         if (player->playback_rate == rate)
9427                 return MM_ERROR_NONE;
9428
9429         /* If the position is reached at start potion during fast backward, EOS is posted.
9430          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
9431          * */
9432         player->playback_rate = rate;
9433
9434         current_state = MMPLAYER_CURRENT_STATE(player);
9435
9436         if (current_state != MM_PLAYER_STATE_PAUSED)
9437                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec);
9438
9439         LOGD("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_nsec), ret, current_state);
9440
9441         if ((current_state == MM_PLAYER_STATE_PAUSED)
9442                 || (!ret) /*|| (player->last_position != 0 && pos_msec == 0)*/) {
9443                 LOGW("returning last point : %"G_GINT64_FORMAT, player->last_position);
9444                 pos_nsec = player->last_position;
9445         }
9446
9447         if (rate >= 0) {
9448                 start = pos_nsec;
9449                 stop = GST_CLOCK_TIME_NONE;
9450         } else {
9451                 start = GST_CLOCK_TIME_NONE;
9452                 stop = pos_nsec;
9453         }
9454
9455         if (!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
9456                                 player->playback_rate,
9457                                 GST_FORMAT_TIME,
9458                                 (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
9459                                 GST_SEEK_TYPE_SET, start,
9460                                 GST_SEEK_TYPE_SET, stop)) {
9461                 LOGE("failed to set speed playback\n");
9462                 return MM_ERROR_PLAYER_SEEK;
9463         }
9464
9465         LOGD("succeeded to set speed playback as %0.1f\n", rate);
9466
9467         MMPLAYER_FLEAVE();
9468
9469         return MM_ERROR_NONE;;
9470 }
9471
9472 int
9473 _mmplayer_set_position(MMHandleType hplayer, int format, gint64 position)
9474 {
9475         mm_player_t* player = (mm_player_t*)hplayer;
9476         int ret = MM_ERROR_NONE;
9477
9478         MMPLAYER_FENTER();
9479
9480         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9481
9482         /* check pipline building state */
9483         __mmplayer_check_pipeline(player);
9484
9485         ret = __gst_set_position(player, format, position, FALSE);
9486
9487         MMPLAYER_FLEAVE();
9488
9489         return ret;
9490 }
9491
9492 int
9493 _mmplayer_get_position(MMHandleType hplayer, int format, gint64 *position)
9494 {
9495         mm_player_t* player = (mm_player_t*)hplayer;
9496         int ret = MM_ERROR_NONE;
9497
9498         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9499
9500         ret = __gst_get_position(player, format, position);
9501
9502         return ret;
9503 }
9504
9505 int
9506 _mmplayer_get_duration(MMHandleType hplayer, gint64 *duration)
9507 {
9508         mm_player_t* player = (mm_player_t*)hplayer;
9509         int ret = MM_ERROR_NONE;
9510
9511         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9512         MMPLAYER_RETURN_VAL_IF_FAIL(duration, MM_ERROR_COMMON_INVALID_ARGUMENT);
9513
9514         *duration = player->duration;
9515         return ret;
9516 }
9517
9518 int
9519 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos)
9520 {
9521         mm_player_t* player = (mm_player_t*)hplayer;
9522         int ret = MM_ERROR_NONE;
9523
9524         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9525
9526         ret = __gst_get_buffer_position(player, format, start_pos, stop_pos);
9527
9528         return ret;
9529 }
9530
9531 int
9532 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position)
9533 {
9534         mm_player_t* player = (mm_player_t*)hplayer;
9535         int ret = MM_ERROR_NONE;
9536
9537         MMPLAYER_FENTER();
9538
9539         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9540
9541         ret = __gst_adjust_subtitle_position(player, format, position);
9542
9543         MMPLAYER_FLEAVE();
9544
9545         return ret;
9546 }
9547
9548 static gboolean
9549 __mmplayer_is_midi_type(gchar* str_caps)
9550 {
9551         if ((g_strrstr(str_caps, "audio/midi")) ||
9552                 (g_strrstr(str_caps, "application/x-gst_ff-mmf")) ||
9553                 (g_strrstr(str_caps, "application/x-smaf")) ||
9554                 (g_strrstr(str_caps, "audio/x-imelody")) ||
9555                 (g_strrstr(str_caps, "audio/mobile-xmf")) ||
9556                 (g_strrstr(str_caps, "audio/xmf")) ||
9557                 (g_strrstr(str_caps, "audio/mxmf"))) {
9558                 LOGD("midi\n");
9559                 return TRUE;
9560         }
9561
9562         return FALSE;
9563 }
9564
9565 static gboolean
9566 __mmplayer_is_only_mp3_type(gchar *str_caps)
9567 {
9568         if (g_strrstr(str_caps, "application/x-id3") ||
9569                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion= (int)1")))
9570                 return TRUE;
9571         return FALSE;
9572 }
9573
9574 static void
9575 __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps)
9576 {
9577         GstStructure* caps_structure = NULL;
9578         gint samplerate = 0;
9579         gint channels = 0;
9580
9581         MMPLAYER_FENTER();
9582         MMPLAYER_RETURN_IF_FAIL(player && caps);
9583
9584         caps_structure = gst_caps_get_structure(caps, 0);
9585
9586         /* set stream information */
9587         gst_structure_get_int(caps_structure, "rate", &samplerate);
9588         mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
9589
9590         gst_structure_get_int(caps_structure, "channels", &channels);
9591         mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
9592
9593         LOGD("audio samplerate : %d     channels : %d\n", samplerate, channels);
9594 }
9595
9596 static void
9597 __mmplayer_update_content_type_info(mm_player_t* player)
9598 {
9599         MMPLAYER_FENTER();
9600         MMPLAYER_RETURN_IF_FAIL(player && player->type);
9601
9602         if (__mmplayer_is_midi_type(player->type)) {
9603                 player->bypass_audio_effect = TRUE;
9604         } else if (g_strrstr(player->type, "application/x-hls")) {
9605                 /* If it can't know exact type when it parses uri because of redirection case,
9606                  * it will be fixed by typefinder or when doing autoplugging.
9607                  */
9608                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
9609                 if (player->streamer) {
9610                         player->streamer->is_adaptive_streaming = TRUE;
9611                         player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
9612                         player->streamer->buffering_req.rebuffer_time = 5 * 1000;
9613                 }
9614         } else if (g_strrstr(player->type, "application/dash+xml")) {
9615                 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
9616         }
9617
9618         MMPLAYER_FLEAVE();
9619 }
9620
9621 static void
9622 __mmplayer_typefind_have_type(GstElement *tf, guint probability,
9623 GstCaps *caps, gpointer data)
9624 {
9625         mm_player_t* player = (mm_player_t*)data;
9626         GstPad* pad = NULL;
9627
9628         MMPLAYER_FENTER();
9629
9630         MMPLAYER_RETURN_IF_FAIL(player && tf && caps);
9631
9632         /* store type string */
9633         MMPLAYER_FREEIF(player->type);
9634         player->type = gst_caps_to_string(caps);
9635         if (player->type) {
9636                 LOGD("[handle: %p] media type %s found, probability %d%% / %d\n",
9637                                 player, player->type, probability, gst_caps_get_size(caps));
9638         }
9639
9640         if ((!MMPLAYER_IS_RTSP_STREAMING(player)) &&
9641                 (g_strrstr(player->type, "audio/x-raw-int"))) {
9642                 LOGE("not support media format\n");
9643
9644                 if (player->msg_posted == FALSE) {
9645                         MMMessageParamType msg_param;
9646                         memset(&msg_param, 0, sizeof(MMMessageParamType));
9647
9648                         msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
9649                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9650
9651                         /* don't post more if one was sent already */
9652                         player->msg_posted = TRUE;
9653                 }
9654                 return;
9655         }
9656
9657         __mmplayer_update_content_type_info(player);
9658
9659         pad = gst_element_get_static_pad(tf, "src");
9660         if (!pad) {
9661                 LOGE("fail to get typefind src pad.\n");
9662                 return;
9663         }
9664
9665         if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
9666                 gboolean async = FALSE;
9667                 LOGE("failed to autoplug %s\n", player->type);
9668
9669                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
9670
9671                 if (async && player->msg_posted == FALSE)
9672                         __mmplayer_handle_missed_plugin(player);
9673
9674                 goto DONE;
9675         }
9676
9677 DONE:
9678         gst_object_unref(GST_OBJECT(pad));
9679
9680         MMPLAYER_FLEAVE();
9681
9682         return;
9683 }
9684
9685 static GstElement *
9686 __mmplayer_create_decodebin(mm_player_t* player)
9687 {
9688         GstElement *decodebin = NULL;
9689
9690         MMPLAYER_FENTER();
9691
9692         /* create decodebin */
9693         decodebin = gst_element_factory_make("decodebin", NULL);
9694
9695         if (!decodebin) {
9696                 LOGE("fail to create decodebin\n");
9697                 goto ERROR;
9698         }
9699
9700         /* raw pad handling signal */
9701         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
9702                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
9703
9704         /* no-more-pad pad handling signal */
9705         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
9706                                                 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
9707
9708         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
9709                                                 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
9710
9711         /* This signal is emitted when a pad for which there is no further possible
9712            decoding is added to the decodebin.*/
9713         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
9714                                                 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player);
9715
9716         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
9717            before looking for any elements that can handle that stream.*/
9718         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
9719                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
9720
9721         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
9722            before looking for any elements that can handle that stream.*/
9723         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
9724                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
9725
9726         /* This signal is emitted once decodebin has finished decoding all the data.*/
9727         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
9728                                                 G_CALLBACK(__mmplayer_gst_decode_drained), player);
9729
9730         /* This signal is emitted when a element is added to the bin.*/
9731         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
9732                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
9733
9734 ERROR:
9735         return decodebin;
9736 }
9737
9738 static gboolean
9739 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
9740 {
9741         MMPlayerGstElement* mainbin = NULL;
9742         GstElement* decodebin = NULL;
9743         GstElement* queue2 = NULL;
9744         GstPad* sinkpad = NULL;
9745         GstPad* qsrcpad = NULL;
9746         gint64 dur_bytes = 0L;
9747
9748         guint max_buffer_size_bytes = 0;
9749         gint init_buffering_time = player->streamer->buffering_req.prebuffer_time;
9750
9751         MMPLAYER_FENTER();
9752         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, FALSE);
9753
9754         mainbin = player->pipeline->mainbin;
9755
9756         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
9757                 (MMPLAYER_IS_HTTP_STREAMING(player))) {
9758                 LOGD("creating http streaming buffering queue(queue2)\n");
9759
9760                 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
9761                         LOGE("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
9762                 } else {
9763                         queue2 = gst_element_factory_make("queue2", "queue2");
9764                         if (!queue2) {
9765                                 LOGE("failed to create buffering queue element\n");
9766                                 goto ERROR;
9767                         }
9768
9769                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) {
9770                                 LOGE("failed to add buffering queue\n");
9771                                 goto ERROR;
9772                         }
9773
9774                         sinkpad = gst_element_get_static_pad(queue2, "sink");
9775                         qsrcpad = gst_element_get_static_pad(queue2, "src");
9776
9777                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
9778                                 LOGE("failed to link buffering queue");
9779                                 goto ERROR;
9780                         }
9781
9782                         if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
9783                                 LOGE("fail to get duration");
9784
9785                         LOGD("dur_bytes = %"G_GINT64_FORMAT, dur_bytes);
9786
9787                         muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
9788
9789                         if (dur_bytes > 0) {
9790                                 if (MMPLAYER_USE_FILE_FOR_BUFFERING(player)) {
9791                                         type = MUXED_BUFFER_TYPE_FILE;
9792                                 } else {
9793                                         type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
9794                                         player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
9795                                 }
9796                         } else {
9797                                 dur_bytes = 0;
9798                         }
9799
9800                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
9801                         // if (!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
9802                         if (!g_strrstr(player->type, "video/mpegts")) {
9803                                 max_buffer_size_bytes = (type == MUXED_BUFFER_TYPE_FILE) ? (player->ini.http_max_size_bytes) : (5*1024*1024);
9804                                 LOGD("max_buffer_size_bytes = %d", max_buffer_size_bytes);
9805
9806                                 /* FIXME : pass ini setting directly. is this ok? */
9807                                 __mm_player_streaming_set_queue2(player->streamer,
9808                                                                                                 queue2,
9809                                                                                                 FALSE,
9810                                                                                                 max_buffer_size_bytes,
9811                                                                                                 player->ini.http_buffering_time,
9812                                                                                                 1.0,                                                            // no meaning
9813                                                                                                 player->ini.http_buffering_limit,       // no meaning
9814                                                                                                 type,
9815                                                                                                 player->http_file_buffering_path,
9816                                                                                                 (guint64)dur_bytes);
9817                         }
9818
9819                         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(queue2)) {
9820                                 LOGE("failed to sync queue2 state with parent\n");
9821                                 goto ERROR;
9822                         }
9823
9824                         srcpad = qsrcpad;
9825
9826                         gst_object_unref(GST_OBJECT(sinkpad));
9827
9828                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
9829                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
9830                 }
9831         }
9832
9833         /* create decodebin */
9834         decodebin = __mmplayer_create_decodebin(player);
9835
9836         if (!decodebin) {
9837                 LOGE("can not create autoplug element\n");
9838                 goto ERROR;
9839         }
9840
9841         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
9842                 LOGE("failed to add decodebin\n");
9843                 goto ERROR;
9844         }
9845
9846         /* to force caps on the decodebin element and avoid reparsing stuff by
9847         * typefind. It also avoids a deadlock in the way typefind activates pads in
9848         * the state change */
9849         g_object_set(decodebin, "sink-caps", caps, NULL);
9850
9851         sinkpad = gst_element_get_static_pad(decodebin, "sink");
9852
9853         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
9854                 LOGE("failed to link decodebin\n");
9855                 goto ERROR;
9856         }
9857
9858         gst_object_unref(GST_OBJECT(sinkpad));
9859
9860         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
9861         mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin;
9862
9863         /* set decodebin property about buffer in streaming playback. *
9864          * in case of HLS/DASH, it does not need to have big buffer        *
9865          * because it is kind of adaptive streaming.                  */
9866         if (!MMPLAYER_IS_HTTP_PD(player) && MMPLAYER_IS_HTTP_STREAMING(player)) {
9867                 guint max_size_bytes = MAX_DECODEBIN_BUFFER_BYTES;
9868                 guint64 max_size_time = MAX_DECODEBIN_BUFFER_TIME;
9869                 init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
9870
9871                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
9872                         || MMPLAYER_IS_DASH_STREAMING(player)) {
9873                         max_size_bytes = MAX_DECODEBIN_ADAPTIVE_BUFFER_BYTES;
9874                         max_size_time = MAX_DECODEBIN_ADAPTIVE_BUFFER_TIME;
9875                 }
9876
9877                 g_object_set(G_OBJECT(decodebin), "use-buffering", TRUE,
9878                                                                                         "high-percent", (gint)player->ini.http_buffering_limit,
9879                                                                                         "low-percent", 1,   // 1%
9880                                                                                         "max-size-bytes", max_size_bytes,
9881                                                                                         "max-size-time", (guint64)(max_size_time * GST_SECOND),
9882                                                                                         "max-size-buffers", 0, NULL);  // disable or automatic
9883         }
9884
9885         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin)) {
9886                 LOGE("failed to sync decodebin state with parent\n");
9887                 goto ERROR;
9888         }
9889
9890         MMPLAYER_FLEAVE();
9891
9892         return TRUE;
9893
9894 ERROR:
9895
9896         if (sinkpad)
9897                 gst_object_unref(GST_OBJECT(sinkpad));
9898
9899         if (queue2) {
9900                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
9901                  * You need to explicitly set elements to the NULL state before
9902                  * dropping the final reference, to allow them to clean up.
9903                  */
9904                 gst_element_set_state(queue2, GST_STATE_NULL);
9905
9906                 /* And, it still has a parent "player".
9907                  * You need to let the parent manage the object instead of unreffing the object directly.
9908                  */
9909                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
9910                 gst_object_unref(queue2);
9911                 queue2 = NULL;
9912         }
9913
9914         if (decodebin) {
9915                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
9916                  * You need to explicitly set elements to the NULL state before
9917                  * dropping the final reference, to allow them to clean up.
9918                  */
9919                 gst_element_set_state(decodebin, GST_STATE_NULL);
9920
9921                 /* And, it still has a parent "player".
9922                  * You need to let the parent manage the object instead of unreffing the object directly.
9923                  */
9924
9925                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
9926                 gst_object_unref(decodebin);
9927                 decodebin = NULL;
9928         }
9929
9930         return FALSE;
9931 }
9932
9933 static int
9934 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
9935 {
9936         MMPLAYER_FENTER();
9937
9938         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
9939         MMPLAYER_RETURN_VAL_IF_FAIL(mime, MM_ERROR_INVALID_ARGUMENT);
9940
9941         LOGD("class : %s, mime : %s \n", factory_class, mime);
9942
9943         /* add missing plugin */
9944         /* NOTE : msl should check missing plugin for image mime type.
9945          * Some motion jpeg clips can have playable audio track.
9946          * So, msl have to play audio after displaying popup written video format not supported.
9947          */
9948         if (!(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)) {
9949                 if (!(player->can_support_codec | player->videodec_linked | player->audiodec_linked)) {
9950                         LOGD("not found demuxer\n");
9951                         player->not_found_demuxer = TRUE;
9952                         player->unlinked_demuxer_mime = g_strdup_printf("%s", mime);
9953
9954                         goto DONE;
9955                 }
9956         }
9957
9958         if (!g_strrstr(factory_class, "Demuxer")) {
9959                 if ((g_str_has_prefix(mime, "video")) || (g_str_has_prefix(mime, "image"))) {
9960                         LOGD("can support codec=0x%X, vdec_linked=%d, adec_linked=%d\n",
9961                                 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
9962
9963                         /* check that clip have multi tracks or not */
9964                         if ((player->can_support_codec & FOUND_PLUGIN_VIDEO) && (player->videodec_linked)) {
9965                                 LOGD("video plugin is already linked\n");
9966                         } else {
9967                                 LOGW("add VIDEO to missing plugin\n");
9968                                 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
9969                                 player->unlinked_video_mime = g_strdup_printf("%s", mime);
9970                         }
9971                 } else if (g_str_has_prefix(mime, "audio")) {
9972                         if ((player->can_support_codec & FOUND_PLUGIN_AUDIO) && (player->audiodec_linked)) {
9973                                 LOGD("audio plugin is already linked\n");
9974                         } else {
9975                                 LOGW("add AUDIO to missing plugin\n");
9976                                 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
9977                                 player->unlinked_audio_mime = g_strdup_printf("%s", mime);
9978                         }
9979                 }
9980         }
9981
9982 DONE:
9983         MMPLAYER_FLEAVE();
9984
9985         return MM_ERROR_NONE;
9986 }
9987
9988
9989 static void
9990 __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
9991 {
9992         mm_player_t* player = (mm_player_t*)data;
9993
9994         MMPLAYER_FENTER();
9995
9996         MMPLAYER_RETURN_IF_FAIL(player);
9997
9998         /* remove fakesink. */
9999         if (!__mmplayer_gst_remove_fakesink(player,
10000                                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK])) {
10001                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
10002                  * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
10003                  * source element are not same. To overcome this situation, this function will called
10004                  * several places and several times. Therefore, this is not an error case.
10005                  */
10006                 return;
10007         }
10008
10009         LOGD("[handle: %p] pipeline has completely constructed", player);
10010
10011         if ((player->ini.async_start) &&
10012                 (player->msg_posted == FALSE) &&
10013                 (player->cmd >= MMPLAYER_COMMAND_START))
10014                 __mmplayer_handle_missed_plugin(player);
10015
10016         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-complete");
10017 }
10018
10019 static gboolean
10020 __mmplayer_verify_next_play_path(mm_player_t *player)
10021 {
10022         MMHandleType attrs = 0;
10023         MMPlayerParseProfile profile;
10024         gint uri_idx = 0, check_cnt = 0;
10025         char *uri = NULL;
10026         gint mode = MM_PLAYER_PD_MODE_NONE;
10027         gint video = 0;
10028         gint count = 0;
10029         gint gapless = 0;
10030         guint num_of_list = 0;
10031         static int profile_tv = -1;
10032
10033         MMPLAYER_FENTER();
10034
10035         LOGD("checking for gapless play");
10036
10037         if (player->pipeline->textbin) {
10038                 LOGE("subtitle path is enabled. gapless play is not supported.\n");
10039                 goto ERROR;
10040         }
10041
10042         attrs = MMPLAYER_GET_ATTRS(player);
10043         if (!attrs) {
10044                 LOGE("fail to get attributes.\n");
10045                 goto ERROR;
10046         }
10047
10048         mm_attrs_get_int_by_name(attrs, "content_video_found", &video);
10049
10050         if (__builtin_expect(profile_tv == -1, 0)) {
10051                 char *profileName;
10052                 system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
10053                 switch (*profileName) {
10054                 case 't':
10055                 case 'T':
10056                         profile_tv = 1;
10057                         break;
10058                 default:
10059                         profile_tv = 0;
10060                 }
10061                 free(profileName);
10062         }
10063         /* gapless playback is not supported in case of video at TV profile. */
10064         if (profile_tv && video) {
10065                 LOGW("not support video gapless playback");
10066                 goto ERROR;
10067         }
10068
10069         if (mm_attrs_get_int_by_name(attrs, "pd_mode", &mode) == MM_ERROR_NONE) {
10070                 if (mode == TRUE) {
10071                         LOGW("pd mode\n");
10072                         goto ERROR;
10073                 }
10074         }
10075
10076         if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
10077                 LOGE("can not get play count\n");
10078
10079         if (mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless) != MM_ERROR_NONE)
10080                 LOGE("can not get gapless mode\n");
10081
10082         if (video && !gapless) {
10083                 LOGW("not enabled video gapless playback");
10084                 goto ERROR;
10085         }
10086
10087         if ((count == -1 || count > 1)) /* enable gapless when looping or repeat */
10088                 gapless = 1;
10089
10090         if (!gapless) {
10091                 LOGW("gapless is disabled\n");  /* FIXME: playlist(without gapless) is not implemented. */
10092                 goto ERROR;
10093         }
10094
10095         num_of_list = g_list_length(player->uri_info.uri_list);
10096
10097         LOGD("repeat count = %d, num_of_list = %d\n", count, num_of_list);
10098
10099         if (num_of_list == 0) {
10100                 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE) {
10101                         LOGE("can not get profile_uri\n");
10102                         goto ERROR;
10103                 }
10104
10105                 if (!uri) {
10106                         LOGE("uri list is empty.\n");
10107                         goto ERROR;
10108                 }
10109
10110                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
10111                 LOGD("add original path : %s ", uri);
10112
10113                 num_of_list = 1;
10114                 uri = NULL;
10115         }
10116
10117         uri_idx = player->uri_info.uri_idx;
10118
10119         while (TRUE) {
10120                 check_cnt++;
10121
10122                 if (check_cnt > num_of_list) {
10123                         LOGE("there is no valid uri.");
10124                         goto ERROR;
10125                 }
10126
10127                 LOGD("uri idx : %d / %d\n", uri_idx, num_of_list);
10128
10129                 if (uri_idx < num_of_list-1) {
10130                         uri_idx++;
10131                 } else {
10132                         if ((count <= 1) && (count != -1)) {
10133                                 LOGD("no repeat.");
10134                                 goto ERROR;
10135                         } else if (count > 1) {
10136                                 /* decrease play count */
10137                                 /* we succeeded to rewind. update play count and then wait for next EOS */
10138                                 count--;
10139
10140                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
10141
10142                                 /* commit attribute */
10143                                 if (mmf_attrs_commit(attrs))
10144                                         LOGE("failed to commit attribute\n");
10145                         }
10146
10147                         /* count < 0 : repeat continually */
10148                         uri_idx = 0;
10149                 }
10150
10151                 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
10152                 LOGD("uri idx : %d, uri = %s\n", uri_idx, uri);
10153
10154                 if (uri == NULL) {
10155                         LOGW("next uri does not exist\n");
10156                         continue;
10157                 }
10158
10159                 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE) {
10160                         LOGE("failed to parse profile\n");
10161                         continue;
10162                 }
10163
10164                 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
10165                         (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP)) {
10166                         LOGW("uri type is not supported(%d).", profile.uri_type);
10167                         continue;
10168                 }
10169
10170                 break;
10171         }
10172
10173         player->uri_info.uri_idx = uri_idx;
10174         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
10175
10176         if (mmf_attrs_commit(player->attrs)) {
10177                 LOGE("failed to commit.\n");
10178                 goto ERROR;
10179         }
10180
10181         LOGD("next uri %s(%d)\n", uri, uri_idx);
10182
10183         return TRUE;
10184
10185 ERROR:
10186
10187         LOGE("unable to play next path. EOS will be posted soon.\n");
10188         return FALSE;
10189 }
10190
10191 static void
10192 __mmplayer_initialize_next_play(mm_player_t *player)
10193 {
10194         int i;
10195
10196         MMPLAYER_FENTER();
10197
10198         player->smooth_streaming = FALSE;
10199         player->videodec_linked = 0;
10200         player->audiodec_linked = 0;
10201         player->videosink_linked = 0;
10202         player->audiosink_linked = 0;
10203         player->textsink_linked = 0;
10204         player->is_external_subtitle_present = FALSE;
10205         player->is_external_subtitle_added_now = FALSE;
10206         player->not_supported_codec = MISSING_PLUGIN_NONE;
10207         player->can_support_codec = FOUND_PLUGIN_NONE;
10208         player->pending_seek.is_pending = FALSE;
10209         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
10210         player->pending_seek.pos = 0;
10211         player->msg_posted = FALSE;
10212         player->has_many_types = FALSE;
10213         player->no_more_pad = FALSE;
10214         player->not_found_demuxer = 0;
10215         player->doing_seek = FALSE;
10216         player->max_audio_channels = 0;
10217         player->is_subtitle_force_drop = FALSE;
10218         player->play_subtitle = FALSE;
10219         player->adjust_subtitle_pos = 0;
10220
10221         player->total_bitrate = 0;
10222         player->total_maximum_bitrate = 0;
10223
10224         _mmplayer_track_initialize(player);
10225         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
10226
10227         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
10228                 player->bitrate[i] = 0;
10229                 player->maximum_bitrate[i] = 0;
10230         }
10231
10232         if (player->v_stream_caps) {
10233                 gst_caps_unref(player->v_stream_caps);
10234                 player->v_stream_caps = NULL;
10235         }
10236
10237         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
10238
10239         /* clean found parsers */
10240         if (player->parsers) {
10241                 GList *parsers = player->parsers;
10242                 for (; parsers; parsers = g_list_next(parsers)) {
10243                         gchar *name = parsers->data;
10244                         MMPLAYER_FREEIF(name);
10245                 }
10246                 g_list_free(player->parsers);
10247                 player->parsers = NULL;
10248         }
10249
10250         /* clean found audio decoders */
10251         if (player->audio_decoders) {
10252                 GList *a_dec = player->audio_decoders;
10253                 for (; a_dec; a_dec = g_list_next(a_dec)) {
10254                         gchar *name = a_dec->data;
10255                         MMPLAYER_FREEIF(name);
10256                 }
10257                 g_list_free(player->audio_decoders);
10258                 player->audio_decoders = NULL;
10259         }
10260
10261         MMPLAYER_FLEAVE();
10262 }
10263
10264 static void
10265 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
10266 {
10267         MMPlayerGstElement *mainbin = NULL;
10268         MMMessageParamType msg_param = {0,};
10269         GstElement *element = NULL;
10270         MMHandleType attrs = 0;
10271         char *uri = NULL;
10272         enum MainElementID elemId = MMPLAYER_M_NUM;
10273
10274         MMPLAYER_FENTER();
10275
10276         if ((player == NULL) ||
10277                 (player->pipeline == NULL) ||
10278                 (player->pipeline->mainbin == NULL)) {
10279                 LOGE("player is null.\n");
10280                 goto ERROR;
10281         }
10282
10283         mainbin = player->pipeline->mainbin;
10284         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
10285
10286         attrs = MMPLAYER_GET_ATTRS(player);
10287         if (!attrs) {
10288                 LOGE("fail to get attributes.\n");
10289                 goto ERROR;
10290         }
10291
10292         /* Initialize Player values */
10293         __mmplayer_initialize_next_play(player);
10294
10295         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
10296
10297         if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE) {
10298                 LOGE("failed to parse profile\n");
10299                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
10300                 goto ERROR;
10301         }
10302
10303         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
10304                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player))) {
10305                 LOGE("it's dash or hls. not support.");
10306                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
10307                 goto ERROR;
10308         }
10309
10310         /* setup source */
10311         switch (player->profile.uri_type) {
10312         /* file source */
10313         case MM_PLAYER_URI_TYPE_FILE:
10314         {
10315                 LOGD("using filesrc for 'file://' handler.\n");
10316                 if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
10317                         LOGE("failed to get storage info");
10318                         break;
10319                 }
10320
10321                 element = gst_element_factory_make("filesrc", "source");
10322
10323                 if (!element) {
10324                         LOGE("failed to create filesrc\n");
10325                         break;
10326                 }
10327
10328                 g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
10329                 break;
10330         }
10331         case MM_PLAYER_URI_TYPE_URL_HTTP:
10332         {
10333                 gchar *user_agent, *cookies, **cookie_list;
10334                 gint http_timeout = DEFAULT_HTTP_TIMEOUT;
10335                 user_agent = cookies = NULL;
10336                 cookie_list = NULL;
10337
10338                 element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
10339                 if (!element) {
10340                         LOGE("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
10341                         break;
10342                 }
10343                 LOGD("using http streamming source [%s].\n", player->ini.httpsrc_element);
10344
10345                 /* get attribute */
10346                 mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
10347                 mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
10348
10349                 if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
10350                         LOGD("get timeout from ini\n");
10351                         http_timeout = player->ini.http_timeout;
10352                 }
10353
10354                 /* get attribute */
10355                 SECURE_LOGD("location : %s\n", player->profile.uri);
10356                 SECURE_LOGD("cookies : %s\n", cookies);
10357                 SECURE_LOGD("user_agent :  %s\n", user_agent);
10358                 LOGD("timeout : %d\n", http_timeout);
10359
10360                 /* setting property to streaming source */
10361                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
10362                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
10363                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
10364
10365                 /* parsing cookies */
10366                 if ((cookie_list = util_get_cookie_list((const char*)cookies)))
10367                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
10368                 if (user_agent)
10369                         g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
10370                 break;
10371         }
10372         default:
10373                 LOGE("not support uri type %d\n", player->profile.uri_type);
10374                 break;
10375         }
10376
10377         if (!element) {
10378                 LOGE("no source element was created.\n");
10379                 goto ERROR;
10380         }
10381
10382         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
10383                 LOGE("failed to add source element to pipeline\n");
10384                 gst_object_unref(GST_OBJECT(element));
10385                 element = NULL;
10386                 goto ERROR;
10387         }
10388
10389         /* take source element */
10390         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
10391         mainbin[MMPLAYER_M_SRC].gst = element;
10392
10393         element = NULL;
10394
10395         if (MMPLAYER_IS_HTTP_STREAMING(player)) {
10396                 if (player->streamer == NULL) {
10397                         player->streamer = __mm_player_streaming_create();
10398                         __mm_player_streaming_initialize(player->streamer);
10399                 }
10400
10401                 elemId = MMPLAYER_M_TYPEFIND;
10402                 element = gst_element_factory_make("typefind", "typefinder");
10403                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
10404                         G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
10405         } else {
10406                 elemId = MMPLAYER_M_AUTOPLUG;
10407                 element = __mmplayer_create_decodebin(player);
10408         }
10409
10410         /* check autoplug element is OK */
10411         if (!element) {
10412                 LOGE("can not create element(%d)\n", elemId);
10413                 goto ERROR;
10414         }
10415
10416         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
10417                 LOGE("failed to add sinkbin to pipeline\n");
10418                 gst_object_unref(GST_OBJECT(element));
10419                 element = NULL;
10420                 goto ERROR;
10421         }
10422
10423         mainbin[elemId].id = elemId;
10424         mainbin[elemId].gst = element;
10425
10426         if (gst_element_link(mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE) {
10427                 LOGE("Failed to link src - autoplug(or typefind)\n");
10428                 goto ERROR;
10429         }
10430
10431         if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
10432                 LOGE("Failed to change state of src element\n");
10433                 goto ERROR;
10434         }
10435
10436         if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
10437                 if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
10438                         LOGE("Failed to change state of decodebin\n");
10439                         goto ERROR;
10440                 }
10441         } else {
10442                 if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {
10443                         LOGE("Failed to change state of src element\n");
10444                         goto ERROR;
10445                 }
10446         }
10447
10448         player->gapless.stream_changed = TRUE;
10449         player->gapless.running = TRUE;
10450         MMPLAYER_FLEAVE();
10451         return;
10452
10453 ERROR:
10454         if (player) {
10455                 MMPLAYER_PLAYBACK_UNLOCK(player);
10456
10457                 if (!player->msg_posted) {
10458                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
10459                         player->msg_posted = TRUE;
10460                 }
10461         }
10462         return;
10463 }
10464
10465 static gboolean
10466 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
10467 {
10468         mm_player_selector_t *selector = &player->selector[type];
10469         MMPlayerGstElement *sinkbin = NULL;
10470         enum MainElementID selectorId = MMPLAYER_M_NUM;
10471         enum MainElementID sinkId = MMPLAYER_M_NUM;
10472         GstPad *srcpad = NULL;
10473         GstPad *sinkpad = NULL;
10474         gboolean send_notice = FALSE;
10475
10476         MMPLAYER_FENTER();
10477         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
10478
10479         LOGD("type %d", type);
10480
10481         switch (type) {
10482         case MM_PLAYER_TRACK_TYPE_AUDIO:
10483                 selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
10484                 sinkId = MMPLAYER_A_BIN;
10485                 sinkbin = player->pipeline->audiobin;
10486                 break;
10487         case MM_PLAYER_TRACK_TYPE_VIDEO:
10488                 selectorId = MMPLAYER_M_V_INPUT_SELECTOR;
10489                 sinkId = MMPLAYER_V_BIN;
10490                 sinkbin = player->pipeline->videobin;
10491                 send_notice = TRUE;
10492                 break;
10493         case MM_PLAYER_TRACK_TYPE_TEXT:
10494                 selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
10495                 sinkId = MMPLAYER_T_BIN;
10496                 sinkbin = player->pipeline->textbin;
10497                 break;
10498         default:
10499                 LOGE("requested type is not supportable");
10500                 return FALSE;
10501                 break;
10502         }
10503
10504         if (player->pipeline->mainbin[selectorId].gst) {
10505                 gint n;
10506
10507                 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
10508
10509                 if (selector->event_probe_id != 0)
10510                         gst_pad_remove_probe(srcpad, selector->event_probe_id);
10511                 selector->event_probe_id = 0;
10512
10513                 if ((sinkbin) && (sinkbin[sinkId].gst)) {
10514                         sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
10515
10516                         if (srcpad && sinkpad) {
10517                                 /* after getting drained signal there is no data flows, so no need to do pad_block */
10518                                 LOGD("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
10519                                 gst_pad_unlink(srcpad, sinkpad);
10520
10521                                 /* send custom event to sink pad to handle it at video sink */
10522                                 if (send_notice) {
10523                                         LOGD("send custom event to sinkpad");
10524                                         GstStructure *s = gst_structure_new_empty("application/flush-buffer");
10525                                         GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, s);
10526                                         gst_pad_send_event(sinkpad, event);
10527                                 }
10528                         }
10529
10530                         gst_object_unref(sinkpad);
10531                         sinkpad = NULL;
10532                 }
10533                 gst_object_unref(srcpad);
10534                 srcpad = NULL;
10535
10536                 LOGD("selector release");
10537
10538                 /* release and unref requests pad from the selector */
10539                 for (n = 0; n < selector->channels->len; n++) {
10540                         GstPad *sinkpad = g_ptr_array_index(selector->channels, n);
10541                         gst_element_release_request_pad((player->pipeline->mainbin[selectorId].gst), sinkpad);
10542                 }
10543                 g_ptr_array_set_size(selector->channels, 0);
10544
10545                 gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
10546                 gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
10547
10548                 player->pipeline->mainbin[selectorId].gst = NULL;
10549                 selector = NULL;
10550         }
10551
10552         return TRUE;
10553 }
10554
10555 static void
10556 __mmplayer_deactivate_old_path(mm_player_t *player)
10557 {
10558         MMPLAYER_FENTER();
10559         MMPLAYER_RETURN_IF_FAIL(player);
10560
10561         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
10562                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
10563                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
10564                 LOGE("deactivate selector error");
10565                 goto ERROR;
10566         }
10567
10568         _mmplayer_track_destroy(player);
10569         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
10570
10571         if (player->streamer) {
10572                 __mm_player_streaming_deinitialize(player->streamer);
10573                 __mm_player_streaming_destroy(player->streamer);
10574                 player->streamer = NULL;
10575         }
10576
10577         MMPLAYER_PLAYBACK_LOCK(player);
10578         MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
10579
10580         MMPLAYER_FLEAVE();
10581         return;
10582
10583 ERROR:
10584
10585         if (!player->msg_posted) {
10586                 MMMessageParamType msg = {0,};
10587
10588                 /*post error*/
10589                 msg.code = MM_ERROR_PLAYER_INTERNAL;
10590                 LOGE("next_uri_play> deactivate error");
10591
10592                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
10593                 player->msg_posted = TRUE;
10594         }
10595         return;
10596 }
10597
10598 int _mmplayer_set_file_buffering_path(MMHandleType hplayer, const char* file_path)
10599 {
10600         int result = MM_ERROR_NONE;
10601         mm_player_t* player = (mm_player_t*) hplayer;
10602         MMPLAYER_FENTER();
10603
10604         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10605
10606         if (file_path) {
10607                 player->http_file_buffering_path = (gchar*)file_path;
10608                 LOGD("temp file path: %s\n", player->http_file_buffering_path);
10609         }
10610         MMPLAYER_FLEAVE();
10611         return result;
10612 }
10613
10614 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
10615 {
10616         int result = MM_ERROR_NONE;
10617         mm_player_t* player = (mm_player_t*) hplayer;
10618         MMPLAYER_FENTER();
10619
10620         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10621
10622         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
10623         if (mmf_attrs_commit(player->attrs)) {
10624                 LOGE("failed to commit the original uri.\n");
10625                 result = MM_ERROR_PLAYER_INTERNAL;
10626         } else {
10627                 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
10628                         LOGE("failed to add the original uri in the uri list.\n");
10629         }
10630
10631         MMPLAYER_FLEAVE();
10632         return result;
10633 }
10634
10635 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
10636 {
10637         mm_player_t* player = (mm_player_t*) hplayer;
10638         guint num_of_list = 0;
10639
10640         MMPLAYER_FENTER();
10641
10642         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10643         MMPLAYER_RETURN_VAL_IF_FAIL(uri, MM_ERROR_INVALID_ARGUMENT);
10644
10645         if (player->pipeline && player->pipeline->textbin) {
10646                 LOGE("subtitle path is enabled.\n");
10647                 return MM_ERROR_PLAYER_INVALID_STATE;
10648         }
10649
10650         num_of_list = g_list_length(player->uri_info.uri_list);
10651
10652         if (is_first_path == TRUE) {
10653                 if (num_of_list == 0) {
10654                         player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
10655                         LOGD("add original path : %s", uri);
10656                 } else {
10657                         player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
10658                         player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
10659
10660                         LOGD("change original path : %s", uri);
10661                 }
10662         } else {
10663                 MMHandleType attrs = 0;
10664                 attrs = MMPLAYER_GET_ATTRS(player);
10665
10666                 if (num_of_list == 0) {
10667                         char *original_uri = NULL;
10668
10669                         if (attrs) {
10670                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
10671
10672                                 if (!original_uri) {
10673                                         LOGE("there is no original uri.");
10674                                         return MM_ERROR_PLAYER_INVALID_STATE;
10675                                 }
10676
10677                                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
10678                                 player->uri_info.uri_idx = 0;
10679
10680                                 LOGD("add original path at first : %s(%d)", original_uri);
10681                         }
10682                 }
10683
10684                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
10685                 LOGD("add new path : %s(total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
10686         }
10687
10688         MMPLAYER_FLEAVE();
10689         return MM_ERROR_NONE;
10690 }
10691
10692 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
10693 {
10694         mm_player_t* player = (mm_player_t*) hplayer;
10695         char *next_uri = NULL;
10696         guint num_of_list = 0;
10697
10698         MMPLAYER_FENTER();
10699         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10700
10701         num_of_list = g_list_length(player->uri_info.uri_list);
10702
10703         if (num_of_list > 0) {
10704                 gint uri_idx = player->uri_info.uri_idx;
10705
10706                 if (uri_idx < num_of_list-1)
10707                         uri_idx++;
10708                 else
10709                         uri_idx = 0;
10710
10711                 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
10712                 LOGE("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
10713
10714                 *uri = g_strdup(next_uri);
10715         }
10716
10717         MMPLAYER_FLEAVE();
10718         return MM_ERROR_NONE;
10719 }
10720
10721 static void
10722 __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad,
10723 GstCaps *caps, gpointer data)
10724 {
10725         mm_player_t* player = (mm_player_t*)data;
10726         const gchar* klass = NULL;
10727         const gchar* mime = NULL;
10728         gchar* caps_str = NULL;
10729
10730         klass = gst_element_factory_get_metadata(gst_element_get_factory(elem), GST_ELEMENT_METADATA_KLASS);
10731         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
10732         caps_str = gst_caps_to_string(caps);
10733
10734         LOGW("unknown type of caps : %s from %s",
10735                                         caps_str, GST_ELEMENT_NAME(elem));
10736
10737         MMPLAYER_FREEIF(caps_str);
10738
10739         /* There is no available codec. */
10740         __mmplayer_check_not_supported_codec(player, klass, mime);
10741 }
10742
10743 static gboolean
10744 __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad,
10745 GstCaps * caps,  gpointer data)
10746 {
10747         mm_player_t* player = (mm_player_t*)data;
10748         const char* mime = NULL;
10749         gboolean ret = TRUE;
10750
10751         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
10752         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
10753
10754         if (g_str_has_prefix(mime, "audio")) {
10755                 GstStructure* caps_structure = NULL;
10756                 gint samplerate = 0;
10757                 gint channels = 0;
10758                 gchar *caps_str = NULL;
10759
10760                 caps_structure = gst_caps_get_structure(caps, 0);
10761                 gst_structure_get_int(caps_structure, "rate", &samplerate);
10762                 gst_structure_get_int(caps_structure, "channels", &channels);
10763
10764                 if ((channels > 0 && samplerate == 0)) {
10765                         LOGD("exclude audio...");
10766                         ret = FALSE;
10767                 }
10768
10769                 caps_str = gst_caps_to_string(caps);
10770                 /* set it directly because not sent by TAG */
10771                 if (g_strrstr(caps_str, "mobile-xmf"))
10772                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
10773                 MMPLAYER_FREEIF(caps_str);
10774         } else if (g_str_has_prefix(mime, "video") && !player->ini.video_playback_supported) {
10775                 MMMessageParamType msg_param;
10776                 memset(&msg_param, 0, sizeof(MMMessageParamType));
10777                 msg_param.code = MM_ERROR_NOT_SUPPORT_API;
10778                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
10779                 LOGD("video file is not supported on this device");
10780                 ret = FALSE;
10781         } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
10782                 LOGD("already video linked");
10783                 ret = FALSE;
10784         } else {
10785                 LOGD("found new stream");
10786         }
10787
10788         return ret;
10789 }
10790
10791 static int
10792 __mmplayer_check_codec_info(mm_player_t* player, const char* klass, GstCaps* caps, char* factory_name)
10793 {
10794         int ret = MM_ERROR_NONE;
10795         int idx = 0;
10796         int codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
10797
10798         if ((g_strrstr(klass, "Codec/Decoder/Audio"))) {
10799                 GstStructure* str = NULL;
10800                 gint channels = 0;
10801                 mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type);
10802
10803                 LOGD("audio codec type: %d", codec_type);
10804                 if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
10805                         /* sw codec will be skipped */
10806                         for (idx = 0; player->ini.audiocodec_element_sw[idx][0] != '\0'; idx++) {
10807                                 if (strstr(factory_name, player->ini.audiocodec_element_sw[idx])) {
10808                                         LOGW("skipping sw acodec:[%s] by codec type", factory_name);
10809                                         ret = MM_ERROR_PLAYER_INTERNAL;
10810                                         goto DONE;
10811                                 }
10812                         }
10813                 } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
10814                         /* hw codec will be skipped */
10815                         if (strcmp(player->ini.audiocodec_element_hw, "") &&
10816                             g_strrstr(factory_name, player->ini.audiocodec_element_hw)) {
10817                                 LOGW("skipping hw acodec:[%s] by codec type", factory_name);
10818                                 ret = MM_ERROR_PLAYER_INTERNAL;
10819                                 goto DONE;
10820                         }
10821                 }
10822
10823                 str = gst_caps_get_structure(caps, 0);
10824                 if (str) {
10825                         gst_structure_get_int(str, "channels", &channels);
10826
10827                         LOGD("check audio ch : %d %d\n", player->max_audio_channels, channels);
10828                         if (player->max_audio_channels < channels)
10829                                 player->max_audio_channels = channels;
10830                 }
10831                 /* set stream information */
10832                 if (!player->audiodec_linked)
10833                         __mmplayer_set_audio_attrs(player, caps);
10834
10835                 /* update codec info */
10836                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
10837                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
10838                 player->audiodec_linked = 1;
10839
10840         } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
10841
10842                 mm_attrs_get_int_by_name(player->attrs, "video_codec_type", &codec_type);
10843
10844                 LOGD("video codec type: %d", codec_type);
10845                 if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
10846                         /* sw codec is skipped */
10847                         for (idx = 0; player->ini.videocodec_element_sw[idx][0] != '\0'; idx++) {
10848                                 if (strstr(factory_name, player->ini.videocodec_element_sw[idx])) {
10849                                         LOGW("skipping sw vcodec:[%s] by codec type", factory_name);
10850                                         ret = MM_ERROR_PLAYER_INTERNAL;
10851                                         goto DONE;
10852                                 }
10853                         }
10854                 } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
10855                         /* hw codec is skipped */
10856                         if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
10857                                 LOGW("skipping hw vcodec:[%s] by codec type", factory_name);
10858                                 ret = MM_ERROR_PLAYER_INTERNAL;
10859                                 goto DONE;
10860                         }
10861                 }
10862
10863                 if ((strlen(player->ini.videocodec_element_hw) > 0) &&
10864                         (g_strrstr(factory_name, player->ini.videocodec_element_hw))) {
10865
10866                         /* mark video decoder for acquire */
10867                         if (player->video_decoder_resource == NULL) {
10868                                 if (mm_resource_manager_mark_for_acquire(player->resource_manager,
10869                                                 MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER,
10870                                                 MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
10871                                                 &player->video_decoder_resource)
10872                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
10873                                         LOGE("could not mark video_decoder resource for acquire");
10874                                         ret = MM_ERROR_PLAYER_INTERNAL;
10875                                         goto DONE;
10876                                 }
10877                         } else {
10878                                 LOGW("video decoder resource is already acquired, skip it.");
10879                                 ret = MM_ERROR_PLAYER_INTERNAL;
10880                                 goto DONE;
10881                         }
10882
10883                         player->interrupted_by_resource = FALSE;
10884                         /* acquire resources for video playing */
10885                         if (mm_resource_manager_commit(player->resource_manager)
10886                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
10887                                 LOGE("could not acquire resources for video decoding\n");
10888                                 ret = MM_ERROR_PLAYER_INTERNAL;
10889                                 goto DONE;
10890                         }
10891                 }
10892
10893                 /* update codec info */
10894                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
10895                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
10896                 player->videodec_linked = 1;
10897         }
10898
10899 DONE:
10900         return ret;
10901 }
10902
10903 static gint
10904 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad,
10905 GstCaps* caps, GstElementFactory* factory, gpointer data)
10906 {
10907         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
10908          We are defining our own and will be removed when it actually exposed */
10909         typedef enum {
10910                 GST_AUTOPLUG_SELECT_TRY,
10911                 GST_AUTOPLUG_SELECT_EXPOSE,
10912                 GST_AUTOPLUG_SELECT_SKIP
10913         } GstAutoplugSelectResult;
10914
10915         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
10916         mm_player_t* player = (mm_player_t*)data;
10917
10918         gchar* factory_name = NULL;
10919         gchar* caps_str = NULL;
10920         const gchar* klass = NULL;
10921         gint idx = 0;
10922
10923         factory_name = GST_OBJECT_NAME(factory);
10924         klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
10925         caps_str = gst_caps_to_string(caps);
10926
10927         LOGD("[handle: %p] found new element [%s] to link", player, factory_name);
10928
10929         /* store type string */
10930         if (player->type == NULL) {
10931                 player->type = gst_caps_to_string(caps);
10932                 __mmplayer_update_content_type_info(player);
10933         }
10934
10935         /* filtering exclude keyword */
10936         for (idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++) {
10937                 if (strstr(factory_name, player->ini.exclude_element_keyword[idx])) {
10938                         LOGW("skipping [%s] by exculde keyword [%s]\n",
10939                                         factory_name, player->ini.exclude_element_keyword[idx]);
10940
10941                         result = GST_AUTOPLUG_SELECT_SKIP;
10942                         goto DONE;
10943                 }
10944         }
10945
10946         /* exclude webm format */
10947         /* NOTE : MSL have to post MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT
10948          * because webm format is not supportable.
10949          * If webm is disabled in "autoplug-continue", there is no state change
10950          * failure or error because the decodebin will expose the pad directly.
10951          * It make MSL invoke _prepare_async_callback.
10952          * So, we need to disable webm format in "autoplug-select" */
10953         if (caps_str && strstr(caps_str, "webm")) {
10954                 LOGW("webm is not supported");
10955                 result = GST_AUTOPLUG_SELECT_SKIP;
10956                 goto DONE;
10957         }
10958
10959         /* check factory class for filtering */
10960         /* NOTE : msl don't need to use image plugins.
10961          * So, those plugins should be skipped for error handling.
10962          */
10963         if (g_strrstr(klass, "Codec/Decoder/Image")) {
10964                 LOGD("skipping [%s] by not required\n", factory_name);
10965                 result = GST_AUTOPLUG_SELECT_SKIP;
10966                 goto DONE;
10967         }
10968
10969         if ((MMPLAYER_IS_MS_BUFF_SRC(player)) &&
10970                 (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser")))) {
10971                 // TO CHECK : subtitle if needed, add subparse exception.
10972                 LOGD("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
10973                 result = GST_AUTOPLUG_SELECT_SKIP;
10974                 goto DONE;
10975         }
10976
10977         if (g_strrstr(factory_name, "mpegpsdemux")) {
10978                 LOGD("skipping PS container - not support\n");
10979                 result = GST_AUTOPLUG_SELECT_SKIP;
10980                 goto DONE;
10981         }
10982
10983         if (g_strrstr(factory_name, "mssdemux"))
10984                 player->smooth_streaming = TRUE;
10985
10986         if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
10987                 (g_strrstr(klass, "Codec/Decoder/Video"))) {
10988                 gint stype = 0;
10989                 gint width = 0;
10990                 GstStructure *str = NULL;
10991                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
10992
10993                 /* don't make video because of not required */
10994                 if ((stype == MM_DISPLAY_SURFACE_NULL) &&
10995                         (player->set_mode.media_packet_video_stream == FALSE)) {
10996                         LOGD("no video because it's not required. -> return expose");
10997                         result = GST_AUTOPLUG_SELECT_EXPOSE;
10998                         goto DONE;
10999                 }
11000
11001                 /* get w/h for omx state-tune */
11002                 /* FIXME: deprecated? */
11003                 str = gst_caps_get_structure(caps, 0);
11004                 gst_structure_get_int(str, "width", &width);
11005
11006                 if (width != 0) {
11007                         if (player->v_stream_caps) {
11008                                 gst_caps_unref(player->v_stream_caps);
11009                                 player->v_stream_caps = NULL;
11010                         }
11011
11012                         player->v_stream_caps = gst_caps_copy(caps);
11013                         LOGD("take caps for video state tune");
11014                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
11015                 }
11016         }
11017
11018         if (g_strrstr(klass, "Codec/Decoder")) {
11019                 if (__mmplayer_check_codec_info(player, klass, caps, factory_name) != MM_ERROR_NONE) {
11020                         LOGD("skipping %s codec", factory_name);
11021                         result = GST_AUTOPLUG_SELECT_SKIP;
11022                         goto DONE;
11023                 }
11024         }
11025
11026 DONE:
11027         MMPLAYER_FREEIF(caps_str);
11028
11029         return result;
11030 }
11031
11032 static void
11033 __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad,
11034 gpointer data)
11035 {
11036         //mm_player_t* player = (mm_player_t*)data;
11037         GstCaps* caps = NULL;
11038
11039         LOGD("[Decodebin2] pad-removed signal\n");
11040
11041         caps = gst_pad_query_caps(new_pad, NULL);
11042         if (caps) {
11043                 gchar* caps_str = NULL;
11044                 caps_str = gst_caps_to_string(caps);
11045
11046                 LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem));
11047
11048                 MMPLAYER_FREEIF(caps_str);
11049                 gst_caps_unref(caps);
11050         }
11051 }
11052
11053 static void
11054 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
11055 {
11056         mm_player_t* player = (mm_player_t*)data;
11057         GstIterator *iter = NULL;
11058         GValue item = { 0, };
11059         GstPad *pad = NULL;
11060         gboolean done = FALSE;
11061         gboolean is_all_drained = TRUE;
11062
11063         MMPLAYER_FENTER();
11064         MMPLAYER_RETURN_IF_FAIL(player);
11065
11066         LOGD("__mmplayer_gst_decode_drained");
11067
11068         if (player->use_deinterleave == TRUE) {
11069                 LOGD("group playing mode.");
11070                 return;
11071         }
11072
11073         if (!MMPLAYER_CMD_TRYLOCK(player)) {
11074                 LOGW("Fail to get cmd lock");
11075                 return;
11076         }
11077
11078         if (!player->gapless.reconfigure && /* If it is already checked, skip verify. */
11079                 !__mmplayer_verify_next_play_path(player)) {
11080                 LOGD("decoding is finished.");
11081                 __mmplayer_reset_gapless_state(player);
11082                 MMPLAYER_CMD_UNLOCK(player);
11083                 return;
11084         }
11085
11086         player->gapless.reconfigure = TRUE;
11087
11088         /* check decodebin src pads whether they received EOS or not */
11089         iter = gst_element_iterate_src_pads(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
11090
11091         while (!done) {
11092                 switch (gst_iterator_next(iter, &item)) {
11093                 case GST_ITERATOR_OK:
11094                         pad = g_value_get_object(&item);
11095                         if (pad && !GST_PAD_IS_EOS(pad)) {
11096                                 LOGW("[%s:%s] not received EOS yet.", GST_DEBUG_PAD_NAME(pad));
11097                                 is_all_drained = FALSE;
11098                                 break;
11099                         }
11100                         g_value_reset(&item);
11101                         break;
11102                 case GST_ITERATOR_RESYNC:
11103                         gst_iterator_resync(iter);
11104                         break;
11105                 case GST_ITERATOR_ERROR:
11106                 case GST_ITERATOR_DONE:
11107                         done = TRUE;
11108                         break;
11109                 }
11110         }
11111         g_value_unset(&item);
11112         gst_iterator_free(iter);
11113
11114         if (!is_all_drained) {
11115                 LOGD("Wait util the all pads get EOS.");
11116                 MMPLAYER_CMD_UNLOCK(player);
11117                 MMPLAYER_FLEAVE();
11118                 return;
11119         }
11120
11121         player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_AUDIO] = FALSE;
11122         player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_VIDEO] = FALSE;
11123
11124         /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
11125         MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL); /* post message for gapless */
11126         __mmplayer_deactivate_old_path(player);
11127         MMPLAYER_CMD_UNLOCK(player);
11128
11129         MMPLAYER_FLEAVE();
11130 }
11131
11132 static void
11133 __mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
11134 {
11135         mm_player_t* player = (mm_player_t*)data;
11136         const gchar* klass = NULL;
11137         gchar* factory_name = NULL;
11138
11139         klass = gst_element_factory_get_metadata(gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
11140         factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
11141
11142         LOGD("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
11143
11144         if (__mmplayer_add_dump_buffer_probe(player, element))
11145                 LOGD("add buffer probe");
11146
11147         //<-
11148         if (g_strrstr(klass, "Codec/Decoder/Audio")) {
11149                 gchar* selected = NULL;
11150                 selected = g_strdup(GST_ELEMENT_NAME(element));
11151                 player->audio_decoders = g_list_append(player->audio_decoders, selected);
11152         }
11153         //-> temp code
11154
11155         if (g_strrstr(klass, "Parser")) {
11156                 gchar* selected = NULL;
11157
11158                 selected = g_strdup(factory_name);
11159                 player->parsers = g_list_append(player->parsers, selected);
11160         }
11161
11162         if (g_strrstr(klass, "Demuxer/Adaptive")) {
11163                 player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX;
11164                 player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst = element;
11165
11166                 LOGD("set max variant limit: %d, %d %d", player->adaptive_info.limit.bandwidth,
11167                                                 player->adaptive_info.limit.width, player->adaptive_info.limit.height);
11168
11169                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
11170                                                 "max-bandwidth", player->adaptive_info.limit.bandwidth,
11171                                                 "max-video-width", player->adaptive_info.limit.width,
11172                                                 "max-video-height", player->adaptive_info.limit.height, NULL);
11173
11174         } else if (g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) {
11175                 /* FIXIT : first value will be overwritten if there's more
11176                  * than 1 demuxer/parser
11177                  */
11178
11179                 //LOGD("plugged element is demuxer. take it\n");
11180                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
11181                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
11182
11183                 /*Added for multi audio support */ // Q. del?
11184                 if (g_strrstr(klass, "Demux")) {
11185                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
11186                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
11187                 }
11188         }
11189
11190         if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) {
11191                 int surface_type = 0;
11192
11193                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
11194         }
11195
11196         // to support trust-zone only
11197         if (g_strrstr(factory_name, "asfdemux")) {
11198                 LOGD("set file-location %s\n", player->profile.uri);
11199                 g_object_set(G_OBJECT(element), "file-location", player->profile.uri, NULL);
11200
11201                 if (player->video_hub_download_mode == TRUE)
11202                         g_object_set(G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
11203         } else if (g_strrstr(factory_name, "legacyh264parse")) {
11204                 LOGD("[%s] output-format to legacyh264parse\n", "mssdemux");
11205                 g_object_set(G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
11206         } else if (g_strrstr(factory_name, "mpegaudioparse")) {
11207                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
11208                         (__mmplayer_is_only_mp3_type(player->type))) {
11209                         LOGD("[mpegaudioparse] set streaming pull mode.");
11210                         g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
11211                 }
11212         } else if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
11213                 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
11214         }
11215
11216         if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
11217                 (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))) {
11218                 LOGD("plugged element is multiqueue. take it\n");
11219
11220                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
11221                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
11222
11223                 if (!MMPLAYER_IS_HTTP_PD(player) &&
11224                         ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
11225                         (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)))) {
11226                         /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
11227                         __mm_player_streaming_set_multiqueue(player->streamer,
11228                                 element,
11229                                 TRUE,
11230                                 player->ini.http_buffering_time,
11231                                 1.0,
11232                                 player->ini.http_buffering_limit);
11233
11234                         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
11235                 }
11236         }
11237
11238         return;
11239 }
11240
11241 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
11242 {
11243         MMPLAYER_FENTER();
11244         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11245
11246         if (MMPLAYER_IS_STREAMING(player))
11247                 return FALSE;
11248
11249         /* This callback can be set to music player only. */
11250         if ((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO) {
11251                 LOGW("audio callback is not supported for video");
11252                 return FALSE;
11253         }
11254
11255         if (player->audio_stream_cb) {
11256                 GstPad *pad = NULL;
11257
11258                 pad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
11259
11260                 if (!pad) {
11261                         LOGE("failed to get sink pad from audiosink to probe data\n");
11262                         return FALSE;
11263                 }
11264                 player->audio_cb_probe_id = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
11265                         __mmplayer_audio_stream_probe, player, NULL);
11266
11267                 gst_object_unref(pad);
11268
11269                 pad = NULL;
11270         } else {
11271                 LOGE("There is no audio callback to configure.\n");
11272                 return FALSE;
11273         }
11274
11275         MMPLAYER_FLEAVE();
11276
11277         return TRUE;
11278 }
11279
11280 static void
11281 __mmplayer_release_misc(mm_player_t* player)
11282 {
11283         int i;
11284         bool cur_mode = player->set_mode.rich_audio;
11285         MMPLAYER_FENTER();
11286
11287         MMPLAYER_RETURN_IF_FAIL(player);
11288
11289         player->video_stream_cb = NULL;
11290         player->video_stream_cb_user_param = NULL;
11291         player->video_stream_prerolled = FALSE;
11292
11293         player->audio_stream_cb = NULL;
11294         player->audio_stream_render_cb_ex = NULL;
11295         player->audio_stream_cb_user_param = NULL;
11296         player->audio_stream_sink_sync = false;
11297
11298         player->video_stream_changed_cb = NULL;
11299         player->video_stream_changed_cb_user_param = NULL;
11300
11301         player->audio_stream_changed_cb = NULL;
11302         player->audio_stream_changed_cb_user_param = NULL;
11303
11304         player->sent_bos = FALSE;
11305         player->playback_rate = DEFAULT_PLAYBACK_RATE;
11306
11307         player->doing_seek = FALSE;
11308
11309         player->total_bitrate = 0;
11310         player->total_maximum_bitrate = 0;
11311
11312         player->not_found_demuxer = 0;
11313
11314         player->last_position = 0;
11315         player->duration = 0;
11316         player->http_content_size = 0;
11317         player->not_supported_codec = MISSING_PLUGIN_NONE;
11318         player->can_support_codec = FOUND_PLUGIN_NONE;
11319         player->pending_seek.is_pending = FALSE;
11320         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
11321         player->pending_seek.pos = 0;
11322         player->msg_posted = FALSE;
11323         player->has_many_types = FALSE;
11324         player->max_audio_channels = 0;
11325         player->video_share_api_delta = 0;
11326         player->video_share_clock_delta = 0;
11327         player->is_subtitle_force_drop = FALSE;
11328         player->play_subtitle = FALSE;
11329         player->adjust_subtitle_pos = 0;
11330         player->last_multiwin_status = FALSE;
11331         player->has_closed_caption = FALSE;
11332         player->set_mode.media_packet_video_stream = FALSE;
11333         player->profile.uri_type = MM_PLAYER_URI_TYPE_NONE;
11334         memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
11335         /* recover mode */
11336         player->set_mode.rich_audio = cur_mode;
11337
11338         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
11339                 player->bitrate[i] = 0;
11340                 player->maximum_bitrate[i] = 0;
11341         }
11342
11343         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
11344
11345         /* remove media stream cb(appsrc cb) */
11346         for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++) {
11347                 player->media_stream_buffer_status_cb[i] = NULL;
11348                 player->media_stream_seek_data_cb[i] = NULL;
11349                 player->buffer_cb_user_param[i] = NULL;
11350                 player->seek_cb_user_param[i] = NULL;
11351         }
11352         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
11353
11354         /* free memory related to audio effect */
11355         MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
11356
11357         if (player->adaptive_info.var_list) {
11358                 g_list_free_full(player->adaptive_info.var_list, g_free);
11359                 player->adaptive_info.var_list = NULL;
11360         }
11361
11362         player->adaptive_info.limit.bandwidth = ADAPTIVE_VARIANT_DEFAULT_VALUE;
11363         player->adaptive_info.limit.width = ADAPTIVE_VARIANT_DEFAULT_VALUE;
11364         player->adaptive_info.limit.height = ADAPTIVE_VARIANT_DEFAULT_VALUE;
11365
11366         /* Reset video360 settings to their defaults in case if the pipeline is to be
11367          * re-created.
11368          * */
11369         player->video360_metadata.is_spherical = -1;
11370         player->is_openal_plugin_used = FALSE;
11371
11372         player->is_content_spherical = FALSE;
11373         player->is_video360_enabled = TRUE;
11374         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
11375         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
11376         player->video360_yaw_radians = PLAYER_SPHERICAL_DEFAULT_YAW;
11377         player->video360_pitch_radians = PLAYER_SPHERICAL_DEFAULT_PITCH;
11378         player->video360_zoom = 1.0f;
11379         player->video360_horizontal_fov = PLAYER_SPHERICAL_DEFAULT_H_FOV;
11380         player->video360_vertical_fov = PLAYER_SPHERICAL_DEFAULT_V_FOV;
11381
11382         player->sound.rg_enable = false;
11383
11384         MMPLAYER_FLEAVE();
11385 }
11386
11387 static void
11388 __mmplayer_release_misc_post(mm_player_t* player)
11389 {
11390         char *original_uri = NULL;
11391         MMPLAYER_FENTER();
11392
11393         /* player->pipeline is already released before. */
11394
11395         MMPLAYER_RETURN_IF_FAIL(player);
11396
11397         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
11398
11399         /* clean found parsers */
11400         if (player->parsers) {
11401                 GList *parsers = player->parsers;
11402                 for (; parsers; parsers = g_list_next(parsers)) {
11403                         gchar *name = parsers->data;
11404                         MMPLAYER_FREEIF(name);
11405                 }
11406                 g_list_free(player->parsers);
11407                 player->parsers = NULL;
11408         }
11409
11410         /* clean found audio decoders */
11411         if (player->audio_decoders) {
11412                 GList *a_dec = player->audio_decoders;
11413                 for (; a_dec; a_dec = g_list_next(a_dec)) {
11414                         gchar *name = a_dec->data;
11415                         MMPLAYER_FREEIF(name);
11416                 }
11417                 g_list_free(player->audio_decoders);
11418                 player->audio_decoders = NULL;
11419         }
11420
11421         /* clean the uri list except original uri */
11422         if (player->uri_info.uri_list) {
11423                 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
11424
11425                 if (player->attrs) {
11426                         mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
11427                         LOGD("restore original uri = %s\n", original_uri);
11428
11429                         if (mmf_attrs_commit(player->attrs))
11430                                 LOGE("failed to commit the original uri.\n");
11431                 }
11432
11433                 GList *uri_list = player->uri_info.uri_list;
11434                 for (; uri_list; uri_list = g_list_next(uri_list)) {
11435                         gchar *uri = uri_list->data;
11436                         MMPLAYER_FREEIF(uri);
11437                 }
11438                 g_list_free(player->uri_info.uri_list);
11439                 player->uri_info.uri_list = NULL;
11440         }
11441
11442         /* clear the audio stream buffer list */
11443         __mmplayer_audio_stream_clear_buffer(player, FALSE);
11444
11445         /* clear the video stream bo list */
11446         __mmplayer_video_stream_destroy_bo_list(player);
11447         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
11448
11449         if (player->profile.input_mem.buf) {
11450                 free(player->profile.input_mem.buf);
11451                 player->profile.input_mem.buf = NULL;
11452         }
11453         player->profile.input_mem.len = 0;
11454         player->profile.input_mem.offset = 0;
11455
11456         player->uri_info.uri_idx = 0;
11457         MMPLAYER_FLEAVE();
11458 }
11459
11460 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
11461 {
11462         GstElement *element = NULL;
11463         GstPad *sinkpad;
11464
11465         LOGD("creating %s to plug\n", name);
11466
11467         element = gst_element_factory_make(name, NULL);
11468         if (!element) {
11469                 LOGE("failed to create queue\n");
11470                 return NULL;
11471         }
11472
11473         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY)) {
11474                 LOGE("failed to set state READY to %s\n", name);
11475                 gst_object_unref(element);
11476                 return NULL;
11477         }
11478
11479         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element)) {
11480                 LOGE("failed to add %s\n", name);
11481                 gst_object_unref(element);
11482                 return NULL;
11483         }
11484
11485         sinkpad = gst_element_get_static_pad(element, "sink");
11486
11487         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
11488                 LOGE("failed to link %s\n", name);
11489                 gst_object_unref(sinkpad);
11490                 gst_object_unref(element);
11491                 return NULL;
11492         }
11493
11494         LOGD("linked %s to pipeline successfully\n", name);
11495
11496         gst_object_unref(sinkpad);
11497
11498         return element;
11499 }
11500
11501 gboolean
11502 __mmplayer_check_subtitle(mm_player_t* player)
11503 {
11504         MMHandleType attrs = 0;
11505         char *subtitle_uri = NULL;
11506
11507         MMPLAYER_FENTER();
11508
11509         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11510
11511         /* get subtitle attribute */
11512         attrs = MMPLAYER_GET_ATTRS(player);
11513         if (!attrs)
11514                 return FALSE;
11515
11516         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
11517         if (!subtitle_uri || !strlen(subtitle_uri))
11518                 return FALSE;
11519
11520         LOGD("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
11521         player->is_external_subtitle_present = TRUE;
11522
11523         MMPLAYER_FLEAVE();
11524
11525         return TRUE;
11526 }
11527
11528 static gboolean
11529 __mmplayer_can_extract_pcm(mm_player_t* player)
11530 {
11531         MMHandleType attrs = 0;
11532         gboolean sound_extraction = FALSE;
11533
11534         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11535
11536         attrs = MMPLAYER_GET_ATTRS(player);
11537         if (!attrs) {
11538                 LOGE("fail to get attributes.");
11539                 return FALSE;
11540         }
11541
11542         /* get sound_extraction property */
11543         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
11544
11545         if (!sound_extraction) {
11546                 LOGD("checking pcm extraction mode : %d ", sound_extraction);
11547                 return FALSE;
11548         }
11549
11550         return TRUE;
11551 }
11552
11553 static gboolean
11554 __mmplayer_handle_streaming_error(mm_player_t* player, GstMessage * message)
11555 {
11556         LOGD("\n");
11557         MMMessageParamType msg_param;
11558         gchar *msg_src_element = NULL;
11559         GstStructure *s = NULL;
11560         guint error_id = 0;
11561         gchar *error_string = NULL;
11562
11563         MMPLAYER_FENTER();
11564
11565         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11566         MMPLAYER_RETURN_VAL_IF_FAIL(message, FALSE);
11567
11568         s = gst_structure_copy(gst_message_get_structure(message));
11569
11570
11571         if (!gst_structure_get_uint(s, "error_id", &error_id))
11572                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
11573
11574         switch (error_id) {
11575         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
11576                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
11577                 break;
11578         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
11579                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
11580                 break;
11581         case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
11582                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
11583                 break;
11584         case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
11585                 msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
11586                 break;
11587         case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
11588                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
11589                 break;
11590         case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
11591                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
11592                 break;
11593         case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
11594                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
11595                 break;
11596         case MMPLAYER_STREAMING_ERROR_INVALID_URL:
11597                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
11598                 break;
11599         case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
11600                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
11601                 break;
11602         case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
11603                 msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
11604                 break;
11605         case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
11606                 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
11607                 break;
11608         case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
11609                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
11610                 break;
11611         case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
11612                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
11613                 break;
11614         case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
11615                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
11616                 break;
11617         case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
11618                 msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
11619                 break;
11620         case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
11621                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
11622                 break;
11623         case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
11624                 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
11625                 break;
11626         case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
11627                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
11628                 break;
11629         case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
11630                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
11631                 break;
11632         case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
11633                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
11634                 break;
11635         case MMPLAYER_STREAMING_ERROR_GONE:
11636                 msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
11637                 break;
11638         case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
11639                 msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
11640                 break;
11641         case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
11642                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
11643                 break;
11644         case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
11645                 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
11646                 break;
11647         case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
11648                 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
11649                 break;
11650         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
11651                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
11652                 break;
11653         case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
11654                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
11655                 break;
11656         case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
11657                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
11658                 break;
11659         case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
11660                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
11661                 break;
11662         case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
11663                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
11664                 break;
11665         case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
11666                 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
11667                 break;
11668         case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
11669                 msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
11670                 break;
11671         case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
11672                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
11673                 break;
11674         case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
11675                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
11676                 break;
11677         case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
11678                 msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
11679                 break;
11680         case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
11681                 msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
11682                 break;
11683         case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
11684                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
11685                 break;
11686         case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
11687                 msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
11688                 break;
11689         case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
11690                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
11691                 break;
11692         case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
11693                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
11694                 break;
11695         case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
11696                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
11697                 break;
11698         case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
11699                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
11700                 break;
11701         case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
11702                 msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
11703                 break;
11704         case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
11705                 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
11706                 break;
11707         case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
11708                 msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
11709                 break;
11710         default:
11711                 {
11712                         gst_structure_free(s);
11713                         return MM_ERROR_PLAYER_STREAMING_FAIL;
11714                 }
11715         }
11716
11717         error_string = g_strdup(gst_structure_get_string(s, "error_string"));
11718         if (error_string)
11719                 msg_param.data = (void *) error_string;
11720
11721         if (message->src) {
11722                 msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
11723
11724                 LOGE("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
11725                         msg_src_element, msg_param.code, (char*)msg_param.data);
11726         }
11727
11728         /* post error to application */
11729         if (!player->msg_posted) {
11730                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
11731
11732                 /* don't post more if one was sent already */
11733                 player->msg_posted = TRUE;
11734         } else
11735                 LOGD("skip error post because it's sent already.\n");
11736
11737         gst_structure_free(s);
11738         MMPLAYER_FLEAVE();
11739         g_free(error_string);
11740
11741         return TRUE;
11742
11743 }
11744
11745 static void
11746 __mmplayer_handle_eos_delay(mm_player_t* player, int delay_in_ms)
11747 {
11748         MMPLAYER_RETURN_IF_FAIL(player);
11749
11750         /* post now if delay is zero */
11751         if (delay_in_ms == 0 || player->set_mode.pcm_extraction) {
11752                 LOGD("eos delay is zero. posting EOS now\n");
11753                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
11754
11755                 if (player->set_mode.pcm_extraction)
11756                         __mmplayer_cancel_eos_timer(player);
11757
11758                 return;
11759         }
11760
11761         /* cancel if existing */
11762         __mmplayer_cancel_eos_timer(player);
11763
11764         /* init new timeout */
11765         /* NOTE : consider give high priority to this timer */
11766         LOGD("posting EOS message after [%d] msec\n", delay_in_ms);
11767
11768         player->eos_timer = g_timeout_add(delay_in_ms,
11769                 __mmplayer_eos_timer_cb, player);
11770
11771         player->context.global_default = g_main_context_default();
11772         LOGD("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
11773
11774         /* check timer is valid. if not, send EOS now */
11775         if (player->eos_timer == 0) {
11776                 LOGW("creating timer for delayed EOS has failed. sending EOS now\n");
11777                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
11778         }
11779 }
11780
11781 static void
11782 __mmplayer_cancel_eos_timer(mm_player_t* player)
11783 {
11784         MMPLAYER_RETURN_IF_FAIL(player);
11785
11786         if (player->eos_timer) {
11787                 LOGD("cancel eos timer");
11788                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
11789                 player->eos_timer = 0;
11790         }
11791
11792         return;
11793 }
11794
11795 static gboolean
11796 __mmplayer_eos_timer_cb(gpointer u_data)
11797 {
11798         mm_player_t* player = NULL;
11799         MMHandleType attrs = 0;
11800         int count = 0;
11801
11802         MMPLAYER_RETURN_VAL_IF_FAIL(u_data, FALSE);
11803
11804         player = (mm_player_t*) u_data;
11805         attrs = MMPLAYER_GET_ATTRS(player);
11806
11807         mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
11808
11809         if (count == -1) {
11810                 gint ret_value = 0;
11811                 ret_value = __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
11812                 if (ret_value != MM_ERROR_NONE)
11813                         LOGE("seeking to 0 failed in repeat play");
11814         } else {
11815                 /* posting eos */
11816                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
11817         }
11818
11819         /* we are returning FALSE as we need only one posting */
11820         return FALSE;
11821 }
11822
11823 /* sending event to one of sinkelements */
11824 static gboolean
11825 __gst_send_event_to_sink(mm_player_t* player, GstEvent* event)
11826 {
11827         GstEvent * event2 = NULL;
11828         GList *sinks = NULL;
11829         gboolean res = FALSE;
11830         MMPLAYER_FENTER();
11831
11832         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11833         MMPLAYER_RETURN_VAL_IF_FAIL(event, FALSE);
11834
11835         /* While adding subtitles in live feeds seek is getting called.
11836            Adding defensive check in framework layer.*/
11837         if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
11838                 if (MMPLAYER_IS_LIVE_STREAMING(player)) {
11839                         LOGE("Should not send seek event during live playback");
11840                         return TRUE;
11841                 }
11842         }
11843
11844         if (player->play_subtitle)
11845                 event2 = gst_event_copy((const GstEvent *)event);
11846
11847         sinks = player->sink_elements;
11848         while (sinks) {
11849                 GstElement *sink = GST_ELEMENT_CAST(sinks->data);
11850
11851                 if (GST_IS_ELEMENT(sink)) {
11852                         /* keep ref to the event */
11853                         gst_event_ref(event);
11854
11855                         if ((res = gst_element_send_event(sink, event))) {
11856                                 LOGD("sending event[%s] to sink element [%s] success!\n",
11857                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
11858
11859                                 /* rtsp case, asyn_done is not called after seek during pause state */
11860                                 if (MMPLAYER_IS_RTSP_STREAMING(player)) {
11861                                         if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
11862                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
11863                                                         LOGD("RTSP seek completed, after pause state..\n");
11864                                                         player->doing_seek = FALSE;
11865                                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
11866                                                 }
11867
11868                                         }
11869                                 }
11870
11871                                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
11872                                         sinks = g_list_next(sinks);
11873                                         continue;
11874                                 } else {
11875                                         break;
11876                                 }
11877                         }
11878
11879                         LOGD("sending event[%s] to sink element [%s] failed. try with next one.\n",
11880                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
11881                 }
11882
11883                 sinks = g_list_next(sinks);
11884         }
11885
11886         /* Note : Textbin is not linked to the video or audio bin.
11887          * It needs to send the event to the text sink seperatelly.
11888          */
11889          if (player->play_subtitle && player->pipeline) {
11890                 GstElement *text_sink = GST_ELEMENT_CAST(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
11891
11892                 if (GST_IS_ELEMENT(text_sink)) {
11893                         /* keep ref to the event */
11894                         gst_event_ref(event2);
11895
11896                         if ((res = gst_element_send_event(text_sink, event2)))
11897                                 LOGD("sending event[%s] to subtitle sink element [%s] success!\n",
11898                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
11899                         else
11900                                 LOGE("sending event[%s] to subtitle sink element [%s] failed!\n",
11901                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
11902
11903                         gst_event_unref(event2);
11904                 }
11905          }
11906
11907         gst_event_unref(event);
11908
11909         MMPLAYER_FLEAVE();
11910
11911         return res;
11912 }
11913
11914 static void
11915 __mmplayer_add_sink(mm_player_t* player, GstElement* sink)
11916 {
11917         MMPLAYER_FENTER();
11918
11919         MMPLAYER_RETURN_IF_FAIL(player);
11920         MMPLAYER_RETURN_IF_FAIL(sink);
11921
11922         player->sink_elements =
11923                 g_list_append(player->sink_elements, sink);
11924
11925         MMPLAYER_FLEAVE();
11926 }
11927
11928 static void
11929 __mmplayer_del_sink(mm_player_t* player, GstElement* sink)
11930 {
11931         MMPLAYER_FENTER();
11932
11933         MMPLAYER_RETURN_IF_FAIL(player);
11934         MMPLAYER_RETURN_IF_FAIL(sink);
11935
11936         player->sink_elements =
11937                         g_list_remove(player->sink_elements, sink);
11938
11939         MMPLAYER_FLEAVE();
11940 }
11941
11942 static gboolean
11943 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
11944                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
11945                         gint64 cur, GstSeekType stop_type, gint64 stop)
11946 {
11947         GstEvent* event = NULL;
11948         gboolean result = FALSE;
11949
11950         MMPLAYER_FENTER();
11951
11952         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11953
11954         if (player->pipeline && player->pipeline->textbin)
11955                 __mmplayer_drop_subtitle(player, FALSE);
11956
11957         event = gst_event_new_seek(rate, format, flags, cur_type,
11958                 cur, stop_type, stop);
11959
11960         result = __gst_send_event_to_sink(player, event);
11961
11962         MMPLAYER_FLEAVE();
11963
11964         return result;
11965 }
11966
11967 /* NOTE : be careful with calling this api. please refer to below glib comment
11968  * glib comment : Note that there is a bug in GObject that makes this function much
11969  * less useful than it might seem otherwise. Once gobject is disposed, the callback
11970  * will no longer be called, but, the signal handler is not currently disconnected.
11971  * If the instance is itself being freed at the same time than this doesn't matter,
11972  * since the signal will automatically be removed, but if instance persists,
11973  * then the signal handler will leak. You should not remove the signal yourself
11974  * because in a future versions of GObject, the handler will automatically be
11975  * disconnected.
11976  *
11977  * It's possible to work around this problem in a way that will continue to work
11978  * with future versions of GObject by checking that the signal handler is still
11979  * connected before disconnected it:
11980  *
11981  *  if (g_signal_handler_is_connected(instance, id))
11982  *    g_signal_handler_disconnect(instance, id);
11983  */
11984 static void
11985 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
11986 {
11987         GList* sig_list = NULL;
11988         MMPlayerSignalItem* item = NULL;
11989
11990         MMPLAYER_FENTER();
11991
11992         MMPLAYER_RETURN_IF_FAIL(player);
11993
11994         LOGD("release signals type : %d", type);
11995
11996         if (type >= MM_PLAYER_SIGNAL_TYPE_ALL) {
11997                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
11998                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
11999                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
12000                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
12001                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
12002                 return;
12003         }
12004
12005         sig_list = player->signals[type];
12006
12007         for (; sig_list; sig_list = sig_list->next) {
12008                 item = sig_list->data;
12009
12010                 if (item && item->obj && GST_IS_ELEMENT(item->obj)) {
12011                         if (g_signal_handler_is_connected(item->obj, item->sig))
12012                                 g_signal_handler_disconnect(item->obj, item->sig);
12013                 }
12014
12015                 MMPLAYER_FREEIF(item);
12016         }
12017
12018         g_list_free(player->signals[type]);
12019         player->signals[type] = NULL;
12020
12021         MMPLAYER_FLEAVE();
12022
12023         return;
12024 }
12025
12026 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
12027 {
12028         mm_player_t* player = 0;
12029         int prev_display_surface_type = 0;
12030         void *prev_display_overlay = NULL;
12031         const gchar *klass = NULL;
12032         gchar *cur_videosink_name = NULL;
12033         int ret = 0;
12034         int i = 0;
12035         int num_of_dec = 2; /* DEC1, DEC2 */
12036
12037         MMPLAYER_FENTER();
12038
12039         MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
12040         MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
12041
12042         player = MM_PLAYER_CAST(handle);
12043
12044         if (surface_type >= MM_DISPLAY_SURFACE_NUM) {
12045                 LOGE("Not support this surface type(%d) for changing vidoesink", surface_type);
12046                 MMPLAYER_FLEAVE();
12047                 return MM_ERROR_INVALID_ARGUMENT;
12048         }
12049
12050         /* load previous attributes */
12051         if (player->attrs) {
12052                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &prev_display_surface_type);
12053                 mm_attrs_get_data_by_name(player->attrs, "display_overlay", &prev_display_overlay);
12054                 LOGD("[0: Video surface, 4: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
12055                 if (prev_display_surface_type == surface_type) {
12056                         LOGD("incoming display surface type is same as previous one, do nothing..");
12057                         MMPLAYER_FLEAVE();
12058                         return MM_ERROR_NONE;
12059                 }
12060         } else {
12061                 LOGE("failed to load attributes");
12062                 MMPLAYER_FLEAVE();
12063                 return MM_ERROR_PLAYER_INTERNAL;
12064         }
12065
12066         /* check videosink element is created */
12067         if (!player->pipeline || !player->pipeline->videobin ||
12068                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
12069                 LOGD("videosink element is not yet ready");
12070
12071                 /* videobin is not created yet, so we just set attributes related to display surface */
12072                 LOGD("store display attribute for given surface type(%d)", surface_type);
12073                 mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
12074                 mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
12075                 if (mmf_attrs_commit(player->attrs)) {
12076                         LOGE("failed to commit attribute");
12077                         MMPLAYER_FLEAVE();
12078                         return MM_ERROR_PLAYER_INTERNAL;
12079                 }
12080                 MMPLAYER_FLEAVE();
12081                 return MM_ERROR_NONE;
12082         } else {
12083                 /* get player command status */
12084                 if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE)) {
12085                         LOGE("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command", player->cmd);
12086                         MMPLAYER_FLEAVE();
12087                         return MM_ERROR_PLAYER_INVALID_STATE;
12088                 }
12089
12090                 /* surface change */
12091                 for (i = 0 ; i < num_of_dec ; i++) {
12092                         if (player->pipeline->mainbin &&
12093                                 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) {
12094                                 GstElementFactory *decfactory;
12095                                 decfactory = gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst);
12096
12097                                 klass = gst_element_factory_get_metadata(decfactory, GST_ELEMENT_METADATA_KLASS);
12098                                 if ((g_strrstr(klass, "Codec/Decoder/Video"))) {
12099                                         if ((prev_display_surface_type == MM_DISPLAY_SURFACE_OVERLAY) && (surface_type == MM_DISPLAY_SURFACE_REMOTE)) {
12100                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, "fakesink", surface_type, display_overlay);
12101                                                 if (ret) {
12102                                                         goto ERROR_CASE;
12103                                                 } else {
12104                                                         LOGW("success to changing display surface(%d)", surface_type);
12105                                                         MMPLAYER_FLEAVE();
12106                                                         return MM_ERROR_NONE;
12107                                                 }
12108                                         } else if ((prev_display_surface_type == MM_DISPLAY_SURFACE_REMOTE) && (surface_type == MM_DISPLAY_SURFACE_OVERLAY)) {
12109                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_overlay, 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 {
12118                                                 LOGE("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface", surface_type, cur_videosink_name);
12119                                                 ret = MM_ERROR_PLAYER_INTERNAL;
12120                                                 goto ERROR_CASE;
12121                                         }
12122                                 }
12123                         }
12124                 }
12125         }
12126
12127 ERROR_CASE:
12128         /* rollback to previous attributes */
12129         mm_attrs_set_int_by_name(player->attrs, "display_surface_type", prev_display_surface_type);
12130         mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(void*));
12131         if (mmf_attrs_commit(player->attrs)) {
12132                 LOGE("failed to commit attributes to rollback");
12133                 MMPLAYER_FLEAVE();
12134                 return MM_ERROR_PLAYER_INTERNAL;
12135         }
12136         MMPLAYER_FLEAVE();
12137         return ret;
12138 }
12139
12140 /* NOTE : It does not support some use cases, eg using colorspace converter */
12141 int
12142 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
12143 {
12144         GstPad *src_pad_dec = NULL;
12145         GstPad *sink_pad_videosink = NULL;
12146         GstPad *sink_pad_videobin = NULL;
12147         GstClock *clock = NULL;
12148         MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
12149         int ret = MM_ERROR_NONE;
12150         gboolean is_audiobin_created = TRUE;
12151
12152         MMPLAYER_FENTER();
12153
12154         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
12155         MMPLAYER_RETURN_VAL_IF_FAIL(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
12156         MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
12157
12158         LOGD("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
12159         LOGD("surface type(%d), display overlay(%x)", surface_type, display_overlay);
12160
12161         /* get information whether if audiobin is created */
12162         if (!player->pipeline->audiobin ||
12163                      !player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
12164                 LOGW("audiobin is null, this video content may not have audio data");
12165                 is_audiobin_created = FALSE;
12166         }
12167
12168         /* get current state of player */
12169         previous_state = MMPLAYER_CURRENT_STATE(player);
12170         LOGD("previous state(%d)", previous_state);
12171
12172
12173         /* get src pad of decoder and block it */
12174         src_pad_dec = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
12175         if (!src_pad_dec) {
12176                 LOGE("failed to get src pad from decode in mainbin");
12177                 return MM_ERROR_PLAYER_INTERNAL;
12178         }
12179
12180         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING) {
12181                 LOGW("trying to block pad(video)");
12182 //              if (!gst_pad_set_blocked(src_pad_dec, TRUE))
12183                 gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
12184                         NULL, NULL, NULL);
12185                 {
12186                         LOGE("failed to set block pad(video)");
12187                         return MM_ERROR_PLAYER_INTERNAL;
12188                 }
12189                 LOGW("pad is blocked(video)");
12190         } else {
12191                 /* no data flows, so no need to do pad_block */
12192                 if (player->doing_seek)
12193                         LOGW("not completed seek(%d), do nothing", player->doing_seek);
12194
12195                 LOGD("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
12196         }
12197
12198         /* remove pad */
12199         if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
12200                 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin)))) {
12201                 LOGE("failed to remove previous ghost_pad for videobin");
12202                 return MM_ERROR_PLAYER_INTERNAL;
12203         }
12204
12205         /* change state of videobin to NULL */
12206         LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
12207         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
12208         if (ret != GST_STATE_CHANGE_SUCCESS) {
12209                 LOGE("failed to change state of videobin to NULL");
12210                 return MM_ERROR_PLAYER_INTERNAL;
12211         }
12212
12213         /* unlink between decoder and videobin and remove previous videosink from videobin */
12214         gst_element_unlink(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
12215         if (!gst_bin_remove(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst))) {
12216                 LOGE("failed to remove former videosink from videobin");
12217                 return MM_ERROR_PLAYER_INTERNAL;
12218         }
12219
12220         __mmplayer_del_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
12221
12222         /* create a new videosink and add it to videobin */
12223         player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, "videosink");
12224         if (!player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
12225                 LOGE("failed to create videosink element\n");
12226                 MMPLAYER_FLEAVE();
12227                 return MM_ERROR_PLAYER_INTERNAL;
12228         }
12229         gst_bin_add(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
12230         __mmplayer_add_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
12231         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
12232
12233         /* save attributes */
12234         if (player->attrs) {
12235                 /* set a new display surface type */
12236                 mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
12237                 /* set a new diplay overlay */
12238                 switch (surface_type) {
12239                 case MM_DISPLAY_SURFACE_OVERLAY:
12240                         LOGD("save attributes related to video display surface : id = %d", *(int*)display_overlay);
12241                         mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
12242                         break;
12243                 default:
12244                         LOGE("invalid type(%d) for changing display surface", surface_type);
12245                         MMPLAYER_FLEAVE();
12246                         return MM_ERROR_INVALID_ARGUMENT;
12247                 }
12248                 if (mmf_attrs_commit(player->attrs)) {
12249                         LOGE("failed to commit");
12250                         MMPLAYER_FLEAVE();
12251                         return MM_ERROR_PLAYER_INTERNAL;
12252                 }
12253         } else {
12254                 LOGE("player->attrs is null, failed to save attributes");
12255                 MMPLAYER_FLEAVE();
12256                 return MM_ERROR_PLAYER_INTERNAL;
12257         }
12258
12259         /* update video param */
12260         if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "update_all_param")) {
12261                 LOGE("failed to update video param");
12262                 return MM_ERROR_PLAYER_INTERNAL;
12263         }
12264
12265         /* change state of videobin to READY */
12266         LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
12267         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
12268         if (ret != GST_STATE_CHANGE_SUCCESS) {
12269                 LOGE("failed to change state of videobin to READY");
12270                 return MM_ERROR_PLAYER_INTERNAL;
12271         }
12272
12273         /* change ghostpad */
12274         sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
12275         if (!sink_pad_videosink) {
12276                 LOGE("failed to get sink pad from videosink element");
12277                 return MM_ERROR_PLAYER_INTERNAL;
12278         }
12279         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
12280         if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE)) {
12281                 LOGE("failed to set active to ghost_pad");
12282                 return MM_ERROR_PLAYER_INTERNAL;
12283         }
12284         if (FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
12285                 LOGE("failed to change ghostpad for videobin");
12286                 return MM_ERROR_PLAYER_INTERNAL;
12287         }
12288         gst_object_unref(sink_pad_videosink);
12289
12290         /* link decoder with videobin */
12291         sink_pad_videobin = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
12292         if (!sink_pad_videobin) {
12293                 LOGE("failed to get sink pad from videobin");
12294                 return MM_ERROR_PLAYER_INTERNAL;
12295         }
12296         if (GST_PAD_LINK_OK != gst_pad_link(src_pad_dec, sink_pad_videobin)) {
12297                 LOGE("failed to link");
12298                 return MM_ERROR_PLAYER_INTERNAL;
12299         }
12300         gst_object_unref(sink_pad_videobin);
12301
12302         /* clock setting for a new videosink plugin */
12303         /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
12304                         so we set it from audiosink plugin or pipeline(system clock) */
12305         if (!is_audiobin_created) {
12306                 LOGW("audiobin is not created, get clock from pipeline..");
12307                 clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
12308         } else {
12309                 clock = GST_ELEMENT_CLOCK(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
12310         }
12311         if (clock) {
12312                 GstClockTime now;
12313                 GstClockTime base_time;
12314                 LOGD("set the clock to videosink");
12315                 gst_element_set_clock(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
12316                 clock = GST_ELEMENT_CLOCK(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
12317                 if (clock) {
12318                         LOGD("got clock of videosink");
12319                         now = gst_clock_get_time(clock);
12320                         base_time = GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
12321                         LOGD("at time %" GST_TIME_FORMAT ", base %"
12322                                         GST_TIME_FORMAT, GST_TIME_ARGS(now), GST_TIME_ARGS(base_time));
12323                 } else {
12324                         LOGE("failed to get clock of videosink after setting clock");
12325                         return MM_ERROR_PLAYER_INTERNAL;
12326                 }
12327         } else
12328                 LOGW("failed to get clock, maybe it is the time before first playing");
12329
12330         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING) {
12331                 /* change state of videobin to PAUSED */
12332                 LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
12333                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
12334                 if (ret != GST_STATE_CHANGE_FAILURE) {
12335                         LOGW("change state of videobin to PLAYING, ret(%d)", ret);
12336                 } else {
12337                         LOGE("failed to change state of videobin to PLAYING");
12338                         return MM_ERROR_PLAYER_INTERNAL;
12339                 }
12340
12341                 /* release blocked and unref src pad of video decoder */
12342                 #if 0
12343                 if (!gst_pad_set_blocked(src_pad_dec, FALSE)) {
12344                         LOGE("failed to set pad blocked FALSE(video)");
12345                         return MM_ERROR_PLAYER_INTERNAL;
12346                 }
12347                 #endif
12348                 LOGW("pad is unblocked(video)");
12349         } else {
12350                 if (player->doing_seek)
12351                         LOGW("not completed seek(%d)", player->doing_seek);
12352                 /* change state of videobin to PAUSED */
12353                 LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
12354                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
12355                 if (ret != GST_STATE_CHANGE_FAILURE) {
12356                         LOGW("change state of videobin to PAUSED, ret(%d)", ret);
12357                 } else {
12358                         LOGE("failed to change state of videobin to PLAYING");
12359                         return MM_ERROR_PLAYER_INTERNAL;
12360                 }
12361
12362                 /* already skipped pad block */
12363                 LOGD("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
12364         }
12365
12366         /* do get/set position for new videosink plugin */
12367         {
12368                 gint64 position = 0;
12369
12370                 LOGD("do get/set position for new videosink plugin");
12371                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position)) {
12372                         LOGE("failed to get position");
12373                         return MM_ERROR_PLAYER_INTERNAL;
12374                 }
12375 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
12376                 /* accurate seek */
12377                 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE)) {
12378                         LOGE("failed to set position");
12379                         return MM_ERROR_PLAYER_INTERNAL;
12380                 }
12381 #else
12382                 /* key unit seek */
12383                 ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
12384                                 GST_FORMAT_TIME, (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
12385                                                         GST_SEEK_TYPE_SET, position,
12386                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
12387                 if (!ret) {
12388                         LOGE("failed to set position");
12389                         return MM_ERROR_PLAYER_INTERNAL;
12390                 }
12391 #endif
12392         }
12393
12394         if (src_pad_dec)
12395                 gst_object_unref(src_pad_dec);
12396         LOGD("success to change sink");
12397
12398         MMPLAYER_FLEAVE();
12399
12400         return MM_ERROR_NONE;
12401 }
12402
12403
12404 /* Note : if silent is true, then subtitle would not be displayed. :*/
12405 int _mmplayer_set_subtitle_silent(MMHandleType hplayer, int silent)
12406 {
12407         mm_player_t* player = (mm_player_t*) hplayer;
12408
12409         MMPLAYER_FENTER();
12410
12411         /* check player handle */
12412         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12413
12414         player->set_mode.subtitle_off = silent;
12415
12416         LOGD("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
12417
12418         MMPLAYER_FLEAVE();
12419
12420         return MM_ERROR_NONE;
12421 }
12422
12423 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
12424 {
12425         MMPlayerGstElement* mainbin = NULL;
12426         MMPlayerGstElement* textbin = NULL;
12427         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
12428         GstState current_state = GST_STATE_VOID_PENDING;
12429         GstState element_state = GST_STATE_VOID_PENDING;
12430         GstState element_pending_state = GST_STATE_VOID_PENDING;
12431         gint64 time = 0;
12432         GstEvent *event = NULL;
12433         int result = MM_ERROR_NONE;
12434
12435         GstClock *curr_clock = NULL;
12436         GstClockTime base_time, start_time, curr_time;
12437
12438
12439         MMPLAYER_FENTER();
12440
12441         /* check player handle */
12442         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
12443                                                                 player->pipeline &&
12444                                                                 player->pipeline->mainbin &&
12445                                                                 player->pipeline->textbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
12446
12447         mainbin = player->pipeline->mainbin;
12448         textbin = player->pipeline->textbin;
12449
12450         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
12451
12452         // sync clock with current pipeline
12453         curr_clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
12454         curr_time = gst_clock_get_time(curr_clock);
12455
12456         base_time = gst_element_get_base_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
12457         start_time = gst_element_get_start_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
12458
12459         LOGD("state: %d, base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
12460                 current_state, GST_TIME_ARGS(base_time), GST_TIME_ARGS(start_time), GST_TIME_ARGS(curr_time));
12461
12462         if (current_state > GST_STATE_READY) {
12463                 // sync state with current pipeline
12464                 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
12465                 gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_PAUSED);
12466                 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
12467
12468                 ret = gst_element_get_state(mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
12469                 if (GST_STATE_CHANGE_FAILURE == ret) {
12470                         LOGE("fail to state change.\n");
12471                         result = MM_ERROR_PLAYER_INTERNAL;
12472                         goto ERROR;
12473                 }
12474         }
12475
12476         gst_element_set_base_time(textbin[MMPLAYER_T_BIN].gst, base_time);
12477         gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
12478
12479         if (curr_clock) {
12480                 gst_element_set_clock(textbin[MMPLAYER_T_BIN].gst, curr_clock);
12481                 gst_object_unref(curr_clock);
12482         }
12483
12484         // seek to current position
12485         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
12486                 result = MM_ERROR_PLAYER_INVALID_STATE;
12487                 LOGE("gst_element_query_position failed, invalid state\n");
12488                 goto ERROR;
12489         }
12490
12491         LOGD("seek time = %"G_GINT64_FORMAT", rate = %f", time, player->playback_rate);
12492         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);
12493         if (event) {
12494                 __gst_send_event_to_sink(player, event);
12495         } else {
12496                 result = MM_ERROR_PLAYER_INTERNAL;
12497                 LOGE("gst_event_new_seek failed"); /* pipeline will got error and can not be recovered */
12498                 goto ERROR;
12499         }
12500
12501         /* sync state with current pipeline */
12502         gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
12503         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
12504         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
12505
12506         return MM_ERROR_NONE;
12507
12508 ERROR:
12509         /* release text pipeline resource */
12510         player->textsink_linked = 0;
12511
12512         /* release signal */
12513         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
12514
12515         /* release textbin with it's childs */
12516         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN);
12517         MMPLAYER_FREEIF(player->pipeline->textbin);
12518         player->pipeline->textbin = NULL;
12519
12520         /* release subtitle elem */
12521         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBSRC);
12522         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBPARSE);
12523
12524         return result;
12525 }
12526
12527 static int
12528 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
12529 {
12530         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
12531         GstState current_state = GST_STATE_VOID_PENDING;
12532
12533         MMHandleType attrs = 0;
12534         MMPlayerGstElement* mainbin = NULL;
12535         MMPlayerGstElement* textbin = NULL;
12536
12537         gchar* subtitle_uri = NULL;
12538         int result = MM_ERROR_NONE;
12539         const gchar *charset = NULL;
12540
12541         MMPLAYER_FENTER();
12542
12543         /* check player handle */
12544         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
12545                                                                 player->pipeline &&
12546                                                                 player->pipeline->mainbin &&
12547                                                                 player->pipeline->textbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
12548         MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT);
12549
12550         mainbin = player->pipeline->mainbin;
12551         textbin = player->pipeline->textbin;
12552
12553         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
12554         if (current_state < GST_STATE_READY) {
12555                 result = MM_ERROR_PLAYER_INVALID_STATE;
12556                 LOGE("Pipeline is not in proper state\n");
12557                 goto EXIT;
12558         }
12559
12560         attrs = MMPLAYER_GET_ATTRS(player);
12561         if (!attrs) {
12562                 LOGE("cannot get content attribute\n");
12563                 result = MM_ERROR_PLAYER_INTERNAL;
12564                 goto EXIT;
12565         }
12566
12567         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
12568         if (!subtitle_uri || strlen(subtitle_uri) < 1) {
12569                 LOGE("subtitle uri is not proper filepath\n");
12570                 result = MM_ERROR_PLAYER_INVALID_URI;
12571                 goto EXIT;
12572         }
12573
12574         if (!util_get_storage_info(filepath, &player->storage_info[MMPLAYER_PATH_TEXT])) {
12575                 LOGE("failed to get storage info of subtitle path");
12576                 result = MM_ERROR_PLAYER_INVALID_URI;
12577                 goto EXIT;
12578         }
12579
12580         LOGD("old subtitle file path is [%s]\n", subtitle_uri);
12581         LOGD("new subtitle file path is [%s]\n", filepath);
12582
12583         if (!strcmp(filepath, subtitle_uri)) {
12584                 LOGD("No need to swtich subtitle, as input filepath is same as current filepath\n");
12585                 goto EXIT;
12586         } else {
12587                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
12588                 if (mmf_attrs_commit(player->attrs)) {
12589                         LOGE("failed to commit.\n");
12590                         goto EXIT;
12591                 }
12592         }
12593
12594         //gst_pad_set_blocked_async(src-srcpad, TRUE)
12595         MMPLAYER_SUBTITLE_INFO_LOCK(player);
12596         player->subtitle_language_list = NULL;
12597         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
12598
12599         ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
12600         if (ret != GST_STATE_CHANGE_SUCCESS) {
12601                 LOGE("failed to change state of textbin to READY");
12602                 result = MM_ERROR_PLAYER_INTERNAL;
12603                 goto EXIT;
12604         }
12605
12606         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_READY);
12607         if (ret != GST_STATE_CHANGE_SUCCESS) {
12608                 LOGE("failed to change state of subparse to READY");
12609                 result = MM_ERROR_PLAYER_INTERNAL;
12610                 goto EXIT;
12611         }
12612
12613         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
12614         if (ret != GST_STATE_CHANGE_SUCCESS) {
12615                 LOGE("failed to change state of filesrc to READY");
12616                 result = MM_ERROR_PLAYER_INTERNAL;
12617                 goto EXIT;
12618         }
12619
12620         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_TEXT);
12621
12622         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
12623
12624         charset = util_get_charset(filepath);
12625         if (charset) {
12626                 LOGD("detected charset is %s\n", charset);
12627                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
12628         }
12629
12630         result = _mmplayer_sync_subtitle_pipeline(player);
12631
12632 EXIT:
12633         MMPLAYER_FLEAVE();
12634         return result;
12635 }
12636
12637 /* API to switch between external subtitles */
12638 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
12639 {
12640         int result = MM_ERROR_NONE;
12641         mm_player_t* player = (mm_player_t*)hplayer;
12642         char *path = NULL;
12643
12644         MMPLAYER_FENTER();
12645
12646         /* check player handle */
12647         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12648
12649         /* filepath can be null in idle state */
12650         if (filepath) {
12651                 /* check file path */
12652                 if ((path = strstr(filepath, "file://")))
12653                         result = util_exist_file_path(path + 7);
12654                 else
12655                         result = util_exist_file_path(filepath);
12656
12657                 if (result != MM_ERROR_NONE) {
12658                         LOGE("invalid subtitle path 0x%X", result);
12659                         return result; /* file not found or permission denied */
12660                 }
12661         }
12662
12663         if (!player->pipeline) {
12664                 /* IDLE state */
12665                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
12666                 if (mmf_attrs_commit(player->attrs)) {
12667                         LOGE("failed to commit");       /* subtitle path will not be created */
12668                         return MM_ERROR_PLAYER_INTERNAL;
12669                 }
12670         } else {
12671                 /* cur state <> IDLE(READY, PAUSE, PLAYING..) */
12672                 /* check filepath */
12673                 MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT);
12674
12675                 if (!__mmplayer_check_subtitle(player)) {
12676                         mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
12677                         if (mmf_attrs_commit(player->attrs)) {
12678                                 LOGE("failed to commit");
12679                                 return MM_ERROR_PLAYER_INTERNAL;
12680                         }
12681
12682                         if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) {
12683                                 LOGE("fail to create text pipeline");
12684                                 return MM_ERROR_PLAYER_INTERNAL;
12685                         }
12686
12687                         result = _mmplayer_sync_subtitle_pipeline(player);
12688                 } else {
12689                         result = __mmplayer_change_external_subtitle_language(player, filepath);
12690                 }
12691
12692                 MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
12693                 player->is_external_subtitle_added_now = TRUE;
12694
12695                 MMPLAYER_SUBTITLE_INFO_LOCK(player);
12696                 if (!player->subtitle_language_list) {
12697                         gint64 timeout = g_get_monotonic_time() + G_TIME_SPAN_SECOND; /* wait 1 sec */
12698                         if (!MMPLAYER_SUBTITLE_INFO_WAIT_UNTIL(player, timeout))
12699                                 LOGW("subtitle language list is not updated yet");
12700                 }
12701                 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
12702         }
12703
12704         MMPLAYER_FLEAVE();
12705         return result;
12706 }
12707
12708 static int
12709 __mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index)
12710 {
12711         int result = MM_ERROR_NONE;
12712         gchar* change_pad_name = NULL;
12713         GstPad* sinkpad = NULL;
12714         MMPlayerGstElement* mainbin = NULL;
12715         enum MainElementID elemId = MMPLAYER_M_NUM;
12716         GstCaps* caps = NULL;
12717         gint total_track_num = 0;
12718
12719         MMPLAYER_FENTER();
12720
12721         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin,
12722                                                                                                         MM_ERROR_PLAYER_NOT_INITIALIZED);
12723
12724         LOGD("Change Track(%d) to %d\n", type, index);
12725
12726         mainbin = player->pipeline->mainbin;
12727
12728         if (type == MM_PLAYER_TRACK_TYPE_AUDIO) {
12729                 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
12730         } else if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
12731                 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
12732         } else {
12733                 /* Changing Video Track is not supported. */
12734                 LOGE("Track Type Error\n");
12735                 goto EXIT;
12736         }
12737
12738         if (mainbin[elemId].gst == NULL) {
12739                 result = MM_ERROR_PLAYER_NO_OP;
12740                 LOGD("Req track doesn't exist\n");
12741                 goto EXIT;
12742         }
12743
12744         total_track_num = player->selector[type].total_track_num;
12745         if (total_track_num <= 0) {
12746                 result = MM_ERROR_PLAYER_NO_OP;
12747                 LOGD("Language list is not available \n");
12748                 goto EXIT;
12749         }
12750
12751         if ((index < 0) || (index >= total_track_num)) {
12752                 result = MM_ERROR_INVALID_ARGUMENT;
12753                 LOGD("Not a proper index : %d \n", index);
12754                 goto EXIT;
12755         }
12756
12757         /*To get the new pad from the selector*/
12758         change_pad_name = g_strdup_printf("sink_%u", index);
12759         if (change_pad_name == NULL) {
12760                 result = MM_ERROR_PLAYER_INTERNAL;
12761                 LOGD("Pad does not exists\n");
12762                 goto EXIT;
12763         }
12764
12765         LOGD("new active pad name: %s\n", change_pad_name);
12766
12767         sinkpad = gst_element_get_static_pad(mainbin[elemId].gst, change_pad_name);
12768         if (sinkpad == NULL) {
12769                 LOGD("sinkpad is NULL");
12770                 result = MM_ERROR_PLAYER_INTERNAL;
12771                 goto EXIT;
12772         }
12773
12774         LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
12775         g_object_set(mainbin[elemId].gst, "active-pad", sinkpad, NULL);
12776
12777         caps = gst_pad_get_current_caps(sinkpad);
12778         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
12779
12780         if (sinkpad)
12781                 gst_object_unref(sinkpad);
12782
12783         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
12784                 __mmplayer_set_audio_attrs(player, caps);
12785
12786 EXIT:
12787
12788         MMPLAYER_FREEIF(change_pad_name);
12789         return result;
12790 }
12791
12792 int _mmplayer_change_track_language(MMHandleType hplayer, MMPlayerTrackType type, int index)
12793 {
12794         int result = MM_ERROR_NONE;
12795         mm_player_t* player = NULL;
12796         MMPlayerGstElement* mainbin = NULL;
12797
12798         gint current_active_index = 0;
12799
12800         GstState current_state = GST_STATE_VOID_PENDING;
12801         GstEvent* event = NULL;
12802         gint64 time = 0;
12803
12804         MMPLAYER_FENTER();
12805
12806         player = (mm_player_t*)hplayer;
12807         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12808
12809         if (!player->pipeline) {
12810                 LOGE("Track %d pre setting -> %d\n", type, index);
12811
12812                 player->selector[type].active_pad_index = index;
12813                 goto EXIT;
12814         }
12815
12816         mainbin = player->pipeline->mainbin;
12817
12818         current_active_index = player->selector[type].active_pad_index;
12819
12820         /*If index is same as running index no need to change the pad*/
12821         if (current_active_index == index)
12822                 goto EXIT;
12823
12824         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
12825                 result = MM_ERROR_PLAYER_INVALID_STATE;
12826                 goto EXIT;
12827         }
12828
12829         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
12830         if (current_state < GST_STATE_PAUSED) {
12831                 result = MM_ERROR_PLAYER_INVALID_STATE;
12832                 LOGW("Pipeline not in porper state\n");
12833                 goto EXIT;
12834         }
12835
12836         result = __mmplayer_change_selector_pad(player, type, index);
12837         if (result != MM_ERROR_NONE) {
12838                 LOGE("change selector pad error\n");
12839                 goto EXIT;
12840         }
12841
12842         player->selector[type].active_pad_index = index;
12843
12844         if (current_state == GST_STATE_PLAYING) {
12845                 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);
12846                 if (event) {
12847                         __gst_send_event_to_sink(player, event);
12848                 } else {
12849                         result = MM_ERROR_PLAYER_INTERNAL;
12850                         goto EXIT;
12851                 }
12852         }
12853
12854 EXIT:
12855         return result;
12856 }
12857
12858 int _mmplayer_get_subtitle_silent(MMHandleType hplayer, int* silent)
12859 {
12860         mm_player_t* player = (mm_player_t*) hplayer;
12861
12862         MMPLAYER_FENTER();
12863
12864         /* check player handle */
12865         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12866
12867         *silent = player->set_mode.subtitle_off;
12868
12869         LOGD("subtitle is %s.\n", silent ? "ON" : "OFF");
12870
12871         MMPLAYER_FLEAVE();
12872
12873         return MM_ERROR_NONE;
12874 }
12875
12876 gboolean
12877 __is_ms_buff_src(mm_player_t* player)
12878 {
12879         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
12880
12881         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_MS_BUFF) ? TRUE : FALSE;
12882 }
12883
12884 gboolean
12885 __has_suffix(mm_player_t* player, const gchar* suffix)
12886 {
12887         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
12888         MMPLAYER_RETURN_VAL_IF_FAIL(suffix, FALSE);
12889
12890         gboolean ret = FALSE;
12891         gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
12892         gchar* t_suffix = g_ascii_strdown(suffix, -1);
12893
12894         if (g_str_has_suffix(player->profile.uri, suffix))
12895                 ret = TRUE;
12896
12897         MMPLAYER_FREEIF(t_url);
12898         MMPLAYER_FREEIF(t_suffix);
12899
12900         return ret;
12901 }
12902
12903 int
12904 _mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
12905 {
12906         mm_player_t* player = (mm_player_t*) hplayer;
12907
12908         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12909
12910         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL) {
12911                 MMPLAYER_PRINT_STATE(player);
12912                 LOGE("wrong-state : can't set the download mode to parse");
12913                 return MM_ERROR_PLAYER_INVALID_STATE;
12914         }
12915
12916         LOGD("set video hub download mode to %s", (mode) ? "ON" : "OFF");
12917         player->video_hub_download_mode = mode;
12918
12919         return MM_ERROR_NONE;
12920 }
12921
12922 int
12923 _mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
12924 {
12925         mm_player_t* player = (mm_player_t*) hplayer;
12926
12927         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12928
12929         LOGD("enable sync handler : %s", (enable) ? "ON" : "OFF");
12930         player->sync_handler = enable;
12931
12932         return MM_ERROR_NONE;
12933 }
12934
12935 int
12936 _mmplayer_set_video_share_master_clock(MMHandleType hplayer, gint64 clock, gint64 clock_delta,
12937                                                                                 gint64 video_time, gint64 media_clock, gint64 audio_time)
12938 {
12939         mm_player_t* player = (mm_player_t*) hplayer;
12940         MMPlayerGstElement* mainbin = NULL;
12941         GstClockTime start_time_audio = 0, start_time_video = 0;
12942         GstClockTimeDiff base_time = 0, new_base_time = 0;
12943         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
12944         gint64 api_delta = 0;
12945         gint64 position = 0, position_delta = 0;
12946         gint64 adj_base_time = 0;
12947         GstClock *curr_clock = NULL;
12948         GstClockTime curr_time = 0;
12949         gboolean query_ret = TRUE;
12950         int result = MM_ERROR_NONE;
12951
12952         MMPLAYER_FENTER();
12953
12954         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
12955         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
12956         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
12957
12958         /* LOGD("in(us) : %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT,
12959                                                                         clock, clock_delta, video_time, media_clock, audio_time); */
12960
12961         if ((video_time < 0) || (player->doing_seek)) {
12962                 LOGD("skip setting master clock. %lld", video_time);
12963                 goto EXIT;
12964         }
12965
12966         mainbin = player->pipeline->mainbin;
12967
12968         curr_clock = gst_pipeline_get_clock(GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
12969         curr_time = gst_clock_get_time(curr_clock);
12970
12971         current_state = MMPLAYER_CURRENT_STATE(player);
12972
12973         if (current_state == MM_PLAYER_STATE_PLAYING)
12974                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
12975
12976         if ((current_state != MM_PLAYER_STATE_PLAYING) ||
12977                 (!query_ret)) {
12978                 position = player->last_position;
12979                 LOGD("query fail. %"G_GINT64_FORMAT, position);
12980         }
12981
12982         clock *= GST_USECOND;
12983         clock_delta *= GST_USECOND;
12984
12985         api_delta = clock - curr_time;
12986         if ((player->video_share_api_delta == 0) || (player->video_share_api_delta > api_delta))
12987                 player->video_share_api_delta = api_delta;
12988         else
12989                 clock_delta += (api_delta - player->video_share_api_delta);
12990
12991         if ((player->video_share_clock_delta == 0) || (player->video_share_clock_delta > clock_delta)) {
12992                 player->video_share_clock_delta = (gint64)clock_delta;
12993
12994                 position_delta = (position/GST_USECOND) - video_time;
12995                 position_delta *= GST_USECOND;
12996
12997                 adj_base_time = position_delta;
12998                 LOGD("video_share_clock_delta = %"G_GINT64_FORMAT", adj = %"G_GINT64_FORMAT, player->video_share_clock_delta, adj_base_time);
12999
13000         } else {
13001                 gint64 new_play_time = 0;
13002                 gint64 network_delay = 0;
13003
13004                 video_time *= GST_USECOND;
13005
13006                 network_delay = clock_delta - player->video_share_clock_delta;
13007                 new_play_time = video_time + network_delay;
13008
13009                 adj_base_time = position - new_play_time;
13010
13011                 LOGD("%"G_GINT64_FORMAT"(delay) = %"G_GINT64_FORMAT" - %"G_GINT64_FORMAT" / %"G_GINT64_FORMAT
13012                          "(adj) = %"G_GINT64_FORMAT"(slave_pos) - %"G_GINT64_FORMAT"(master_pos) - %"G_GINT64_FORMAT"(delay)",
13013                         network_delay, clock_delta, player->video_share_clock_delta, adj_base_time, position, video_time, network_delay);
13014         }
13015
13016         /* Adjust Current Stream Time with base_time of sink
13017          * 1. Set Start time to CLOCK NONE, to control the base time by MSL
13018          * 2. Set new base time
13019          *    if adj_base_time is positive value, the stream time will be decreased.
13020          * 3. If seek event is occurred, the start time will be reset. */
13021         if ((player->pipeline->audiobin) &&
13022                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst)) {
13023                 start_time_audio = gst_element_get_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
13024
13025                 if (start_time_audio != GST_CLOCK_TIME_NONE) {
13026                         LOGD("audio sink : gst_element_set_start_time -> NONE");
13027                         gst_element_set_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, GST_CLOCK_TIME_NONE);
13028                 }
13029
13030                 base_time = gst_element_get_base_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
13031         }
13032
13033         if ((player->pipeline->videobin) &&
13034                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst)) {
13035                 start_time_video = gst_element_get_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
13036
13037                 if (start_time_video != GST_CLOCK_TIME_NONE) {
13038                         LOGD("video sink : gst_element_set_start_time -> NONE");
13039                         gst_element_set_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst, GST_CLOCK_TIME_NONE);
13040                 }
13041
13042                 // if videobin exist, get base_time from videobin.
13043                 base_time = gst_element_get_base_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
13044         }
13045
13046         new_base_time = base_time + adj_base_time;
13047
13048         if ((player->pipeline->audiobin) &&
13049                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
13050                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), (GstClockTime)new_base_time);
13051
13052         if ((player->pipeline->videobin) &&
13053                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
13054                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), (GstClockTime)new_base_time);
13055
13056 EXIT:
13057         MMPLAYER_FLEAVE();
13058
13059         return result;
13060 }
13061
13062 int
13063 _mmplayer_get_video_share_master_clock(MMHandleType hplayer, gint64 *video_time, gint64 *media_clock, gint64 *audio_time)
13064 {
13065         mm_player_t* player = (mm_player_t*) hplayer;
13066         MMPlayerGstElement* mainbin = NULL;
13067         GstClock *curr_clock = NULL;
13068         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
13069         gint64 position = 0;
13070         gboolean query_ret = TRUE;
13071
13072         MMPLAYER_FENTER();
13073
13074         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
13075         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
13076         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
13077
13078         MMPLAYER_RETURN_VAL_IF_FAIL(video_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
13079         MMPLAYER_RETURN_VAL_IF_FAIL(media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT);
13080         MMPLAYER_RETURN_VAL_IF_FAIL(audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
13081
13082         mainbin = player->pipeline->mainbin;
13083
13084         curr_clock = gst_pipeline_get_clock(GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
13085
13086         current_state = MMPLAYER_CURRENT_STATE(player);
13087
13088         if (current_state != MM_PLAYER_STATE_PAUSED)
13089                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
13090
13091         if ((current_state == MM_PLAYER_STATE_PAUSED) ||
13092                 (!query_ret))
13093                 position = player->last_position;
13094
13095         *media_clock = *video_time = *audio_time = (position/GST_USECOND);
13096
13097         LOGD("media_clock: %"G_GINT64_FORMAT", video_time: %"G_GINT64_FORMAT"(us)", *media_clock, *video_time);
13098
13099         if (curr_clock)
13100                 gst_object_unref(curr_clock);
13101
13102         MMPLAYER_FLEAVE();
13103
13104         return MM_ERROR_NONE;
13105 }
13106
13107 static gboolean
13108 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
13109 {
13110         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13111         MMPLAYER_RETURN_VAL_IF_FAIL(element, FALSE);
13112
13113         gchar *factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
13114         gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
13115
13116         int idx = 0;
13117
13118         for (idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++) {
13119                 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx])) {
13120                         LOGD("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
13121                         mm_player_dump_t *dump_s;
13122                         dump_s = g_malloc(sizeof(mm_player_dump_t));
13123
13124                         if (dump_s == NULL) {
13125                                 LOGE("malloc fail");
13126                                 return FALSE;
13127                         }
13128
13129                         dump_s->dump_element_file = NULL;
13130                         dump_s->dump_pad = NULL;
13131                         dump_s->dump_pad = gst_element_get_static_pad(element, "sink");
13132
13133                         if (dump_s->dump_pad) {
13134                                 memset(dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
13135                                 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]);
13136                                 dump_s->dump_element_file = fopen(dump_file_name, "w+");
13137                                 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);
13138                                 /* add list for removed buffer probe and close FILE */
13139                                 player->dump_list = g_list_append(player->dump_list, dump_s);
13140                                 LOGD("%s sink pad added buffer probe for dump", factory_name);
13141                                 return TRUE;
13142                         } else {
13143                                 g_free(dump_s);
13144                                 dump_s = NULL;
13145                                 LOGE("failed to get %s sink pad added", factory_name);
13146                         }
13147
13148
13149                 }
13150         }
13151         return FALSE;
13152 }
13153
13154 static GstPadProbeReturn
13155 __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data)
13156 {
13157         FILE *dump_data = (FILE *) u_data;
13158 //      int written = 0;
13159         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
13160         GstMapInfo probe_info = GST_MAP_INFO_INIT;
13161
13162         MMPLAYER_RETURN_VAL_IF_FAIL(dump_data, FALSE);
13163
13164         gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
13165
13166 //      LOGD("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
13167
13168         fwrite(probe_info.data, 1, probe_info.size , dump_data);
13169
13170         return GST_PAD_PROBE_OK;
13171 }
13172
13173 static void
13174 __mmplayer_release_dump_list(GList *dump_list)
13175 {
13176         if (dump_list) {
13177                 GList *d_list = dump_list;
13178                 for (; d_list; d_list = g_list_next(d_list)) {
13179                         mm_player_dump_t *dump_s = d_list->data;
13180                         if (dump_s->dump_pad) {
13181                                 if (dump_s->probe_handle_id)
13182                                         gst_pad_remove_probe(dump_s->dump_pad, dump_s->probe_handle_id);
13183                         }
13184                         if (dump_s->dump_element_file) {
13185                                 fclose(dump_s->dump_element_file);
13186                                 dump_s->dump_element_file = NULL;
13187                         }
13188                         MMPLAYER_FREEIF(dump_s);
13189                 }
13190                 g_list_free(dump_list);
13191                 dump_list = NULL;
13192         }
13193 }
13194
13195 int
13196 _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
13197 {
13198         mm_player_t* player = (mm_player_t*) hplayer;
13199
13200         MMPLAYER_FENTER();
13201
13202         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13203         MMPLAYER_RETURN_VAL_IF_FAIL(exist, MM_ERROR_INVALID_ARGUMENT);
13204
13205         *exist = player->has_closed_caption;
13206
13207         MMPLAYER_FLEAVE();
13208
13209         return MM_ERROR_NONE;
13210 }
13211
13212 void _mm_player_video_stream_internal_buffer_unref(void *buffer)
13213 {
13214         MMPLAYER_FENTER();
13215         if (buffer) {
13216                 // LOGD("unref internal gst buffer %p", buffer);
13217                 gst_buffer_unref((GstBuffer *)buffer);
13218                 buffer = NULL;
13219         }
13220         MMPLAYER_FLEAVE();
13221 }
13222
13223 void
13224 __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data)
13225 {
13226         mm_player_t *player  = (mm_player_t*)user_data;
13227         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
13228         guint64 current_level_bytes = 0;
13229
13230         MMPLAYER_RETURN_IF_FAIL(player);
13231
13232         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13233
13234         LOGI("app-src: feed audio(%llu)\n", current_level_bytes);
13235         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13236
13237         if (player->media_stream_buffer_status_cb[type])
13238                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
13239         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13240
13241 }
13242
13243 void
13244 __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data)
13245 {
13246         mm_player_t *player  = (mm_player_t*)user_data;
13247         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
13248         guint64 current_level_bytes = 0;
13249
13250         MMPLAYER_RETURN_IF_FAIL(player);
13251
13252         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13253
13254         LOGI("app-src: feed video(%llu)\n", current_level_bytes);
13255
13256         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13257         if (player->media_stream_buffer_status_cb[type])
13258                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
13259         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13260 }
13261
13262 void
13263 __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data)
13264 {
13265         mm_player_t *player  = (mm_player_t*)user_data;
13266         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
13267         guint64 current_level_bytes = 0;
13268
13269         MMPLAYER_RETURN_IF_FAIL(player);
13270
13271         LOGI("app-src: feed subtitle\n");
13272
13273         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13274
13275         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13276         if (player->media_stream_buffer_status_cb[type])
13277                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
13278
13279         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13280 }
13281
13282 void
13283 __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data)
13284 {
13285         mm_player_t *player  = (mm_player_t*)user_data;
13286         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
13287         guint64 current_level_bytes = 0;
13288
13289         MMPLAYER_RETURN_IF_FAIL(player);
13290
13291         LOGI("app-src: audio buffer is full.\n");
13292
13293         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13294
13295         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13296
13297         if (player->media_stream_buffer_status_cb[type])
13298                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param[type]);
13299
13300         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13301 }
13302
13303 void
13304 __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data)
13305 {
13306         mm_player_t *player  = (mm_player_t*)user_data;
13307         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
13308         guint64 current_level_bytes = 0;
13309
13310         MMPLAYER_RETURN_IF_FAIL(player);
13311
13312         LOGI("app-src: video buffer is full.\n");
13313
13314         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13315
13316         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13317         if (player->media_stream_buffer_status_cb[type])
13318                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param[type]);
13319
13320         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13321 }
13322
13323 gboolean
13324 __gst_seek_audio_data(GstElement * appsrc, guint64 position, gpointer user_data)
13325 {
13326         mm_player_t *player  = (mm_player_t*)user_data;
13327         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
13328
13329         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13330
13331         LOGD("app-src: seek audio data %llu\n", position);
13332         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13333
13334         if (player->media_stream_seek_data_cb[type])
13335                 player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
13336         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13337
13338         return TRUE;
13339 }
13340
13341 gboolean
13342 __gst_seek_video_data(GstElement * appsrc, guint64 position, gpointer user_data)
13343 {
13344         mm_player_t *player  = (mm_player_t*)user_data;
13345         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
13346
13347         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13348
13349         LOGD("app-src: seek video data %llu\n", position);
13350         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13351         if (player->media_stream_seek_data_cb[type])
13352                 player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
13353         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13354
13355         return TRUE;
13356 }
13357
13358 gboolean
13359 __gst_seek_subtitle_data(GstElement * appsrc, guint64 position, gpointer user_data)
13360 {
13361         mm_player_t *player  = (mm_player_t*)user_data;
13362         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
13363
13364         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13365
13366         LOGD("app-src: seek subtitle data\n");
13367         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13368
13369         if (player->media_stream_seek_data_cb[type])
13370                 player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
13371         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13372
13373         return TRUE;
13374 }
13375
13376 int
13377 _mmplayer_set_pcm_spec(MMHandleType hplayer, int samplerate, int channel)
13378 {
13379         mm_player_t* player = (mm_player_t*) hplayer;
13380
13381         MMPLAYER_FENTER();
13382
13383         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13384
13385         player->pcm_samplerate = samplerate;
13386         player->pcm_channel = channel;
13387
13388         MMPLAYER_FLEAVE();
13389         return MM_ERROR_NONE;
13390 }
13391
13392 int _mmplayer_get_timeout(MMHandleType hplayer, int *timeout)
13393 {
13394         mm_player_t* player = (mm_player_t*) hplayer;
13395
13396         MMPLAYER_FENTER();
13397
13398         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13399         MMPLAYER_RETURN_VAL_IF_FAIL(timeout, MM_ERROR_COMMON_INVALID_ARGUMENT);
13400
13401         if (MMPLAYER_IS_STREAMING(player))
13402                 *timeout = player->ini.live_state_change_timeout;
13403         else
13404                 *timeout = player->ini.localplayback_state_change_timeout;
13405
13406         LOGD("timeout = %d\n", *timeout);
13407
13408         MMPLAYER_FLEAVE();
13409         return MM_ERROR_NONE;
13410 }
13411
13412 int _mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int *extra_num)
13413 {
13414         mm_player_t* player = (mm_player_t*) hplayer;
13415
13416         MMPLAYER_FENTER();
13417
13418         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13419         MMPLAYER_RETURN_VAL_IF_FAIL(num && extra_num, MM_ERROR_COMMON_INVALID_ARGUMENT);
13420
13421         *num = player->video_num_buffers;
13422         *extra_num = player->video_extra_num_buffers;
13423
13424         LOGD("state %d, num %d(%d)\n", MMPLAYER_CURRENT_STATE(player), *num, *extra_num);
13425
13426         MMPLAYER_FLEAVE();
13427         return MM_ERROR_NONE;
13428 }
13429
13430 static void
13431 __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type)
13432 {
13433         int i = 0;
13434         MMPLAYER_FENTER();
13435         MMPLAYER_RETURN_IF_FAIL(player);
13436
13437         for (i = 0; i < MMPLAYER_PATH_MAX; i++) {
13438
13439                 if (path_type == MMPLAYER_PATH_MAX || path_type == i) {
13440                         player->storage_info[i].type = STORAGE_TYPE_INTERNAL;
13441                         player->storage_info[i].state = STORAGE_STATE_UNMOUNTABLE;
13442                         player->storage_info[i].id = -1;
13443                         memset(player->storage_info[i].path, 0x00, MM_MAX_URL_LEN);
13444
13445                         if (path_type != MMPLAYER_PATH_MAX)
13446                                 break;
13447                 }
13448         }
13449
13450         MMPLAYER_FLEAVE();
13451 }
13452
13453 int _mmplayer_manage_external_storage_state(MMHandleType hplayer, int id, int state)
13454 {
13455         int ret = MM_ERROR_NONE;
13456         mm_player_t* player = (mm_player_t*)hplayer;
13457         MMMessageParamType msg_param = {0, };
13458
13459         MMPLAYER_FENTER();
13460         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13461
13462         LOGW("state changed storage %d:%d", id, state);
13463
13464         if (state != STORAGE_STATE_UNMOUNTABLE && state != STORAGE_STATE_REMOVED)
13465                 return MM_ERROR_NONE;
13466
13467         /* FIXME: text path should be handled seperately. */
13468         if (((player->storage_info[MMPLAYER_PATH_VOD].type == STORAGE_TYPE_EXTERNAL) && (player->storage_info[MMPLAYER_PATH_VOD].id == id)) ||
13469                 ((player->storage_info[MMPLAYER_PATH_TEXT].type == STORAGE_TYPE_EXTERNAL) && (player->storage_info[MMPLAYER_PATH_TEXT].id == id))) {
13470                 LOGW("external storage is removed");
13471
13472                 if (player->msg_posted == FALSE) {
13473                         memset(&msg_param, 0, sizeof(MMMessageParamType));
13474                         msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
13475                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
13476                         player->msg_posted = TRUE;
13477                 }
13478
13479                 /* unrealize the player */
13480                 ret = _mmplayer_unrealize(hplayer);
13481                 if (ret != MM_ERROR_NONE)
13482                         LOGE("failed to unrealize");
13483         }
13484
13485         MMPLAYER_FLEAVE();
13486         return ret;
13487 }
13488
13489 int _mmplayer_get_adaptive_variant_info(MMHandleType hplayer, int *num, char **var_info)
13490 {
13491         int ret = MM_ERROR_NONE;
13492         mm_player_t* player = (mm_player_t*) hplayer;
13493         int idx = 0, total = 0;
13494         gchar *result = NULL, *tmp = NULL;
13495
13496         MMPLAYER_FENTER();
13497         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13498         MMPLAYER_RETURN_VAL_IF_FAIL(num && var_info, MM_ERROR_COMMON_INVALID_ARGUMENT);
13499
13500         total = *num = g_list_length(player->adaptive_info.var_list);
13501         if (total <= 0) {
13502                 LOGW("There is no stream variant info.");
13503                 return ret;
13504         }
13505
13506         result = g_strdup("");
13507         for (idx = 0 ; idx < total ; idx++) {
13508                 VariantData *v_data = NULL;
13509                 v_data = g_list_nth_data(player->adaptive_info.var_list, idx);
13510
13511                 if (v_data) {
13512                         gchar data[64] = {0};
13513                         snprintf(data, sizeof(data), "%d,%d,%d,", v_data->bandwidth, v_data->width, v_data->height);
13514
13515                         tmp = g_strconcat(result, data, NULL);
13516                         g_free(result);
13517                         result = tmp;
13518                 } else {
13519                         LOGW("There is no variant data in %d", idx);
13520                         (*num)--;
13521                 }
13522         }
13523
13524         *var_info = (char *)result;
13525
13526         LOGD("variant info %d:%s", *num, *var_info);
13527         MMPLAYER_FLEAVE();
13528         return ret;
13529 }
13530
13531 int _mmplayer_set_max_adaptive_variant_limit(MMHandleType hplayer, int bandwidth, int width, int height)
13532 {
13533         int ret = MM_ERROR_NONE;
13534         mm_player_t* player = (mm_player_t*) hplayer;
13535
13536         MMPLAYER_FENTER();
13537         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13538
13539         LOGD("set limit to [b]%d, [w]%d, [h]%d", bandwidth, width, height);
13540
13541         player->adaptive_info.limit.bandwidth = (bandwidth >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (bandwidth) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
13542         player->adaptive_info.limit.width = (width >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (width) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
13543         player->adaptive_info.limit.height = (height >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (height) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
13544
13545         if (player->pipeline && player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst) {
13546                 LOGD("update max limit of %s", GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst));
13547                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
13548                                                 "max-bandwidth", bandwidth, "max-video-width", width, "max-video-height", height, NULL);
13549
13550                 /* FIXME: seek to current position for applying new variant limitation */
13551         }
13552
13553         MMPLAYER_FLEAVE();
13554         return ret;
13555
13556 }
13557
13558 int _mmplayer_get_max_adaptive_variant_limit(MMHandleType hplayer, int *bandwidth, int *width, int *height)
13559 {
13560         int ret = MM_ERROR_NONE;
13561         mm_player_t* player = (mm_player_t*) hplayer;
13562
13563         MMPLAYER_FENTER();
13564         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13565         MMPLAYER_RETURN_VAL_IF_FAIL(bandwidth && width && height, MM_ERROR_COMMON_INVALID_ARGUMENT);
13566
13567         *bandwidth = player->adaptive_info.limit.bandwidth;
13568         *width = player->adaptive_info.limit.width;
13569         *height = player->adaptive_info.limit.height;
13570
13571         LOGD("get limit to [b]%d, [w]%d, [h]%d", *bandwidth, *width, *height);
13572
13573         MMPLAYER_FLEAVE();
13574         return ret;
13575 }
13576
13577 int _mmplayer_set_streaming_buffering_time(MMHandleType hplayer, int buffer_ms, int rebuffer_ms)
13578 {
13579         int ret = MM_ERROR_NONE;
13580         mm_player_t* player = (mm_player_t*) hplayer;
13581
13582         MMPLAYER_FENTER();
13583         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13584
13585         if (MMPLAYER_CURRENT_STATE(player) !=  MM_PLAYER_STATE_NULL)
13586                 LOGW("buffer_ms will not be applied.");
13587
13588
13589         LOGD("set buffering time %d ms / %d ms", buffer_ms, rebuffer_ms);
13590
13591         if (player->streamer == NULL) {
13592                 player->streamer = __mm_player_streaming_create();
13593                 __mm_player_streaming_initialize(player->streamer);
13594         }
13595
13596         if (buffer_ms >= 0)
13597                 player->streamer->buffering_req.prebuffer_time = buffer_ms;
13598
13599         if (rebuffer_ms >= 0)
13600                 player->streamer->buffering_req.rebuffer_time = rebuffer_ms;
13601
13602         MMPLAYER_FLEAVE();
13603         return ret;
13604
13605 }
13606
13607 int _mmplayer_get_streaming_buffering_time(MMHandleType hplayer, int *buffer_ms, int *rebuffer_ms)
13608 {
13609         int ret = MM_ERROR_NONE;
13610         mm_player_t* player = (mm_player_t*) hplayer;
13611
13612         MMPLAYER_FENTER();
13613         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13614         MMPLAYER_RETURN_VAL_IF_FAIL(buffer_ms && rebuffer_ms, MM_ERROR_COMMON_INVALID_ARGUMENT);
13615
13616         if (player->streamer == NULL) {
13617                 player->streamer = __mm_player_streaming_create();
13618                 __mm_player_streaming_initialize(player->streamer);
13619         }
13620
13621         *buffer_ms = player->streamer->buffering_req.prebuffer_time;
13622         *rebuffer_ms = player->streamer->buffering_req.rebuffer_time;
13623
13624         LOGD("buffering time %d ms / %d ms", *buffer_ms, *rebuffer_ms);
13625
13626         MMPLAYER_FLEAVE();
13627         return ret;
13628 }
13629
13630 int _mmplayer_set_codec_type(MMHandleType hplayer, MMPlayerStreamType stream_type, MMPlayerVideoCodecType codec_type)
13631 {
13632 #define IDX_FIRST_SW_CODEC 0
13633         mm_player_t* player = (mm_player_t*) hplayer;
13634         const char* attr_name = (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO) ? (MM_PLAYER_AUDIO_CODEC_TYPE) : (MM_PLAYER_VIDEO_CODEC_TYPE);
13635         MMHandleType attrs = 0;
13636
13637         MMPLAYER_FENTER();
13638         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13639
13640         LOGD("ini setting : [a][h:%s][s:%s] / [v][h:%s][s:%s]",
13641                 player->ini.audiocodec_element_hw, player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC],
13642                 player->ini.videocodec_element_hw, player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC]);
13643
13644         switch (stream_type) {
13645         case MM_PLAYER_STREAM_TYPE_AUDIO:
13646                 if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
13647                          (!strcmp(player->ini.audiocodec_element_hw, ""))) ||
13648                         ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
13649                          (!strcmp(player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
13650                         LOGE("There is no a codec for codec_type %d", codec_type);
13651                         return MM_ERROR_PLAYER_NO_OP;
13652                 }
13653         break;
13654         case MM_PLAYER_STREAM_TYPE_VIDEO:
13655                 if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
13656                          (!strcmp(player->ini.videocodec_element_hw, ""))) ||
13657                         ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
13658                          (!strcmp(player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
13659                         LOGE("There is no v codec for codec_type %d", codec_type);
13660                         return MM_ERROR_PLAYER_NO_OP;
13661                 }
13662
13663         break;
13664         default:
13665                 LOGE("Invalid stream type %d", stream_type);
13666                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
13667         break;
13668         }
13669
13670         LOGD("update %s codec_type to %d", attr_name, codec_type);
13671
13672         attrs = MMPLAYER_GET_ATTRS(player);
13673         mm_attrs_set_int_by_name(attrs, attr_name, codec_type);
13674
13675         if (mmf_attrs_commit(player->attrs)) {
13676                 LOGE("failed to commit codec_type attributes");
13677                 return MM_ERROR_PLAYER_INTERNAL;
13678         }
13679
13680         MMPLAYER_FLEAVE();
13681         return MM_ERROR_NONE;
13682 }
13683
13684 int
13685 _mmplayer_set_replaygain_enabled(MMHandleType hplayer, bool enabled)
13686 {
13687         mm_player_t* player = (mm_player_t*) hplayer;
13688         GstElement* rg_vol_element = NULL;
13689
13690         MMPLAYER_FENTER();
13691
13692         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13693
13694         player->sound.rg_enable = enabled;
13695
13696         /* just hold rgvolume enable value if pipeline is not ready */
13697         if (!player->pipeline || !player->pipeline->audiobin) {
13698                 LOGD("pipeline is not ready. holding rgvolume enable value\n");
13699                 return MM_ERROR_NONE;
13700         }
13701
13702         rg_vol_element = player->pipeline->audiobin[MMPLAYER_A_RGVOL].gst;
13703
13704         if (!rg_vol_element) {
13705                 LOGD("rgvolume element is not created");
13706                 return MM_ERROR_PLAYER_INTERNAL;
13707         }
13708
13709         if (enabled)
13710                 g_object_set(rg_vol_element, "enable-rgvolume", TRUE, NULL);
13711         else
13712                 g_object_set(rg_vol_element, "enable-rgvolume", FALSE, NULL);
13713
13714         MMPLAYER_FLEAVE();
13715
13716         return MM_ERROR_NONE;
13717 }
13718
13719 int
13720 _mmplayer_is_replaygain_enabled(MMHandleType hplayer, bool *enabled)
13721 {
13722         mm_player_t* player = (mm_player_t*) hplayer;
13723         GstElement* rg_vol_element = NULL;
13724         gboolean enable = FALSE;
13725
13726         MMPLAYER_FENTER();
13727
13728         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13729         MMPLAYER_RETURN_VAL_IF_FAIL(enabled, MM_ERROR_INVALID_ARGUMENT);
13730
13731         /* just hold enable_rg value if pipeline is not ready */
13732         if (!player->pipeline || !player->pipeline->audiobin) {
13733                 LOGD("pipeline is not ready. holding rgvolume value (%d)\n", player->sound.rg_enable);
13734                 *enabled = player->sound.rg_enable;
13735                 return MM_ERROR_NONE;
13736         }
13737
13738         rg_vol_element = player->pipeline->audiobin[MMPLAYER_A_RGVOL].gst;
13739
13740         if (!rg_vol_element) {
13741                 LOGD("rgvolume element is not created");
13742                 return MM_ERROR_PLAYER_INTERNAL;
13743         }
13744
13745         g_object_get(rg_vol_element, "enable-rgvolume", &enable, NULL);
13746         *enabled = enable;
13747
13748         MMPLAYER_FLEAVE();
13749
13750         return MM_ERROR_NONE;
13751 }