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