remove unused #define from private file
[platform/core/multimedia/libmm-player.git] / src / server / 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 #ifdef HAVE_WAYLAND
33 #include <gst/wayland/wayland.h>
34 #endif
35 #include <gst/audio/gstaudiobasesink.h>
36 #include <unistd.h>
37 #include <sys/stat.h>
38 #include <string.h>
39 #include <sys/time.h>
40 #include <stdlib.h>
41
42 #include <mm_error.h>
43 #include <mm_attrs.h>
44 #include <mm_attrs_private.h>
45 #include <mm_debug.h>
46 #include <mm_sound.h>
47 #include <mm_sound_focus.h>
48
49 #include "mm_player_priv.h"
50 #include "mm_player_ini.h"
51 #include "mm_player_attrs.h"
52 #include "mm_player_capture.h"
53 #include "mm_player_utils.h"
54 #include "mm_player_tracks.h"
55
56 /*===========================================================================================
57 |                                                                                                                                                                                       |
58 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
59 |                                                                                                                                                                                       |
60 ========================================================================================== */
61
62 /*---------------------------------------------------------------------------
63 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
64 ---------------------------------------------------------------------------*/
65
66 /*---------------------------------------------------------------------------
67 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
68 ---------------------------------------------------------------------------*/
69
70 /*---------------------------------------------------------------------------
71 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
72 ---------------------------------------------------------------------------*/
73
74 /*---------------------------------------------------------------------------
75 |    LOCAL #defines:                                                                                                            |
76 ---------------------------------------------------------------------------*/
77 #define TRICK_PLAY_MUTE_THRESHOLD_MAX   2.0
78 #define TRICK_PLAY_MUTE_THRESHOLD_MIN   0.0
79
80 #define MM_VOLUME_FACTOR_DEFAULT                1.0
81 #define MM_VOLUME_FACTOR_MIN                    0
82 #define MM_VOLUME_FACTOR_MAX                    1.0
83
84 #define MM_PLAYER_FADEOUT_TIME_DEFAULT  700000 // 700 msec
85
86 #define MM_PLAYER_MPEG_VNAME                    "mpegversion"
87 #define MM_PLAYER_DIVX_VNAME                    "divxversion"
88 #define MM_PLAYER_WMV_VNAME                             "wmvversion"
89 #define MM_PLAYER_WMA_VNAME                             "wmaversion"
90
91 #define DEFAULT_PLAYBACK_RATE                   1.0
92 #define PLAYBACK_RATE_EX_AUDIO_MIN              0.5
93 #define PLAYBACK_RATE_EX_AUDIO_MAX              2.0
94 #define PLAYBACK_RATE_EX_VIDEO_MIN              0.5
95 #define PLAYBACK_RATE_EX_VIDEO_MAX              1.5
96
97 #define GST_QUEUE_DEFAULT_TIME                  4
98 #define GST_QUEUE_HLS_TIME                              8
99
100 #define MMPLAYER_USE_FILE_FOR_BUFFERING(player) (((player)->profile.uri_type != MM_PLAYER_URI_TYPE_HLS) && (player->ini.http_file_buffer_path) && (strlen(player->ini.http_file_buffer_path) > 0) )
101 #define MM_PLAYER_NAME  "mmplayer"
102
103 /*---------------------------------------------------------------------------
104 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
105 ---------------------------------------------------------------------------*/
106
107 /*---------------------------------------------------------------------------
108 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
109 ---------------------------------------------------------------------------*/
110
111 /*---------------------------------------------------------------------------
112 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
113 ---------------------------------------------------------------------------*/
114
115 /*---------------------------------------------------------------------------
116 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
117 ---------------------------------------------------------------------------*/
118
119 /*---------------------------------------------------------------------------
120 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
121 ---------------------------------------------------------------------------*/
122 static int              __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
123 static int              __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
124 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player);
125 static int              __mmplayer_gst_create_subtitle_src(mm_player_t* player);
126 static int              __mmplayer_gst_create_pipeline(mm_player_t* player);
127 static int              __mmplayer_gst_destroy_pipeline(mm_player_t* player);
128 static int              __mmplayer_gst_element_link_bucket(GList* element_bucket);
129
130 static GstPadProbeReturn        __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data);
131 static void             __mmplayer_gst_decode_pad_added(GstElement* elem, GstPad* pad, gpointer data);
132 static void             __mmplayer_gst_decode_no_more_pads(GstElement* elem, gpointer data);
133 static void             __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gpointer data);
134 static void             __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad, GstCaps *caps, gpointer data);
135 static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
136 static gint             __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad, GstCaps * caps, GstElementFactory* factory, gpointer data);
137 //static GValueArray* __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
138 static void __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad, gpointer data);
139 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
140 static void     __mmplayer_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
141 static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
142 static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
143
144 static void     __mmplayer_typefind_have_type(  GstElement *tf, guint probability, GstCaps *caps, gpointer data);
145 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
146 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
147 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
148 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
149 static void     __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
150 //static void   __mmplayer_check_video_zero_cpoy(mm_player_t* player, GstElementFactory* factory);
151
152 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
153 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
154 static void             __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
155
156 static void             __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data);
157 //static void    __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
158 static void             __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
159 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player );
160 static gboolean __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
161
162
163 static void             __mmplayer_init_factories(mm_player_t* player);
164 static void             __mmplayer_release_factories(mm_player_t* player);
165 static void             __mmplayer_release_misc(mm_player_t* player);
166 static void             __mmplayer_release_misc_post(mm_player_t* player);
167 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
168 static GstBusSyncReply __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data);
169 static gboolean __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data);
170
171 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
172 static gboolean      __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
173
174 int             __mmplayer_switch_audio_sink (mm_player_t* player);
175 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
176 static GstPadProbeReturn __mmplayer_audio_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
177 static GstPadProbeReturn __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
178 static GstPadProbeReturn __mmplayer_subtitle_adjust_position_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
179 static int __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index);
180
181 static gboolean __mmplayer_check_subtitle( mm_player_t* player );
182 static gboolean __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message );
183 static void             __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms );
184 static void             __mmplayer_cancel_eos_timer( mm_player_t* player );
185 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
186 static gboolean __mmplayer_link_decoder( mm_player_t* player,GstPad *srcpad);
187 static gboolean __mmplayer_link_sink( mm_player_t* player,GstPad *srcpad);
188 static int              __mmplayer_handle_missed_plugin(mm_player_t* player);
189 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
190 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
191 static void             __mmplayer_add_sink( mm_player_t* player, GstElement* sink);
192 static void             __mmplayer_del_sink( mm_player_t* player, GstElement* sink);
193 static void             __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
194 static gpointer __mmplayer_next_play_thread(gpointer data);
195 static gpointer __mmplayer_repeat_thread(gpointer data);
196 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
197
198
199 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
200 static GstPadProbeReturn __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data);
201 static void __mmplayer_release_dump_list (GList *dump_list);
202
203 static int              __gst_realize(mm_player_t* player);
204 static int              __gst_unrealize(mm_player_t* player);
205 static int              __gst_start(mm_player_t* player);
206 static int              __gst_stop(mm_player_t* player);
207 static int              __gst_pause(mm_player_t* player, gboolean async);
208 static int              __gst_resume(mm_player_t* player, gboolean async);
209 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
210                                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
211                                         gint64 cur, GstSeekType stop_type, gint64 stop );
212 static int __gst_pending_seek ( mm_player_t* player );
213
214 static int              __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called);
215 static int              __gst_get_position(mm_player_t* player, int format, unsigned long *position);
216 static int              __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
217 static int              __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
218 static int              __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
219
220 static gboolean __gst_send_event_to_sink( mm_player_t* player, GstEvent* event );
221
222 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
223 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
224
225 /*fadeout */
226 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
227 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
228
229 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
230 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
231
232 /* util */
233 static gboolean __is_es_buff_src(mm_player_t* player);
234 static gboolean __has_suffix(mm_player_t * player, const gchar * suffix);
235
236 static int  __mmplayer_realize_streaming_ext(mm_player_t* player);
237 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
238 static int __mmplayer_start_streaming_ext(mm_player_t *player);
239 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
240 static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
241
242 static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
243 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
244 static void __mmplayer_check_pipeline(mm_player_t* player);
245 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
246 static void __mmplayer_deactivate_old_path(mm_player_t *player);
247 #if 0 // We'll need this in future.
248 static int __mmplayer_gst_switching_element(mm_player_t *player, GstElement *search_from, const gchar *removal_name, const gchar *new_element_name);
249 #endif
250
251 static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg);
252 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
253 static gboolean __mmplayer_can_do_interrupt(mm_player_t *player);
254
255 /* device change post proc */
256 void __mmplayer_device_change_post_process(gpointer user);
257 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score);
258 void __mmplayer_inc_cb_score(mm_player_t* player);
259 void __mmplayer_post_proc_reset(mm_player_t* player);
260 void __mmplayer_device_change_trigger_post_process(mm_player_t* player);
261 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
262 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name);
263 static void             __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data);
264 static void             __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data);
265 static void     __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data);
266 static void             __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data);
267 static void             __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data);
268 static gboolean __gst_seek_audio_data (GstElement * appsrc, guint64 position, gpointer user_data);
269 static gboolean __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data);
270 static gboolean __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data);
271 /*===========================================================================================
272 |                                                                                                                                                                                       |
273 |  FUNCTION DEFINITIONS                                                                                                                                         |
274 |                                                                                                                                                                                       |
275 ========================================================================================== */
276
277 #if 0 //debug
278 static void
279 print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
280 {
281   gint i, count;
282
283   count = gst_tag_list_get_tag_size (list, tag);
284
285   debug_log("count = %d", count);
286
287   for (i = 0; i < count; i++) {
288     gchar *str;
289
290     if (gst_tag_get_type (tag) == G_TYPE_STRING) {
291       if (!gst_tag_list_get_string_index (list, tag, i, &str))
292         g_assert_not_reached ();
293     } else {
294       str =
295           g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
296     }
297
298     if (i == 0) {
299       g_print ("  %15s: %s\n", gst_tag_get_nick (tag), str);
300     } else {
301       g_print ("                 : %s\n", str);
302     }
303
304     g_free (str);
305   }
306 }
307 #endif
308
309 static void
310 __mmplayer_videostream_cb(GstElement *element, void *data,
311 int width, int height, gpointer user_data) // @
312 {
313         mm_player_t* player = (mm_player_t*)user_data;
314
315         return_if_fail ( player );
316
317         MMPLAYER_FENTER();
318
319         if (player->is_drm_file)
320         {
321                 MMMessageParamType msg_param = { 0, };
322                 debug_warning("not supported in drm file");
323                 msg_param.code = MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
324                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
325         }
326         else if ( !player->set_mode.media_packet_video_stream && player->video_stream_cb)
327         {
328                 MMPlayerVideoStreamDataType stream;
329
330                 /* clear stream data structure */
331                 memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
332
333                 stream.data[0] = data;
334                 stream.length_total = width * height * 4; // for rgb 32bit
335                 stream.height = height;
336                 stream.width = width;
337                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
338         }
339
340         MMPLAYER_FLEAVE();
341 }
342
343 static void
344 __mmplayer_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer data)
345 {
346         mm_player_t* player = (mm_player_t*)data;
347
348         return_if_fail ( player );
349
350         MMPLAYER_FENTER();
351
352         if (player->video_frame_render_error_cb )
353         {
354                 if (player->attrs)
355                 {
356                         int surface_type = 0;
357                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
358                         switch (surface_type)
359                         {
360                         case MM_DISPLAY_SURFACE_X_EXT:
361                                 player->video_frame_render_error_cb((unsigned int*)error_id, player->video_frame_render_error_cb_user_param);
362                                 debug_log("display surface type(X_EXT) : render error callback(%p) is finished", player->video_frame_render_error_cb);
363                                 break;
364                         default:
365                                 debug_error("video_frame_render_error_cb was set, but this surface type(%d) is not supported", surface_type);
366                                 break;
367                         }
368                 }
369                 else
370                 {
371                         debug_error("could not get surface type");
372                 }
373         }
374         else
375         {
376                 debug_warning("video_frame_render_error_cb was not set");
377         }
378
379         MMPLAYER_FLEAVE();
380 }
381
382 void
383 __mmplayer_device_change_post_process(gpointer user)
384 {
385         mm_player_t* player = (mm_player_t*)user;
386         unsigned long position = 0;
387         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
388         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
389
390         MMPLAYER_FENTER();
391
392         if (! player ||
393                 ! player->pipeline ||
394                 ! player->pipeline->mainbin ||
395                 ! player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
396         {
397                 goto EXIT;
398         }
399
400         current_state = MMPLAYER_CURRENT_STATE(player);
401         pending_state = MMPLAYER_PENDING_STATE(player);
402
403         if (player->post_proc.need_pause_and_resume)
404         {
405                 debug_log("pausing");
406                 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
407                         ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
408                         gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED);
409         }
410
411         /* seek should be done within pause and resume */
412         if (player->post_proc.need_seek)
413         {
414                 debug_log("seeking");
415                 __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position);
416                 debug_log(">> seek to current position = %ld ms", position);
417                 __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE);
418         }
419
420         if (player->post_proc.need_pause_and_resume)
421         {
422                 debug_log("resuming");
423                 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
424                         ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
425                         gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING);
426         }
427
428         /* async */
429         if (player->post_proc.need_async)
430         {
431                 debug_log("setting async");
432
433                 /* TODO : need some comment here */
434                 if (player->pipeline->textbin && player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst)
435                         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
436         }
437
438 EXIT:
439         /* reset all */
440         __mmplayer_post_proc_reset(player);
441         return;
442 }
443
444 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score)
445 {
446         return_if_fail(player);
447         player->post_proc.required_cb_score = score;
448         debug_log("set required score to : %d", score);
449 }
450
451 void __mmplayer_inc_cb_score(mm_player_t* player)
452 {
453         return_if_fail(player);
454         player->post_proc.cb_score++;
455         debug_log("post proc cb score increased to %d", player->post_proc.cb_score);
456 }
457
458 void __mmplayer_post_proc_reset(mm_player_t* player)
459 {
460         return_if_fail(player);
461
462         /* check if already triggered */
463         if (player->post_proc.id)
464         {
465                 /* TODO : need to consider multiple main context. !!!! */
466                 if (FALSE == g_source_remove(player->post_proc.id) )
467                 {
468                         debug_error("failed to remove exist post_proc item");
469                 }
470                 player->post_proc.id = 0;
471         }
472
473         memset(&player->post_proc, 0, sizeof(mm_player_post_proc_t));
474
475         /* set default required cb score 1 as only audio device has changed in this case.
476            if display status is changed with audio device, required cb score is set 2 in display status callback.
477            this logic bases on the assumption which audio device callback is called after calling display status callback. */
478         player->post_proc.required_cb_score = 1;
479 }
480
481 void
482 __mmplayer_device_change_trigger_post_process(mm_player_t* player)
483 {
484         return_if_fail(player);
485
486         /* check score */
487         if ( player->post_proc.cb_score < player->post_proc.required_cb_score )
488         {
489                 /* wait for next turn */
490                 debug_log("wait for next turn. required cb score : %d   current score : %d\n",
491                         player->post_proc.required_cb_score, player->post_proc.cb_score);
492                 return;
493         }
494
495         /* check if already triggered */
496         if (player->post_proc.id)
497         {
498                 /* TODO : need to consider multiple main context. !!!! */
499                 if (FALSE == g_source_remove(player->post_proc.id) )
500                 {
501                         debug_error("failed to remove exist post_proc item");
502                 }
503                 player->post_proc.id = 0;
504         }
505
506         player->post_proc.id = g_idle_add((GSourceFunc)__mmplayer_device_change_post_process, (gpointer)player);
507 }
508 #if 0
509 /* NOTE : Sound module has different latency according to output device So,
510  * synchronization problem can be happened whenever device is changed.
511  * To avoid this issue, we do reset avsystem or seek as workaroud.
512  */
513 static void
514 __mmplayer_sound_device_info_changed_cb_func (MMSoundDevice_t device_h, int changed_info_type, void *user_data)
515 {
516     int ret;
517     mm_sound_device_type_e device_type;
518         mm_player_t* player = (mm_player_t*) user_data;
519
520         return_if_fail( player );
521
522         debug_warning("device_info_changed_cb is called, device_h[0x%x], changed_info_type[%d]\n", device_h, changed_info_type);
523
524         __mmplayer_inc_cb_score(player);
525
526         /* get device type with device_h*/
527         ret = mm_sound_get_device_type(device_h, &device_type);
528         if (ret) {
529                 debug_error("failed to mm_sound_get_device_type()\n");
530         }
531
532         /* do pause and resume only if video is playing  */
533         if ( player->videodec_linked && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING )
534         {
535                 switch (device_type)
536                 {
537                         case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
538                         case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
539                         case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
540                         case MM_SOUND_DEVICE_TYPE_HDMI:
541                         case MM_SOUND_DEVICE_TYPE_MIRRORING:
542                         {
543                                 player->post_proc.need_pause_and_resume = TRUE;
544                         }
545                         break;
546
547                         default:
548                                 debug_log("do nothing");
549                 }
550         }
551         debug_warning("dispatched");
552
553         __mmplayer_device_change_trigger_post_process(player);
554 }
555 #endif
556 /* This function should be called after the pipeline goes PAUSED or higher
557 state. */
558 gboolean
559 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
560 {
561         static gboolean has_duration = FALSE;
562         static gboolean has_video_attrs = FALSE;
563         static gboolean has_audio_attrs = FALSE;
564         static gboolean has_bitrate = FALSE;
565         gboolean missing_only = FALSE;
566         gboolean all = FALSE;
567         gint64 dur_nsec = 0;
568         GstStructure* p = NULL;
569         MMHandleType attrs = 0;
570         gchar *path = NULL;
571         gint stream_service_type = STREAMING_SERVICE_NONE;
572         struct stat sb;
573
574         MMPLAYER_FENTER();
575
576         return_val_if_fail ( player, FALSE );
577
578         /* check player state here */
579         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
580                 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING )
581         {
582                 /* give warning now only */
583                 debug_warning("be careful. content attributes may not available in this state ");
584         }
585
586         /* get content attribute first */
587         attrs = MMPLAYER_GET_ATTRS(player);
588         if ( !attrs )
589         {
590                 debug_error("cannot get content attribute");
591                 return FALSE;
592         }
593
594         /* get update flag */
595
596         if ( flag & ATTR_MISSING_ONLY )
597         {
598                 missing_only = TRUE;
599                 debug_log("updating missed attr only");
600         }
601
602         if ( flag & ATTR_ALL )
603         {
604                 all = TRUE;
605                 has_duration = FALSE;
606                 has_video_attrs = FALSE;
607                 has_audio_attrs = FALSE;
608                 has_bitrate = FALSE;
609
610                 debug_log("updating all attrs");
611         }
612
613         if ( missing_only && all )
614         {
615                 debug_warning("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
616                 missing_only = FALSE;
617         }
618
619         if (  (flag & ATTR_DURATION) || (!has_duration && missing_only) || all )
620         {
621                 debug_log("try to update duration");
622                 has_duration = FALSE;
623
624                 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
625                 {
626                         player->duration = dur_nsec;
627                         debug_warning("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
628                 }
629
630                 /* try to get streaming service type */
631                 stream_service_type = __mmplayer_get_stream_service_type( player );
632                 mm_attrs_set_int_by_name ( attrs, "streaming_type", stream_service_type );
633
634                 /* check duration is OK */
635                 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
636                 {
637                         /* FIXIT : find another way to get duration here. */
638                         debug_error("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
639                 }
640                 else
641                 {
642                         /*update duration */
643                         mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
644                         has_duration = TRUE;
645                 }
646         }
647
648         if (  (flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all )
649         {
650                 /* update audio params
651                 NOTE : We need original audio params and it can be only obtained from src pad of audio
652                 decoder. Below code only valid when we are not using 'resampler' just before
653                 'audioconverter'. */
654
655                 debug_log("try to update audio attrs");
656                 has_audio_attrs = FALSE;
657
658                 if ( player->pipeline->audiobin &&
659                          player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
660                 {
661                         GstCaps *caps_a = NULL;
662                         GstPad* pad = NULL;
663                         gint samplerate = 0, channels = 0;
664
665                         pad = gst_element_get_static_pad(
666                                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
667
668                         if ( pad )
669                         {
670                                 caps_a = gst_pad_get_current_caps( pad );
671
672                                 if ( caps_a )
673                                 {
674                                         p = gst_caps_get_structure (caps_a, 0);
675
676                                         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
677
678                                         gst_structure_get_int (p, "rate", &samplerate);
679                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
680
681                                         gst_structure_get_int (p, "channels", &channels);
682                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
683
684                                         secure_debug_log("samplerate : %d       channels : %d", samplerate, channels);
685
686                                         gst_caps_unref( caps_a );
687                                         caps_a = NULL;
688
689                                         has_audio_attrs = TRUE;
690                                 }
691                                 else
692                                 {
693                                         debug_warning("not ready to get audio caps");
694                                 }
695
696                                 gst_object_unref( pad );
697                         }
698                         else
699                         {
700                                 debug_warning("failed to get pad from audiosink");
701                         }
702                 }
703         }
704
705         if ( (flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all )
706         {
707                 debug_log("try to update video attrs");
708                 has_video_attrs = FALSE;
709
710                 if ( player->pipeline->videobin &&
711                          player->pipeline->videobin[MMPLAYER_V_SINK].gst )
712                 {
713                         GstCaps *caps_v = NULL;
714                         GstPad* pad = NULL;
715                         gint tmpNu, tmpDe;
716                         gint width, height;
717
718                         pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
719                         if ( pad )
720                         {
721                                 caps_v = gst_pad_get_current_caps( pad );
722
723                                 /* Use v_stream_caps, if fail to get video_sink sink pad*/
724                                 if (!caps_v && player->v_stream_caps)
725                                 {
726                                         caps_v = player->v_stream_caps;
727                                         gst_caps_ref(caps_v);
728                                 }
729
730                                 if (caps_v)
731                                 {
732                                         p = gst_caps_get_structure (caps_v, 0);
733                                         gst_structure_get_int (p, "width", &width);
734                                         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
735
736                                         gst_structure_get_int (p, "height", &height);
737                                         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
738
739                                         gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
740
741                                         secure_debug_log("width : %d     height : %d", width, height );
742
743                                         gst_caps_unref( caps_v );
744                                         caps_v = NULL;
745
746                                         if (tmpDe > 0)
747                                         {
748                                                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
749                                                 secure_debug_log("fps : %d", tmpNu / tmpDe);
750                                         }
751
752                                         has_video_attrs = TRUE;
753                                 }
754                                 else
755                                 {
756                                         debug_log("no negitiated caps from videosink");
757                                 }
758                                 gst_object_unref( pad );
759                                 pad = NULL;
760                         }
761                         else
762                         {
763                                 debug_log("no videosink sink pad");
764                         }
765                 }
766         }
767
768
769         if ( (flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all )
770         {
771                 has_bitrate = FALSE;
772
773                 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
774                 if (player->duration)
775                 {
776                         guint64 data_size = 0;
777
778                         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
779                         {
780                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
781
782                                 if (stat(path, &sb) == 0)
783                                 {
784                                         data_size = (guint64)sb.st_size;
785                                 }
786                         }
787                         else if (MMPLAYER_IS_HTTP_STREAMING(player))
788                         {
789                                 data_size = player->http_content_size;
790                         }
791                         debug_log("try to update bitrate : data_size = %lld", data_size);
792
793                         if (data_size)
794                         {
795                                 guint64 bitrate = 0;
796                                 guint64 msec_dur = 0;
797
798                                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
799                                 bitrate = data_size * 8 * 1000 / msec_dur;
800                                 secure_debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
801                                 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
802
803                                 has_bitrate = TRUE;
804                         }
805
806                         if (MMPLAYER_IS_RTSP_STREAMING(player))
807                         {
808                                 if(player->total_bitrate)
809                                 {
810                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
811                                         has_bitrate = TRUE;
812                                 }
813                         }
814                 }
815         }
816
817         /* validate all */
818         if (  mmf_attrs_commit ( attrs ) )
819         {
820                 debug_error("failed to update attributes\n");
821                 return FALSE;
822         }
823
824         MMPLAYER_FLEAVE();
825
826         return TRUE;
827 }
828
829 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player )
830 {
831         gint streaming_type = STREAMING_SERVICE_NONE;
832
833         MMPLAYER_FENTER();
834
835         return_val_if_fail ( player &&
836                         player->pipeline &&
837                         player->pipeline->mainbin &&
838                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
839                         FALSE );
840
841         /* streaming service type if streaming */
842         if ( ! MMPLAYER_IS_STREAMING(player) )
843                 return STREAMING_SERVICE_NONE;
844
845         if (MMPLAYER_IS_HTTP_STREAMING(player))
846         {
847                 streaming_type = (player->duration == 0) ?
848                         STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
849         }
850
851         switch ( streaming_type )
852         {
853                 case STREAMING_SERVICE_LIVE:
854                         debug_log("it's live streaming");
855                 break;
856                 case STREAMING_SERVICE_VOD:
857                         debug_log("it's vod streaming");
858                 break;
859                 case STREAMING_SERVICE_NONE:
860                         debug_error("should not get here");
861                 break;
862                 default:
863                         debug_error("should not get here");
864         }
865
866         player->streaming_type = streaming_type;
867         MMPLAYER_FLEAVE();
868
869         return streaming_type;
870 }
871
872
873 /* this function sets the player state and also report
874  * it to applicaton by calling callback function
875  */
876 int
877 __mmplayer_set_state(mm_player_t* player, int state) // @
878 {
879         MMMessageParamType msg = {0, };
880         int sound_result = MM_ERROR_NONE;
881         gboolean post_bos = FALSE;
882         gboolean interrupted_by_asm = FALSE;
883         int ret = MM_ERROR_NONE;
884
885         return_val_if_fail ( player, FALSE );
886
887         if ( MMPLAYER_CURRENT_STATE(player) == state )
888         {
889                 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
890                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
891                 return ret;
892         }
893
894         /* update player states */
895         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
896         MMPLAYER_CURRENT_STATE(player) = state;
897
898         /* FIXIT : it's better to do like below code
899         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player) )
900                         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
901         and add more code to handling PENDING_STATE.
902         */
903         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
904                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
905
906         /* print state */
907         MMPLAYER_PRINT_STATE(player);
908
909         /* do some FSM stuffs before posting new state to application  */
910         interrupted_by_asm = player->sound_focus.by_asm_cb;
911
912         switch ( MMPLAYER_CURRENT_STATE(player) )
913         {
914                 case MM_PLAYER_STATE_NULL:
915                 case MM_PLAYER_STATE_READY:
916                 {
917                         if (player->cmd == MMPLAYER_COMMAND_STOP)
918                         {
919                                 sound_result = _mmplayer_sound_release_focus(&player->sound_focus);
920                                 if ( sound_result != MM_ERROR_NONE )
921                                 {
922                                         debug_error("failed to release sound focus\n");
923                                         return MM_ERROR_POLICY_INTERNAL;
924                                 }
925                         }
926                 }
927                 break;
928
929                 case MM_PLAYER_STATE_PAUSED:
930                 {
931                          if ( ! player->sent_bos )
932                          {
933                                 int found = 0;
934                                 #define MMPLAYER_MAX_SOUND_PRIORITY     3
935
936                                 /* it's first time to update all content attrs. */
937                                 _mmplayer_update_content_attrs( player, ATTR_ALL );
938                                 /* set max sound priority to keep own sound and not to mute other's one */
939                                 mm_attrs_get_int_by_name(player->attrs, "content_video_found", &found);
940                                 if (found)
941                                 {
942                                         mm_attrs_get_int_by_name(player->attrs, "content_audio_found", &found);
943                                         if (found)
944                                         {
945                                                 debug_log("set max audio priority");
946                                                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "priority", MMPLAYER_MAX_SOUND_PRIORITY, NULL);
947                                         }
948                                 }
949
950                          }
951
952                         /* add audio callback probe if condition is satisfied */
953                         if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
954                         {
955                                 __mmplayer_configure_audio_callback(player);
956                                 /* FIXIT : handle return value */
957                         }
958
959                         if (!MMPLAYER_IS_STREAMING(player) || (player->streamer && !player->streamer->is_buffering))
960                         {
961                                 sound_result = _mmplayer_sound_release_focus(&player->sound_focus);
962                                 if ( sound_result != MM_ERROR_NONE )
963                                 {
964                                         debug_error("failed to release sound focus\n");
965                                         return MM_ERROR_POLICY_INTERNAL;
966                                 }
967                         }
968                 }
969                 break;
970
971                 case MM_PLAYER_STATE_PLAYING:
972                 {
973                         /* try to get content metadata */
974                         if ( ! player->sent_bos )
975                         {
976                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
977                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
978                                  * legacy mmfw-player api */
979                                 _mmplayer_update_content_attrs( player, ATTR_MISSING_ONLY);
980                         }
981
982                         if ( (player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME) )
983                         {
984                                 if (!player->sent_bos)
985                                 {
986                                         __mmplayer_handle_missed_plugin ( player );
987                                 }
988                                 sound_result = _mmplayer_sound_acquire_focus(&player->sound_focus);
989                                 if (sound_result != MM_ERROR_NONE)
990                                 {
991                                         // FIXME : need to check history
992                                         if (player->pipeline->videobin)
993                                         {
994                                                 MMMessageParamType msg = {0, };
995
996                                                 debug_error("failed to go ahead because of video conflict\n");
997
998                                                 msg.union_type = MM_MSG_UNION_CODE;
999                                                 msg.code = MM_ERROR_POLICY_INTERRUPTED;
1000                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
1001
1002                                                 _mmplayer_unrealize((MMHandleType)player);
1003                                         }
1004                                         else
1005                                         {
1006                                                 debug_error("failed to play by sound focus error : 0x%X\n", sound_result);
1007                                                 _mmplayer_pause((MMHandleType)player);
1008                                                 return sound_result;
1009                                         }
1010
1011                                         return MM_ERROR_POLICY_INTERNAL;
1012                                 }
1013                         }
1014
1015                         if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
1016                         {
1017                                 /* initialize because auto resume is done well. */
1018                                 player->resumed_by_rewind = FALSE;
1019                                 player->playback_rate = 1.0;
1020                         }
1021
1022                         if ( !player->sent_bos )
1023                         {
1024                                 /* check audio codec field is set or not
1025                                  * we can get it from typefinder or codec's caps.
1026                                  */
1027                                 gchar *audio_codec = NULL;
1028                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
1029
1030                                 /* The codec format can't be sent for audio only case like amr, mid etc.
1031                                  * Because, parser don't make related TAG.
1032                                  * So, if it's not set yet, fill it with found data.
1033                                  */
1034                                 if ( ! audio_codec )
1035                                 {
1036                                         if ( g_strrstr(player->type, "audio/midi"))
1037                                         {
1038                                                 audio_codec = g_strdup("MIDI");
1039
1040                                         }
1041                                         else if ( g_strrstr(player->type, "audio/x-amr"))
1042                                         {
1043                                                 audio_codec = g_strdup("AMR");
1044                                         }
1045                                         else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
1046                                         {
1047                                                 audio_codec = g_strdup("AAC");
1048                                         }
1049                                         else
1050                                         {
1051                                                 audio_codec = g_strdup("unknown");
1052                                         }
1053                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1054
1055                                         MMPLAYER_FREEIF(audio_codec);
1056                                         mmf_attrs_commit(player->attrs);
1057                                         debug_log("set audio codec type with caps\n");
1058                                 }
1059
1060                                 post_bos = TRUE;
1061                         }
1062                 }
1063                 break;
1064
1065                 case MM_PLAYER_STATE_NONE:
1066                 default:
1067                         debug_warning("invalid target state, there is nothing to do.\n");
1068                         break;
1069         }
1070
1071
1072         /* post message to application */
1073         if (MMPLAYER_TARGET_STATE(player) == state)
1074         {
1075                 /* fill the message with state of player */
1076                 msg.state.previous = MMPLAYER_PREV_STATE(player);
1077                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
1078
1079                 debug_log ("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
1080
1081                 /* state changed by asm callback */
1082                 if ( interrupted_by_asm )
1083                 {
1084                         msg.union_type = MM_MSG_UNION_CODE;
1085                         msg.code = player->sound_focus.focus_changed_msg;       /* FIXME: player.c convert function have to be modified. */
1086                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
1087                 }
1088                 /* state changed by usecase */
1089                 else
1090                 {
1091                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
1092                 }
1093         }
1094         else
1095         {
1096                 debug_log ("intermediate state, do nothing.\n");
1097                 MMPLAYER_PRINT_STATE(player);
1098                 return ret;
1099         }
1100
1101         if ( post_bos )
1102         {
1103                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
1104                 player->sent_bos = TRUE;
1105         }
1106
1107         return ret;
1108 }
1109
1110 static gpointer __mmplayer_next_play_thread(gpointer data)
1111 {
1112         mm_player_t* player = (mm_player_t*) data;
1113         MMPlayerGstElement *mainbin = NULL;
1114
1115         return_val_if_fail ( player, NULL );
1116
1117         g_mutex_lock(&player->next_play_thread_mutex);
1118         while ( ! player->next_play_thread_exit )
1119         {
1120                 debug_log("next play thread started. waiting for signal.\n");
1121                 g_cond_wait(&player->next_play_thread_cond, &player->next_play_thread_mutex );
1122
1123                 debug_log("reconfigure pipeline for gapless play.\n");
1124
1125                 if ( player->next_play_thread_exit )
1126                 {
1127                         if(player->gapless.reconfigure)
1128                         {
1129                                 player->gapless.reconfigure = false;
1130                                 MMPLAYER_PLAYBACK_UNLOCK(player);
1131                         }
1132                         debug_log("exiting gapless play thread\n");
1133                         break;
1134                 }
1135
1136                 mainbin = player->pipeline->mainbin;
1137
1138                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
1139                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
1140                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
1141                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
1142                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
1143
1144                 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
1145         }
1146         g_mutex_unlock(&player->next_play_thread_mutex);
1147
1148         return NULL;
1149 }
1150
1151 static gpointer __mmplayer_repeat_thread(gpointer data)
1152 {
1153         mm_player_t* player = (mm_player_t*) data;
1154         gboolean ret_value = FALSE;
1155         MMHandleType attrs = 0;
1156         gint count = 0;
1157
1158         return_val_if_fail ( player, NULL );
1159
1160         g_mutex_lock(&player->repeat_thread_mutex);
1161         while ( ! player->repeat_thread_exit )
1162         {
1163                 debug_log("repeat thread started. waiting for signal.\n");
1164                 g_cond_wait(&player->repeat_thread_cond, &player->repeat_thread_mutex );
1165
1166                 if ( player->repeat_thread_exit )
1167                 {
1168                         debug_log("exiting repeat thread\n");
1169                         break;
1170                 }
1171
1172
1173                 /* lock */
1174                 g_mutex_lock(&player->cmd_lock);
1175
1176                 attrs = MMPLAYER_GET_ATTRS(player);
1177
1178                 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1179                 {
1180                         debug_error("can not get play count\n");
1181                         break;
1182                 }
1183
1184                 if ( player->section_repeat )
1185                 {
1186                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1187                 }
1188                 else
1189                 {
1190                         if ( player->playback_rate < 0.0 )
1191                         {
1192                                 player->resumed_by_rewind = TRUE;
1193                                 _mmplayer_set_mute((MMHandleType)player, 0);
1194                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1195                         }
1196
1197                         ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
1198                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1199                                 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1200
1201                         /* initialize */
1202                         player->sent_bos = FALSE;
1203                 }
1204
1205                 if ( ! ret_value )
1206                 {
1207                         debug_error("failed to set position to zero for rewind\n");
1208                         continue;
1209                 }
1210
1211                 /* decrease play count */
1212                 if ( count > 1 )
1213                 {
1214                         /* we successeded to rewind. update play count and then wait for next EOS */
1215                         count--;
1216
1217                         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1218
1219                         /* commit attribute */
1220                         if ( mmf_attrs_commit ( attrs ) )
1221                         {
1222                                 debug_error("failed to commit attribute\n");
1223                         }
1224                 }
1225
1226                 /* unlock */
1227                 g_mutex_unlock(&player->cmd_lock);
1228         }
1229
1230         g_mutex_unlock(&player->repeat_thread_mutex);
1231         return NULL;
1232 }
1233
1234 static void
1235 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
1236 {
1237         MMHandleType attrs = 0;
1238         guint64 data_size = 0;
1239         gchar* path = NULL;
1240         unsigned long pos_msec = 0;
1241         struct stat sb;
1242
1243         return_if_fail( player && player->pipeline && player->pipeline->mainbin);
1244
1245         __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_msec);       // update last_position
1246
1247         attrs = MMPLAYER_GET_ATTRS(player);
1248         if ( !attrs )
1249         {
1250                 debug_error("fail to get attributes.\n");
1251                 return;
1252         }
1253
1254         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1255         {
1256                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1257
1258                 if (stat(path, &sb) == 0)
1259                 {
1260                         data_size = (guint64)sb.st_size;
1261                 }
1262         }
1263         else if (MMPLAYER_IS_HTTP_STREAMING(player))
1264         {
1265                 data_size = player->http_content_size;
1266         }
1267
1268         __mm_player_streaming_buffering(        player->streamer,
1269                                                                                 buffering_msg,
1270                                                                                 data_size,
1271                                                                                 player->last_position,
1272                                                                                 player->duration);
1273
1274         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
1275
1276         return;
1277 }
1278
1279 static int
1280 __mmplayer_handle_buffering_message ( mm_player_t* player )
1281 {
1282         int ret = MM_ERROR_NONE;
1283         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1284         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1285         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1286         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1287
1288         MMPLAYER_CMD_LOCK( player );
1289
1290         if( !player || !player->streamer || MMPLAYER_IS_LIVE_STREAMING(player))
1291         {
1292                 ret = MM_ERROR_PLAYER_INVALID_STATE;
1293                 goto unlock_exit;
1294         }
1295
1296         prev_state = MMPLAYER_PREV_STATE(player);
1297         current_state = MMPLAYER_CURRENT_STATE(player);
1298         target_state = MMPLAYER_TARGET_STATE(player);
1299         pending_state = MMPLAYER_PENDING_STATE(player);
1300
1301         debug_log( "player state : prev %s, current %s, pending %s, target %s, buffering %d",
1302                 MMPLAYER_STATE_GET_NAME(prev_state),
1303                 MMPLAYER_STATE_GET_NAME(current_state),
1304                 MMPLAYER_STATE_GET_NAME(pending_state),
1305                 MMPLAYER_STATE_GET_NAME(target_state),
1306                 player->streamer->is_buffering);
1307
1308         if ( !player->streamer->is_buffering )
1309         {
1310                 /* NOTE : if buffering has done, player has to go to target state. */
1311                 switch ( target_state )
1312                 {
1313                         case MM_PLAYER_STATE_PAUSED :
1314                         {
1315                                 switch ( pending_state )
1316                                 {
1317                                         case MM_PLAYER_STATE_PLAYING:
1318                                         {
1319                                                 __gst_pause ( player, TRUE );
1320                                         }
1321                                         break;
1322
1323                                         case MM_PLAYER_STATE_PAUSED:
1324                                         {
1325                                                 debug_log("player is already going to paused state, there is nothing to do.\n");
1326                                         }
1327                                         break;
1328
1329                                         case MM_PLAYER_STATE_NONE:
1330                                         case MM_PLAYER_STATE_NULL:
1331                                         case MM_PLAYER_STATE_READY:
1332                                         default :
1333                                         {
1334                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1335                                         }
1336                                                 break;
1337                                 }
1338                         }
1339                         break;
1340
1341                         case MM_PLAYER_STATE_PLAYING :
1342                         {
1343                                 switch ( pending_state )
1344                                 {
1345                                         case MM_PLAYER_STATE_NONE:
1346                                         {
1347                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
1348                                                         __gst_resume ( player, TRUE );
1349                                         }
1350                                         break;
1351
1352                                         case MM_PLAYER_STATE_PAUSED:
1353                                         {
1354                                                 /* NOTE: It should be worked as asynchronously.
1355                                                  * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1356                                                  */
1357                                                 __gst_resume ( player, TRUE );
1358                                         }
1359                                         break;
1360
1361                                         case MM_PLAYER_STATE_PLAYING:
1362                                         {
1363                                                 debug_log("player is already going to playing state, there is nothing to do.\n");
1364                                         }
1365                                         break;
1366
1367                                         case MM_PLAYER_STATE_NULL:
1368                                         case MM_PLAYER_STATE_READY:
1369                                         default :
1370                                         {
1371                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1372                                         }
1373                                                 break;
1374                                 }
1375                         }
1376                         break;
1377
1378                         case MM_PLAYER_STATE_NULL :
1379                         case MM_PLAYER_STATE_READY :
1380                         case MM_PLAYER_STATE_NONE :
1381                         default:
1382                         {
1383                                 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1384                         }
1385                                 break;
1386                 }
1387         }
1388         else
1389         {
1390                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1391                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
1392                  */
1393                 switch ( pending_state )
1394                 {
1395                         case MM_PLAYER_STATE_NONE:
1396                         {
1397                                 if (current_state != MM_PLAYER_STATE_PAUSED)
1398                                 {
1399                                         debug_log("set pause state during buffering\n");
1400                                         __gst_pause ( player, TRUE );
1401
1402                                         // to cover the weak-signal environment.
1403                                         if (MMPLAYER_IS_RTSP_STREAMING(player))
1404                                         {
1405                                                 unsigned long position = 0;
1406                                                 gint64 pos_msec = 0;
1407
1408                                                 debug_log("[RTSP] seek to the buffering start point\n");
1409
1410                                                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
1411                                                 {
1412                                                         debug_error("failed to get position\n");
1413                                                         break;
1414                                                 }
1415
1416                                                 /* key unit seek */
1417                                                 pos_msec = position * G_GINT64_CONSTANT(1000000);
1418
1419                                                 __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
1420                                                                         GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1421                                                                         pos_msec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1422                                         }
1423                                 }
1424                         }
1425                         break;
1426
1427                         case MM_PLAYER_STATE_PLAYING:
1428                         {
1429                                 __gst_pause ( player, TRUE );
1430                         }
1431                         break;
1432
1433                         case MM_PLAYER_STATE_PAUSED:
1434                         {
1435                         }
1436                         break;
1437
1438                         case MM_PLAYER_STATE_NULL:
1439                         case MM_PLAYER_STATE_READY:
1440                         default :
1441                         {
1442                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1443                         }
1444                                 break;
1445                 }
1446         }
1447
1448 unlock_exit:
1449         MMPLAYER_CMD_UNLOCK( player );
1450         return ret;
1451 }
1452
1453 static void
1454 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
1455 {
1456         MMPlayerGstElement *textbin;
1457         MMPLAYER_FENTER();
1458
1459         return_if_fail ( player &&
1460                                         player->pipeline &&
1461                                         player->pipeline->textbin);
1462
1463         return_if_fail (player->pipeline->textbin[MMPLAYER_T_IDENTITY].gst);
1464
1465         textbin = player->pipeline->textbin;
1466
1467         if (is_drop)
1468         {
1469                 debug_log("Drop subtitle text after getting EOS\n");
1470
1471                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
1472                 g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1473
1474                 player->is_subtitle_force_drop = TRUE;
1475         }
1476         else
1477         {
1478                 if (player->is_subtitle_force_drop == TRUE)
1479                 {
1480                         debug_log("Enable subtitle data path without drop\n");
1481
1482                         g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1483                         g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
1484
1485                         debug_log ("non-connected with external display");
1486
1487                         player->is_subtitle_force_drop = FALSE;
1488                 }
1489         }
1490 }
1491
1492 static gboolean
1493 __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
1494 {
1495         mm_player_t* player = (mm_player_t*) data;
1496         gboolean ret = TRUE;
1497         static gboolean async_done = FALSE;
1498
1499         return_val_if_fail ( player, FALSE );
1500         return_val_if_fail ( msg && GST_IS_MESSAGE(msg), FALSE );
1501
1502         switch ( GST_MESSAGE_TYPE( msg ) )
1503         {
1504                 case GST_MESSAGE_UNKNOWN:
1505                         debug_log("unknown message received\n");
1506                 break;
1507
1508                 case GST_MESSAGE_EOS:
1509                 {
1510                         MMHandleType attrs = 0;
1511                         gint count = 0;
1512
1513                         debug_log("GST_MESSAGE_EOS received\n");
1514
1515                         /* NOTE : EOS event is comming multiple time. watch out it */
1516                         /* check state. we only process EOS when pipeline state goes to PLAYING */
1517                         if ( ! (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) )
1518                         {
1519                                 debug_log("EOS received on non-playing state. ignoring it\n");
1520                                 break;
1521                         }
1522
1523                         __mmplayer_drop_subtitle(player, TRUE);
1524
1525                         if ( (player->audio_stream_cb) && (player->set_mode.pcm_extraction) && (!player->audio_stream_render_cb_ex))
1526                         {
1527                                 GstPad *pad = NULL;
1528
1529                                 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1530
1531                                 debug_log("release audio callback\n");
1532
1533                                 /* release audio callback */
1534                                 gst_pad_remove_probe (pad, player->audio_cb_probe_id);
1535                                 player->audio_cb_probe_id = 0;
1536                                 /* audio callback should be free because it can be called even though probe remove.*/
1537                                 player->audio_stream_cb = NULL;
1538                                 player->audio_stream_cb_user_param = NULL;
1539
1540                         }
1541
1542                         /* rewind if repeat count is greater then zero */
1543                         /* get play count */
1544                         attrs = MMPLAYER_GET_ATTRS(player);
1545
1546                         if ( attrs )
1547                         {
1548                                 gboolean smooth_repeat = FALSE;
1549
1550                                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1551                                 mm_attrs_get_int_by_name(attrs, "profile_smooth_repeat", &smooth_repeat);
1552
1553                                 player->play_count = count;
1554
1555                                 debug_log("remaining play count: %d, playback rate: %f\n", count, player->playback_rate);
1556
1557                                 if ( count > 1 || count == -1 || player->playback_rate < 0.0 ) /* default value is 1 */
1558                                 {
1559                                         if ( smooth_repeat )
1560                                         {
1561                                                 debug_log("smooth repeat enabled. seeking operation will be excuted in new thread\n");
1562
1563                                                 g_cond_signal( &player->repeat_thread_cond );
1564
1565                                                 break;
1566                                         }
1567                                         else
1568                                         {
1569                                                 gint ret_value = 0;
1570
1571                                                 if ( player->section_repeat )
1572                                                 {
1573                                                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1574                                                 }
1575                                                 else
1576                                                 {
1577                                                         if ( player->playback_rate < 0.0 )
1578                                                         {
1579                                                                 player->resumed_by_rewind = TRUE;
1580                                                                 _mmplayer_set_mute((MMHandleType)player, 0);
1581                                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1582                                                         }
1583
1584                                                         __mmplayer_handle_eos_delay( player, player->ini.delay_before_repeat );
1585
1586                                                         /* initialize */
1587                                                         player->sent_bos = FALSE;
1588                                                 }
1589
1590                                                 if ( MM_ERROR_NONE != ret_value )
1591                                                 {
1592                                                         debug_error("failed to set position to zero for rewind\n");
1593                                                 }
1594
1595                                                 /* not posting eos when repeating */
1596                                                 break;
1597                                         }
1598                                 }
1599                         }
1600
1601                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-eos" );
1602
1603                         /* post eos message to application */
1604                         __mmplayer_handle_eos_delay( player, player->ini.eos_delay );
1605
1606                         /* reset last position */
1607                         player->last_position = 0;
1608                 }
1609                 break;
1610
1611                 case GST_MESSAGE_ERROR:
1612                 {
1613                         GError *error = NULL;
1614                         gchar* debug = NULL;
1615
1616                         /* generating debug info before returning error */
1617                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-error" );
1618
1619                         /* get error code */
1620                         gst_message_parse_error( msg, &error, &debug );
1621
1622                         if ( gst_structure_has_name ( gst_message_get_structure(msg), "streaming_error" ) )
1623                         {
1624                                 /* Note : the streaming error from the streaming source is handled
1625                                  *   using __mmplayer_handle_streaming_error.
1626                                  */
1627                                 __mmplayer_handle_streaming_error ( player, msg );
1628
1629                                 /* dump state of all element */
1630                                 __mmplayer_dump_pipeline_state( player );
1631                         }
1632                         else
1633                         {
1634                                 /* traslate gst error code to msl error code. then post it
1635                                  * to application if needed
1636                                  */
1637                                 __mmplayer_handle_gst_error( player, msg, error );
1638
1639                                 if (debug)
1640                                 {
1641                                         debug_error ("error debug : %s", debug);
1642                                 }
1643
1644                         }
1645
1646                         if (MMPLAYER_IS_HTTP_PD(player))
1647                         {
1648                                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
1649                         }
1650
1651                         MMPLAYER_FREEIF( debug );
1652                         g_error_free( error );
1653                 }
1654                 break;
1655
1656                 case GST_MESSAGE_WARNING:
1657                 {
1658                         char* debug = NULL;
1659                         GError* error = NULL;
1660
1661                         gst_message_parse_warning(msg, &error, &debug);
1662
1663                         debug_log("warning : %s\n", error->message);
1664                         debug_log("debug : %s\n", debug);
1665
1666                         MMPLAYER_POST_MSG( player, MM_MESSAGE_WARNING, NULL );
1667
1668                         MMPLAYER_FREEIF( debug );
1669                         g_error_free( error );
1670                 }
1671                 break;
1672
1673                 case GST_MESSAGE_TAG:
1674                 {
1675                         debug_log("GST_MESSAGE_TAG\n");
1676                         if ( ! __mmplayer_gst_extract_tag_from_msg( player, msg ) )
1677                         {
1678                                 debug_warning("failed to extract tags from gstmessage\n");
1679                         }
1680                 }
1681                 break;
1682
1683                 case GST_MESSAGE_BUFFERING:
1684                 {
1685                         MMMessageParamType msg_param = {0, };
1686
1687                         if (!MMPLAYER_IS_STREAMING(player))
1688                                 break;
1689
1690                         /* ignore the prev buffering message */
1691                         if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (player->streamer->is_buffering_done == TRUE))
1692                         {
1693                                 gint buffer_percent = 0;
1694
1695                                 gst_message_parse_buffering (msg, &buffer_percent);
1696
1697                                 if (buffer_percent == MAX_BUFFER_PERCENT)
1698                                 {
1699                                         debug_log ("Ignored all the previous buffering msg! (got %d%%)\n", buffer_percent);
1700                                         player->streamer->is_buffering_done = FALSE;
1701                                 }
1702
1703                                 break;
1704                         }
1705
1706                         __mmplayer_update_buffer_setting(player, msg);
1707
1708                         if(__mmplayer_handle_buffering_message ( player ) == MM_ERROR_NONE) {
1709
1710                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1711                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param );
1712                                 if (MMPLAYER_IS_RTSP_STREAMING(player) &&
1713                                                 (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT))
1714                                 {
1715                                         if (player->doing_seek)
1716                                         {
1717                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
1718                                                 {
1719                                                         player->doing_seek = FALSE;
1720                                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
1721                                                 }
1722                                                 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
1723                                                 {
1724                                                         async_done = TRUE;
1725                                                 }
1726                                         }
1727                                 }
1728                         }
1729                 }
1730                 break;
1731
1732                 case GST_MESSAGE_STATE_CHANGED:
1733                 {
1734                         MMPlayerGstElement *mainbin;
1735                         const GValue *voldstate, *vnewstate, *vpending;
1736                         GstState oldstate, newstate, pending;
1737
1738                         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
1739                         {
1740                                 debug_error("player pipeline handle is null");
1741                                 break;
1742                         }
1743
1744                         mainbin = player->pipeline->mainbin;
1745
1746                         /* we only handle messages from pipeline */
1747                         if( msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst )
1748                                 break;
1749
1750                         /* get state info from msg */
1751                         voldstate = gst_structure_get_value (gst_message_get_structure(msg), "old-state");
1752                         vnewstate = gst_structure_get_value (gst_message_get_structure(msg), "new-state");
1753                         vpending = gst_structure_get_value (gst_message_get_structure(msg), "pending-state");
1754
1755                         oldstate = (GstState)voldstate->data[0].v_int;
1756                         newstate = (GstState)vnewstate->data[0].v_int;
1757                         pending = (GstState)vpending->data[0].v_int;
1758
1759                         debug_log("state changed [%s] : %s ---> %s     final : %s\n",
1760                                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
1761                                 gst_element_state_get_name( (GstState)oldstate ),
1762                                 gst_element_state_get_name( (GstState)newstate ),
1763                                 gst_element_state_get_name( (GstState)pending ) );
1764
1765                         if (oldstate == newstate)
1766                         {
1767                                 debug_log("pipeline reports state transition to old state");
1768                                 break;
1769                         }
1770
1771                         switch(newstate)
1772                         {
1773                                 case GST_STATE_VOID_PENDING:
1774                                 break;
1775
1776                                 case GST_STATE_NULL:
1777                                 break;
1778
1779                                 case GST_STATE_READY:
1780                                 break;
1781
1782                                 case GST_STATE_PAUSED:
1783                                 {
1784                                         gboolean prepare_async = FALSE;
1785                                         gboolean is_drm = FALSE;
1786
1787                                         if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
1788                                                 __mmplayer_configure_audio_callback(player);
1789
1790                                         if ( ! player->sent_bos && oldstate == GST_STATE_READY) // managed prepare async case
1791                                         {
1792                                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
1793                                                 debug_log("checking prepare mode for async transition - %d", prepare_async);
1794                                         }
1795
1796                                         if ( MMPLAYER_IS_STREAMING(player) || prepare_async )
1797                                         {
1798                                                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
1799
1800                                                 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
1801                                                 {
1802                                                         __mm_player_streaming_set_content_bitrate(player->streamer,
1803                                                                 player->total_maximum_bitrate, player->total_bitrate);
1804                                                 }
1805                                         }
1806
1807                                         /* NOTE : should consider streaming case */
1808                                         /* check if drm file */
1809                                         if ((player->pipeline->mainbin[MMPLAYER_M_SRC].gst) &&
1810                                                 (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm")))
1811                                         {
1812                                                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
1813
1814                                                 if (is_drm)
1815                                                 {
1816                                                         player->is_drm_file = TRUE;
1817                                                 }
1818                                         }
1819                                 }
1820                                 break;
1821
1822                                 case GST_STATE_PLAYING:
1823                                 {
1824 /* for audio tunning */
1825 #ifndef IS_SDK
1826                                         if (player->can_support_codec == 0x03) {
1827                                                 gint volume_type;
1828                                                 mm_attrs_get_int_by_name(player->attrs, "sound_volume_type", &volume_type);
1829                                                 volume_type |= MM_SOUND_VOLUME_GAIN_VIDEO;
1830                                                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "volumetype", volume_type, NULL);
1831                                         }
1832 #endif
1833                                         if ( MMPLAYER_IS_STREAMING(player) ) // managed prepare async case when buffering is completed
1834                                         {
1835                                                 // pending state should be reset oyherwise, it's still playing even though it's resumed after bufferging.
1836                                                 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
1837                                                         (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
1838                                                 {
1839                                                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING);
1840                                                 }
1841                                         }
1842
1843                                         if (player->gapless.stream_changed)
1844                                         {
1845                                                 _mmplayer_update_content_attrs(player, ATTR_ALL);
1846                                         }
1847
1848                                         if (player->doing_seek && async_done)
1849                                         {
1850                                                 player->doing_seek = FALSE;
1851                                                 async_done = FALSE;
1852                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
1853                                         }
1854                                 }
1855                                 break;
1856
1857                                 default:
1858                                 break;
1859                         }
1860                 }
1861                 break;
1862
1863                 case GST_MESSAGE_CLOCK_LOST:
1864                         {
1865                                 GstClock *clock = NULL;
1866                                 gboolean need_new_clock = FALSE;
1867
1868                                 gst_message_parse_clock_lost (msg, &clock);
1869                                 debug_log("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
1870
1871                                 if (!player->videodec_linked)
1872                                 {
1873                                         need_new_clock = TRUE;
1874                                 }
1875                                 else if (!player->ini.use_system_clock)
1876                                 {
1877                                         need_new_clock = TRUE;
1878                                 }
1879
1880                                 if (need_new_clock) {
1881                                         debug_log ("Provide clock is TRUE, do pause->resume\n");
1882                                         __gst_pause(player, FALSE);
1883                                         __gst_resume(player, FALSE);
1884                                 }
1885                         }
1886                         break;
1887
1888                 case GST_MESSAGE_NEW_CLOCK:
1889                         {
1890                                 GstClock *clock = NULL;
1891                                 gst_message_parse_new_clock (msg, &clock);
1892                                 debug_log("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
1893                         }
1894                         break;
1895
1896                 case GST_MESSAGE_ELEMENT:
1897                         {
1898                                 const gchar *structure_name;
1899                                 gint count = 0;
1900                                 MMHandleType attrs = 0;
1901
1902                                 attrs = MMPLAYER_GET_ATTRS(player);
1903                                 if ( !attrs )
1904                                 {
1905                                         debug_error("cannot get content attribute");
1906                                         ret = FALSE;
1907                                         break;
1908                                 }
1909
1910                                 if(gst_message_get_structure(msg) == NULL)
1911                                         break;
1912
1913                                 structure_name = gst_structure_get_name(gst_message_get_structure(msg));
1914                                 if(!strcmp(structure_name, "Language_list"))
1915                                 {
1916                                         const GValue *lang_list = NULL;
1917                                         lang_list = gst_structure_get_value (gst_message_get_structure(msg), "lang_list");
1918                                         if(lang_list != NULL)
1919                                         {
1920                                                 count = g_list_length((GList *)g_value_get_pointer (lang_list));
1921                                                 if (count > 1)
1922                                                         debug_log("Total audio tracks (from parser) = %d \n",count);
1923                                         }
1924                                 }
1925
1926                                 if (!strcmp (structure_name, "Ext_Sub_Language_List"))
1927                                 {
1928                                         const GValue *lang_list = NULL;
1929                                         MMPlayerLangStruct *temp = NULL;
1930
1931                                         lang_list = gst_structure_get_value (gst_message_get_structure(msg), "lang_list");
1932                                         if (lang_list != NULL)
1933                                         {
1934                                                 count = g_list_length ((GList *)g_value_get_pointer (lang_list));
1935                                                 if (count)
1936                                                 {
1937                                                         player->subtitle_language_list = (GList *)g_value_get_pointer (lang_list);
1938                                                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
1939                                                         if (mmf_attrs_commit (attrs))
1940                                                           debug_error("failed to commit.\n");
1941                                                         debug_log("Total subtitle tracks = %d \n", count);
1942                                                 }
1943                                                 while (count)
1944                                                 {
1945                                                         temp = g_list_nth_data (player->subtitle_language_list, count - 1);
1946                                                         debug_log ("value of lang_key is %s and lang_code is %s",
1947                                                                                 temp->language_key, temp->language_code);
1948                                                         count--;
1949                                                 }
1950                                         }
1951                                 }
1952
1953                                 /* custom message */
1954                                 if (!strcmp (structure_name, "audio_codec_not_supported")) {
1955                                         MMMessageParamType msg_param = {0,};
1956                                         msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
1957                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
1958                                 }
1959                         }
1960                         break;
1961
1962                 case GST_MESSAGE_DURATION_CHANGED:
1963                 {
1964                         debug_log("GST_MESSAGE_DURATION_CHANGED\n");
1965                         ret = __mmplayer_gst_handle_duration(player, msg);
1966                         if (!ret)
1967                         {
1968                                 debug_warning("failed to update duration");
1969                         }
1970                 }
1971
1972                 break;
1973
1974                 case GST_MESSAGE_ASYNC_START:
1975                 {
1976                         debug_log("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1977                 }
1978                 break;
1979
1980                 case GST_MESSAGE_ASYNC_DONE:
1981                 {
1982                         debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1983
1984                         /* we only handle messages from pipeline */
1985                         if( msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
1986                                 break;
1987
1988                         if (player->doing_seek)
1989                         {
1990                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
1991                                 {
1992                                         player->doing_seek = FALSE;
1993                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
1994                                 }
1995                                 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
1996                                 {
1997                                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1998                                                 (player->streamer) &&
1999                                                 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
2000                                                 (player->streamer->is_buffering == FALSE))
2001                                         {
2002                                                 GstQuery *query = NULL;
2003                                                 gboolean busy = FALSE;
2004                                                 gint percent = 0;
2005
2006                                                 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer)
2007                                                 {
2008                                                         query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
2009                                                         if ( gst_element_query (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query ) )
2010                                                         {
2011                                                                 gst_query_parse_buffering_percent ( query, &busy, &percent);
2012                                                         }
2013                                                         gst_query_unref (query);
2014
2015                                                         debug_log("buffered percent(%s): %d\n",
2016                                                                 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
2017                                                 }
2018
2019                                                 if (percent >= 100)
2020                                                 {
2021                                                         player->streamer->is_buffering = FALSE;
2022                                                         __mmplayer_handle_buffering_message(player);
2023                                                 }
2024                                         }
2025
2026                                         async_done = TRUE;
2027                                 }
2028                         }
2029                 }
2030                 break;
2031
2032                 #if 0 /* delete unnecessary logs */
2033                 case GST_MESSAGE_REQUEST_STATE:         debug_log("GST_MESSAGE_REQUEST_STATE\n"); break;
2034                 case GST_MESSAGE_STEP_START:            debug_log("GST_MESSAGE_STEP_START\n"); break;
2035                 case GST_MESSAGE_QOS:                           debug_log("GST_MESSAGE_QOS\n"); break;
2036                 case GST_MESSAGE_PROGRESS:                      debug_log("GST_MESSAGE_PROGRESS\n"); break;
2037                 case GST_MESSAGE_ANY:                           debug_log("GST_MESSAGE_ANY\n"); break;
2038                 case GST_MESSAGE_INFO:                          debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2039                 case GST_MESSAGE_STATE_DIRTY:           debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2040                 case GST_MESSAGE_STEP_DONE:                     debug_log("GST_MESSAGE_STEP_DONE\n"); break;
2041                 case GST_MESSAGE_CLOCK_PROVIDE:         debug_log("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
2042                 case GST_MESSAGE_STRUCTURE_CHANGE:      debug_log("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
2043                 case GST_MESSAGE_STREAM_STATUS:         debug_log("GST_MESSAGE_STREAM_STATUS\n"); break;
2044                 case GST_MESSAGE_APPLICATION:           debug_log("GST_MESSAGE_APPLICATION\n"); break;
2045                 case GST_MESSAGE_SEGMENT_START:         debug_log("GST_MESSAGE_SEGMENT_START\n"); break;
2046                 case GST_MESSAGE_SEGMENT_DONE:          debug_log("GST_MESSAGE_SEGMENT_DONE\n"); break;
2047                 case GST_MESSAGE_LATENCY:                               debug_log("GST_MESSAGE_LATENCY\n"); break;
2048                 #endif
2049
2050                 default:
2051                 break;
2052         }
2053
2054         /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
2055          * gst_element_post_message api takes ownership of the message.
2056          */
2057         //gst_message_unref( msg );
2058
2059         return ret;
2060 }
2061
2062 static gboolean
2063 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
2064 {
2065         gint64 bytes = 0;
2066
2067         MMPLAYER_FENTER();
2068
2069         return_val_if_fail(player, FALSE);
2070         return_val_if_fail(msg, FALSE);
2071
2072         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2073                 (msg->src) && (msg->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst))
2074         {
2075                 debug_log("msg src : [%s]", GST_ELEMENT_NAME(GST_ELEMENT_CAST(msg->src)));
2076
2077                 if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes))
2078                 {
2079                         debug_log("data total size of http content: %lld", bytes);
2080                         player->http_content_size = bytes;
2081                 }
2082         }
2083         else
2084         {
2085                 /* handling audio clip which has vbr. means duration is keep changing */
2086                 _mmplayer_update_content_attrs (player, ATTR_DURATION );
2087         }
2088
2089         MMPLAYER_FLEAVE();
2090
2091         return TRUE;
2092 }
2093
2094
2095 static gboolean
2096 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg) // @
2097 {
2098
2099 /* macro for better code readability */
2100 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
2101 if (gst_tag_list_get_string(tag_list, gsttag, &string)) \
2102 {\
2103         if (string != NULL)\
2104         {\
2105                 secure_debug_log ( "update tag string : %s\n", string); \
2106                 mm_attrs_set_string_by_name(attribute, playertag, string); \
2107                 g_free(string);\
2108                 string = NULL;\
2109         }\
2110 }
2111
2112 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
2113 GstSample *sample = NULL;\
2114 if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample))\
2115 {\
2116         GstMapInfo info = GST_MAP_INFO_INIT;\
2117         buffer = gst_sample_get_buffer(sample);\
2118         if (!gst_buffer_map(buffer, &info, GST_MAP_READ)){\
2119                 debug_log("failed to get image data from tag");\
2120                 return FALSE;\
2121         }\
2122         secure_debug_log ( "update album cover data : %p, size : %d\n", info.data, info.size);\
2123         MMPLAYER_FREEIF(player->album_art); \
2124         player->album_art = (gchar *)g_malloc(info.size); \
2125         if (player->album_art) \
2126         { \
2127                 memcpy(player->album_art, info.data, info.size); \
2128                 mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, info.size); \
2129                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) \
2130                 { \
2131                         msg_param.data = (void *)player->album_art; \
2132                         msg_param.size = info.size; \
2133                         MMPLAYER_POST_MSG (player, MM_MESSAGE_IMAGE_BUFFER, &msg_param); \
2134                         secure_debug_log ( "post message image buffer data : %p, size : %d\n", info.data, info.size); \
2135                 } \
2136         } \
2137         gst_buffer_unmap(buffer, &info); \
2138 }
2139
2140 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
2141 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint))\
2142 {\
2143         if(v_uint)\
2144         {\
2145                 if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) \
2146                 {\
2147                         if (player->updated_bitrate_count == 0) \
2148                                 mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
2149                         if (player->updated_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2150                         {\
2151                                 player->bitrate[player->updated_bitrate_count] = v_uint;\
2152                                 player->total_bitrate += player->bitrate[player->updated_maximum_bitrate_count]; \
2153                                 player->updated_bitrate_count++; \
2154                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate);\
2155                                 secure_debug_log ( "update bitrate %d[bps] of stream #%d.\n", v_uint, player->updated_bitrate_count);\
2156                         }\
2157                 }\
2158                 else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) \
2159                 {\
2160                         if (player->updated_maximum_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2161                         {\
2162                                 player->maximum_bitrate[player->updated_maximum_bitrate_count] = v_uint;\
2163                                 player->total_maximum_bitrate += player->maximum_bitrate[player->updated_maximum_bitrate_count]; \
2164                                 player->updated_maximum_bitrate_count++; \
2165                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate); \
2166                                 secure_debug_log ( "update maximum bitrate %d[bps] of stream #%d\n", v_uint, player->updated_maximum_bitrate_count);\
2167                         }\
2168                 }\
2169                 else\
2170                 {\
2171                         mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
2172                 }\
2173                 v_uint = 0;\
2174         }\
2175 }
2176
2177 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
2178 if (gst_tag_list_get_date(tag_list, gsttag, &date))\
2179 {\
2180         if (date != NULL)\
2181         {\
2182                 string = g_strdup_printf("%d", g_date_get_year(date));\
2183                 mm_attrs_set_string_by_name(attribute, playertag, string);\
2184                 secure_debug_log ( "metainfo year : %s\n", string);\
2185                 MMPLAYER_FREEIF(string);\
2186                 g_date_free(date);\
2187         }\
2188 }
2189
2190 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
2191 if(gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64))\
2192 {\
2193         if(v_uint64)\
2194         {\
2195                 /* FIXIT : don't know how to store date */\
2196                 g_assert(1);\
2197                 v_uint64 = 0;\
2198         }\
2199 }
2200
2201 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
2202 if(gst_tag_list_get_double(tag_list, gsttag, &v_double))\
2203 {\
2204         if(v_double)\
2205         {\
2206                 /* FIXIT : don't know how to store date */\
2207                 g_assert(1);\
2208                 v_double = 0;\
2209         }\
2210 }
2211
2212         /* function start */
2213         GstTagList* tag_list = NULL;
2214
2215         MMHandleType attrs = 0;
2216
2217         char *string = NULL;
2218         guint v_uint = 0;
2219         GDate *date = NULL;
2220         /* album cover */
2221         GstBuffer *buffer = NULL;
2222         gint index = 0;
2223         MMMessageParamType msg_param = {0, };
2224
2225         /* currently not used. but those are needed for above macro */
2226         //guint64 v_uint64 = 0;
2227         //gdouble v_double = 0;
2228
2229         return_val_if_fail( player && msg, FALSE );
2230
2231         attrs = MMPLAYER_GET_ATTRS(player);
2232
2233         return_val_if_fail( attrs, FALSE );
2234
2235         /* get tag list from gst message */
2236         gst_message_parse_tag(msg, &tag_list);
2237
2238         /* store tags to player attributes */
2239         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
2240         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
2241         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
2242         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
2243         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
2244         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
2245         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
2246         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
2247         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
2248         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
2249         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
2250         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
2251         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
2252         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
2253         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
2254         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
2255         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
2256         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
2257         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
2258         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
2259         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
2260         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
2261         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
2262         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
2263         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
2264         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
2265         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
2266         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
2267         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
2268         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
2269         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
2270         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
2271         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
2272         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
2273         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
2274         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
2275         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
2276         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
2277         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
2278         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
2279         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
2280         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
2281         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
2282         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
2283         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
2284         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, attrs, "content_video_orientation");
2285
2286         if ( mmf_attrs_commit ( attrs ) )
2287                 debug_error("failed to commit.\n");
2288
2289         gst_tag_list_free(tag_list);
2290
2291         return TRUE;
2292 }
2293
2294 static void
2295 __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data)  // @
2296 {
2297         mm_player_t* player = (mm_player_t*) data;
2298
2299         MMPLAYER_FENTER();
2300
2301         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2302           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2303           * num_dynamic_pad. and this is no-more-pad situation which means mo more pad will be added.
2304           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2305
2306           * [1] audio and video will be dumped with filesink.
2307           * [2] autoplugging is done by just using pad caps.
2308           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
2309           * and the video will be dumped via filesink.
2310           */
2311         if ( player->num_dynamic_pad == 0 )
2312         {
2313                 debug_log("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
2314
2315                 if ( ! __mmplayer_gst_remove_fakesink( player,
2316                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
2317                 {
2318                         /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
2319                          * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
2320                          * source element are not same. To overcome this situation, this function will called
2321                          * several places and several times. Therefore, this is not an error case.
2322                          */
2323                         return;
2324                 }
2325         }
2326
2327         /* create dot before error-return. for debugging */
2328         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-no-more-pad" );
2329
2330         player->no_more_pad = TRUE;
2331
2332         MMPLAYER_FLEAVE();
2333 }
2334
2335 static gboolean
2336 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink) // @
2337 {
2338         GstElement* parent = NULL;
2339
2340         return_val_if_fail(player && player->pipeline, FALSE);
2341
2342         /* if we have no fakesink. this meas we are using decodebin which doesn'
2343         t need to add extra fakesink */
2344         return_val_if_fail(fakesink, TRUE);
2345
2346         /* lock */
2347         g_mutex_lock(&player->fsink_lock );
2348
2349         if ( ! fakesink->gst )
2350         {
2351                 goto ERROR;
2352         }
2353
2354         /* get parent of fakesink */
2355         parent = (GstElement*)gst_object_get_parent( (GstObject*)fakesink->gst );
2356         if ( ! parent )
2357         {
2358                 debug_log("fakesink already removed\n");
2359                 goto ERROR;
2360         }
2361
2362         gst_element_set_locked_state( fakesink->gst, TRUE );
2363
2364         /* setting the state to NULL never returns async
2365          * so no need to wait for completion of state transiton
2366          */
2367         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (fakesink->gst, GST_STATE_NULL) )
2368         {
2369                 debug_error("fakesink state change failure!\n");
2370
2371                 /* FIXIT : should I return here? or try to proceed to next? */
2372                 /* return FALSE; */
2373         }
2374
2375         /* remove fakesink from it's parent */
2376         if ( ! gst_bin_remove( GST_BIN( parent ), fakesink->gst ) )
2377         {
2378                 debug_error("failed to remove fakesink\n");
2379
2380                 gst_object_unref( parent );
2381
2382                 goto ERROR;
2383         }
2384
2385         gst_object_unref( parent );
2386
2387         debug_log("state-holder removed\n");
2388
2389         gst_element_set_locked_state( fakesink->gst, FALSE );
2390
2391         g_mutex_unlock( &player->fsink_lock );
2392         return TRUE;
2393
2394 ERROR:
2395         if ( fakesink->gst )
2396         {
2397                 gst_element_set_locked_state( fakesink->gst, FALSE );
2398         }
2399
2400         g_mutex_unlock( &player->fsink_lock );
2401         return FALSE;
2402 }
2403
2404
2405 static void
2406 __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2407 {
2408         GstPad *sinkpad = NULL;
2409         GstCaps* caps = NULL;
2410         GstElement* new_element = NULL;
2411         GstStructure* str = NULL;
2412         const gchar* name = NULL;
2413
2414         mm_player_t* player = (mm_player_t*) data;
2415
2416         MMPLAYER_FENTER();
2417
2418         return_if_fail( element && pad );
2419         return_if_fail( player &&
2420                                         player->pipeline &&
2421                                         player->pipeline->mainbin );
2422
2423
2424         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2425          * num_dynamic_pad will decreased after creating a sinkbin.
2426          */
2427         player->num_dynamic_pad++;
2428         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2429
2430         caps = gst_pad_query_caps( pad, NULL );
2431
2432         MMPLAYER_CHECK_NULL( caps );
2433
2434         /* clear  previous result*/
2435         player->have_dynamic_pad = FALSE;
2436
2437         str = gst_caps_get_structure(caps, 0);
2438
2439         if ( ! str )
2440         {
2441                 debug_error ("cannot get structure from caps.\n");
2442                 goto ERROR;
2443         }
2444
2445         name = gst_structure_get_name (str);
2446         if ( ! name )
2447         {
2448                 debug_error ("cannot get mimetype from structure.\n");
2449                 goto ERROR;
2450         }
2451
2452         if (strstr(name, "video"))
2453         {
2454                 gint stype = 0;
2455                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
2456
2457                 if (stype == MM_DISPLAY_SURFACE_NULL)
2458                 {
2459                         if (player->v_stream_caps)
2460                         {
2461                                 gst_caps_unref(player->v_stream_caps);
2462                                 player->v_stream_caps = NULL;
2463                         }
2464
2465                         new_element = gst_element_factory_make("fakesink", NULL);
2466                         player->num_dynamic_pad--;
2467                         goto NEW_ELEMENT;
2468                 }
2469         }
2470
2471         /* clear  previous result*/
2472         player->have_dynamic_pad = FALSE;
2473
2474         if ( !__mmplayer_try_to_plug_decodebin(player, pad, caps))
2475         {
2476                 debug_error("failed to autoplug for caps");
2477                 goto ERROR;
2478         }
2479
2480         /* check if there's dynamic pad*/
2481         if( player->have_dynamic_pad )
2482         {
2483                 debug_error("using pad caps assums there's no dynamic pad !\n");
2484                 goto ERROR;
2485         }
2486
2487         gst_caps_unref( caps );
2488         caps = NULL;
2489
2490 NEW_ELEMENT:
2491
2492         /* excute new_element if created*/
2493         if ( new_element )
2494         {
2495                 debug_log("adding new element to pipeline\n");
2496
2497                 /* set state to READY before add to bin */
2498                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2499
2500                 /* add new element to the pipeline */
2501                 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2502                 {
2503                         debug_error("failed to add autoplug element to bin\n");
2504                         goto ERROR;
2505                 }
2506
2507                 /* get pad from element */
2508                 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2509                 if ( !sinkpad )
2510                 {
2511                         debug_error("failed to get sinkpad from autoplug element\n");
2512                         goto ERROR;
2513                 }
2514
2515                 /* link it */
2516                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2517                 {
2518                         debug_error("failed to link autoplug element\n");
2519                         goto ERROR;
2520                 }
2521
2522                 gst_object_unref (sinkpad);
2523                 sinkpad = NULL;
2524
2525                 /* run. setting PLAYING here since streamming source is live source */
2526                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2527         }
2528
2529         MMPLAYER_FLEAVE();
2530
2531         return;
2532
2533 STATE_CHANGE_FAILED:
2534 ERROR:
2535         /* FIXIT : take care if new_element has already added to pipeline */
2536         if ( new_element )
2537                 gst_object_unref(GST_OBJECT(new_element));
2538
2539         if ( sinkpad )
2540                 gst_object_unref(GST_OBJECT(sinkpad));
2541
2542         if ( caps )
2543                 gst_object_unref(GST_OBJECT(caps));
2544
2545         /* FIXIT : how to inform this error to MSL ????? */
2546         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2547          * then post an error to application
2548          */
2549 }
2550
2551
2552
2553 /* FIXIT : check indent */
2554 #if 0
2555 static void
2556 __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2557 {
2558   GstPad *sinkpad = NULL;
2559   GstCaps* caps = NULL;
2560   GstElement* new_element = NULL;
2561   enum MainElementID element_id = MMPLAYER_M_NUM;
2562
2563   mm_player_t* player = (mm_player_t*) data;
2564
2565   MMPLAYER_FENTER();
2566
2567   return_if_fail( element && pad );
2568   return_if_fail(  player &&
2569           player->pipeline &&
2570           player->pipeline->mainbin );
2571
2572   debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2573
2574   {
2575     debug_log("using pad caps to autopluging instead of doing typefind\n");
2576     caps = gst_pad_query_caps( pad );
2577     MMPLAYER_CHECK_NULL( caps );
2578     /* clear  previous result*/
2579     player->have_dynamic_pad = FALSE;
2580     new_element = gst_element_factory_make("rtpmp2tdepay", "wfd_rtp_depay");
2581     if ( !new_element )
2582     {
2583       debug_error ( "failed to create wfd rtp depay element\n" );
2584       goto ERROR;
2585     }
2586     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2587     /* add new element to the pipeline */
2588     if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2589     {
2590       debug_log("failed to add autoplug element to bin\n");
2591       goto ERROR;
2592     }
2593     /* get pad from element */
2594     sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2595     if ( !sinkpad )
2596     {
2597       debug_log("failed to get sinkpad from autoplug element\n");
2598       goto ERROR;
2599     }
2600     /* link it */
2601     if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2602     {
2603       debug_log("failed to link autoplug element\n");
2604       goto ERROR;
2605     }
2606     gst_object_unref (sinkpad);
2607     sinkpad = NULL;
2608     pad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "src" );
2609     caps = gst_pad_query_caps( pad );
2610     MMPLAYER_CHECK_NULL( caps );
2611     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2612     /* create typefind */
2613     new_element = gst_element_factory_make( "typefind", NULL );
2614     if ( ! new_element )
2615     {
2616       debug_log("failed to create typefind\n");
2617       goto ERROR;
2618     }
2619
2620     MMPLAYER_SIGNAL_CONNECT(   player,
2621                 G_OBJECT(new_element),
2622                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2623                 "have-type",
2624                 G_CALLBACK(__mmplayer_typefind_have_type),
2625                 (gpointer)player);
2626
2627     player->have_dynamic_pad = FALSE;
2628   }
2629
2630   /* excute new_element if created*/
2631   if ( new_element )
2632   {
2633     debug_log("adding new element to pipeline\n");
2634
2635     /* set state to READY before add to bin */
2636     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2637
2638     /* add new element to the pipeline */
2639     if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2640     {
2641       debug_log("failed to add autoplug element to bin\n");
2642       goto ERROR;
2643     }
2644
2645     /* get pad from element */
2646     sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2647     if ( !sinkpad )
2648     {
2649       debug_log("failed to get sinkpad from autoplug element\n");
2650       goto ERROR;
2651     }
2652
2653     /* link it */
2654     if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2655     {
2656       debug_log("failed to link autoplug element\n");
2657       goto ERROR;
2658     }
2659
2660     gst_object_unref (sinkpad);
2661     sinkpad = NULL;
2662
2663     /* run. setting PLAYING here since streamming source is live source */
2664     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2665   }
2666
2667   /* store handle to futher manipulation */
2668   player->pipeline->mainbin[element_id].id = element_id;
2669   player->pipeline->mainbin[element_id].gst = new_element;
2670
2671   MMPLAYER_FLEAVE();
2672
2673   return;
2674
2675 STATE_CHANGE_FAILED:
2676 ERROR:
2677   /* FIXIT : take care if new_element has already added to pipeline */
2678   if ( new_element )
2679     gst_object_unref(GST_OBJECT(new_element));
2680
2681   if ( sinkpad )
2682     gst_object_unref(GST_OBJECT(sinkpad));
2683
2684   if ( caps )
2685     gst_object_unref(GST_OBJECT(caps));
2686
2687   /* FIXIT : how to inform this error to MSL ????? */
2688   /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2689    * then post an error to application
2690    */
2691 }
2692 #endif
2693
2694 static GstPadProbeReturn
2695 __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
2696 {
2697         debug_log ("pad(%s:%s) is blocked", GST_DEBUG_PAD_NAME(pad));
2698         return GST_PAD_PROBE_OK;
2699 }
2700
2701 static GstPadProbeReturn
2702 __mmplayer_audio_data_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
2703 {
2704         mm_player_t* player = (mm_player_t*) u_data;
2705         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
2706
2707         /* TO_CHECK: performance */
2708         return_val_if_fail (player && GST_IS_BUFFER(pad_buffer), GST_PAD_PROBE_OK);
2709
2710         if (GST_BUFFER_PTS_IS_VALID(pad_buffer) && GST_BUFFER_DURATION_IS_VALID(pad_buffer))
2711                 player->gapless.next_pts = GST_BUFFER_PTS(pad_buffer) + GST_BUFFER_DURATION(pad_buffer);
2712
2713         return GST_PAD_PROBE_OK;
2714 }
2715
2716 static GstPadProbeReturn
2717 __mmplayer_gst_selector_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
2718 {
2719         GstPadProbeReturn ret = GST_PAD_PROBE_OK;
2720         GstEvent *event = GST_PAD_PROBE_INFO_DATA (info);
2721         mm_player_t* player = (mm_player_t*)data;
2722
2723         switch (GST_EVENT_TYPE (event)) {
2724                 case GST_EVENT_STREAM_START:
2725                 break;
2726                 case GST_EVENT_SEGMENT: {
2727                         GstSegment segment;
2728                         GstEvent *tmpev;
2729
2730                         if (!player->gapless.running)
2731                                 break;
2732
2733                         if (player->gapless.stream_changed) {
2734                                 player->gapless.start_time += player->gapless.next_pts;
2735                                 player->gapless.stream_changed = FALSE;
2736                         }
2737
2738                         debug_log ("event: %" GST_PTR_FORMAT, event);
2739                         gst_event_copy_segment (event, &segment);
2740
2741                         if (segment.format == GST_FORMAT_TIME)
2742                         {
2743                                 segment.base = player->gapless.start_time;
2744                                 debug_log ("base of segment: %" GST_TIME_FORMAT, GST_TIME_ARGS (segment.base));
2745
2746                                 tmpev = gst_event_new_segment (&segment);
2747                                 gst_event_set_seqnum (tmpev, gst_event_get_seqnum (event));
2748                                 gst_event_unref (event);
2749                                 GST_PAD_PROBE_INFO_DATA(info) = tmpev;
2750                         }
2751                         break;
2752                 }
2753                 default:
2754                 break;
2755         }
2756         return ret;
2757 }
2758
2759 static void
2760 __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data)
2761 {
2762         mm_player_t* player = NULL;
2763         GstElement* pipeline = NULL;
2764         GstElement* selector = NULL;
2765         GstElement* fakesink = NULL;
2766         GstCaps* caps = NULL;
2767         GstStructure* str = NULL;
2768         const gchar* name = NULL;
2769         GstPad* sinkpad = NULL;
2770         GstPad* srcpad = NULL;
2771         gboolean first_track = FALSE;
2772
2773         enum MainElementID elemId = MMPLAYER_M_NUM;
2774         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2775
2776         /* check handles */
2777         player = (mm_player_t*)data;
2778
2779         return_if_fail (elem && pad);
2780         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
2781
2782         //debug_log ("pad-added signal handling\n");
2783
2784         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
2785
2786         /* get mimetype from caps */
2787         caps = gst_pad_query_caps (pad, NULL);
2788         if ( !caps )
2789         {
2790                 debug_error ("cannot get caps from pad.\n");
2791                 goto ERROR;
2792         }
2793
2794         str = gst_caps_get_structure (caps, 0);
2795         if ( ! str )
2796         {
2797                 debug_error ("cannot get structure from caps.\n");
2798                 goto ERROR;
2799         }
2800
2801         name = gst_structure_get_name (str);
2802         if ( ! name )
2803         {
2804                 debug_error ("cannot get mimetype from structure.\n");
2805                 goto ERROR;
2806         }
2807
2808         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
2809         //debug_log ("detected mimetype : %s\n", name);
2810
2811         if (strstr(name, "video"))
2812         {
2813                 gint stype = 0;
2814                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
2815
2816                 /* don't make video because of not required, and not support multiple track */
2817                 if (stype == MM_DISPLAY_SURFACE_NULL)
2818                 {
2819                         debug_log ("no video sink by null surface or multiple track");
2820                         gchar *caps_str = gst_caps_to_string(caps);
2821                         if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
2822                         {
2823                                 player->set_mode.video_zc = TRUE;
2824                         }
2825                         MMPLAYER_FREEIF( caps_str );
2826
2827                         if (player->v_stream_caps)
2828                         {
2829                                 gst_caps_unref(player->v_stream_caps);
2830                                 player->v_stream_caps = NULL;
2831                         }
2832
2833                         debug_log ("create fakesink instead of videobin");
2834
2835                         /* fake sink */
2836                         fakesink = gst_element_factory_make ("fakesink", NULL);
2837                         if (fakesink == NULL)
2838                         {
2839                                 debug_error ("ERROR : fakesink create error\n");
2840                                 goto ERROR;
2841                         }
2842
2843                         player->video_fakesink = fakesink;
2844
2845                         gst_bin_add (GST_BIN(pipeline), fakesink);
2846
2847                         // link
2848                         sinkpad = gst_element_get_static_pad (fakesink, "sink");
2849
2850                         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
2851                         {
2852                                 debug_warning ("failed to link fakesink\n");
2853                                 gst_object_unref (GST_OBJECT(fakesink));
2854                                 goto ERROR;
2855                         }
2856
2857                         if (player->set_mode.media_packet_video_stream)
2858                                 player->video_cb_probe_id = gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER, __mmplayer_video_stream_probe, player, NULL);
2859
2860                         g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
2861                         g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
2862                         gst_element_set_state (fakesink, GST_STATE_PAUSED);
2863
2864                         goto DONE;
2865                 }
2866                 __mmplayer_gst_decode_callback (elem, pad, player);
2867         }
2868         else
2869         {
2870                 if (strstr(name, "audio"))
2871                 {
2872                         gint samplerate = 0;
2873                         gint channels = 0;
2874
2875                         if (MMPLAYER_IS_ES_BUFF_SRC(player))
2876                         {
2877                                 __mmplayer_gst_decode_callback (elem, pad, player);
2878                                 return;
2879                         }
2880
2881                         debug_log ("audio selector \n");
2882                         elemId = MMPLAYER_M_A_INPUT_SELECTOR;
2883                         stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2884
2885                         gst_structure_get_int (str, "rate", &samplerate);
2886                         gst_structure_get_int (str, "channels", &channels);
2887
2888                         if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
2889                                 /* fake sink */
2890                                 fakesink = gst_element_factory_make ("fakesink", NULL);
2891                                 if (fakesink == NULL)
2892                                 {
2893                                         debug_error ("ERROR : fakesink create error\n");
2894                                         goto ERROR;
2895                                 }
2896
2897                                 gst_bin_add (GST_BIN(pipeline), fakesink);
2898
2899                                 /* link */
2900                                 sinkpad = gst_element_get_static_pad (fakesink, "sink");
2901
2902                                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
2903                                 {
2904                                         debug_warning ("failed to link fakesink\n");
2905                                         gst_object_unref (GST_OBJECT(fakesink));
2906                                         goto ERROR;
2907                                 }
2908
2909                                 g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
2910                                 g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
2911                                 gst_element_set_state (fakesink, GST_STATE_PAUSED);
2912
2913                                 goto DONE;
2914                         }
2915                 }
2916                 else if (strstr(name, "text"))
2917                 {
2918                         debug_log ("text selector \n");
2919                         elemId = MMPLAYER_M_T_INPUT_SELECTOR;
2920                         stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
2921                 }
2922                 else
2923                 {
2924                         debug_error ("wrong elem id \n");
2925                         goto ERROR;
2926                 }
2927         }
2928
2929         if(strstr(name, "video"))
2930                 return;
2931
2932         selector = player->pipeline->mainbin[elemId].gst;
2933
2934         if (selector == NULL)
2935         {
2936                 selector = gst_element_factory_make ("input-selector", NULL);
2937                 debug_log ("Creating input-selector\n");
2938                 if (selector == NULL)
2939                 {
2940                         debug_error ("ERROR : input-selector create error\n");
2941                         goto ERROR;
2942                 }
2943                 g_object_set (selector, "sync-streams", TRUE, NULL);
2944
2945                 player->pipeline->mainbin[elemId].id = elemId;
2946                 player->pipeline->mainbin[elemId].gst = selector;
2947
2948                 first_track = TRUE;
2949                 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK;      // default
2950
2951                 srcpad = gst_element_get_static_pad (selector, "src");
2952
2953                 debug_log ("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
2954                 player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
2955                         __mmplayer_gst_selector_blocked, NULL, NULL);
2956                 player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
2957                         __mmplayer_gst_selector_event_probe, player, NULL);
2958
2959                 gst_element_set_state (selector, GST_STATE_PAUSED);
2960                 gst_bin_add (GST_BIN(pipeline), selector);
2961         }
2962         else
2963         {
2964                 debug_log ("input-selector is already created.\n");
2965                 selector = player->pipeline->mainbin[elemId].gst;
2966         }
2967
2968         // link
2969         debug_log ("Calling request pad with selector %p \n", selector);
2970         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
2971
2972         debug_log ("got pad %s:%s from selector", GST_DEBUG_PAD_NAME (sinkpad));
2973
2974         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
2975         {
2976                 debug_warning ("failed to link selector\n");
2977                 gst_object_unref (GST_OBJECT(selector));
2978                 goto ERROR;
2979         }
2980
2981         if (first_track)
2982         {
2983                 debug_log ("this is first track --> active track \n");
2984                 g_object_set (selector, "active-pad", sinkpad, NULL);
2985         }
2986
2987         _mmplayer_track_update_info(player, stream_type, sinkpad);
2988
2989
2990 DONE:
2991 ERROR:
2992
2993         if (caps)
2994         {
2995                 gst_caps_unref (caps);
2996         }
2997
2998         if (sinkpad)
2999         {
3000                 gst_object_unref (GST_OBJECT(sinkpad));
3001                 sinkpad = NULL;
3002         }
3003
3004         if (srcpad)
3005         {
3006                 gst_object_unref (GST_OBJECT(srcpad));
3007                 srcpad = NULL;
3008         }
3009
3010         return;
3011 }
3012
3013 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
3014 {
3015         GstPad* srcpad = NULL;
3016         MMHandleType attrs = 0;
3017         gint active_index = 0;
3018
3019         // [link] input-selector :: textbin
3020         srcpad = gst_element_get_static_pad (text_selector, "src");
3021         if (!srcpad)
3022         {
3023                 debug_error("failed to get srcpad from selector\n");
3024                 return;
3025         }
3026
3027         debug_log ("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
3028
3029         active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
3030         if ((active_index != DEFAULT_TRACK) &&
3031                 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE))
3032         {
3033                 debug_warning("failed to change text track\n");
3034                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
3035         }
3036
3037         player->no_more_pad = TRUE;
3038         __mmplayer_gst_decode_callback (text_selector, srcpad, player);
3039
3040         debug_log ("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3041         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id)
3042         {
3043                 gst_pad_remove_probe (srcpad, player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id);
3044                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id = 0;
3045         }
3046
3047         debug_log("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3048
3049         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
3050                 player->has_closed_caption = TRUE;
3051
3052         attrs = MMPLAYER_GET_ATTRS(player);
3053         if ( attrs )
3054         {
3055                 mm_attrs_set_int_by_name(attrs, "content_text_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3056                 if (mmf_attrs_commit (attrs))
3057                         debug_error("failed to commit.\n");
3058         }
3059         else
3060         {
3061                 debug_error("cannot get content attribute");
3062         }
3063
3064         if (srcpad)
3065         {
3066                 gst_object_unref ( GST_OBJECT(srcpad) );
3067                 srcpad = NULL;
3068         }
3069 }
3070
3071 int _mmplayer_gst_set_audio_channel(MMHandleType hplayer, MMPlayerAudioChannel ch_idx)
3072 {
3073         int result = MM_ERROR_NONE;
3074
3075         mm_player_t* player = (mm_player_t*)hplayer;
3076         MMPlayerGstElement* mainbin = NULL;
3077         gchar* change_pad_name = NULL;
3078         GstPad* sinkpad = NULL;
3079         GstCaps* caps = NULL;
3080
3081         MMPLAYER_FENTER();
3082
3083         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3084
3085         debug_log ("Change Audio mode to %d\n", ch_idx);
3086         player->use_deinterleave = TRUE;
3087
3088         if ((!player->pipeline) || (!player->pipeline->mainbin))
3089         {
3090                 debug_log ("pre setting : %d\n", ch_idx);
3091
3092                 player->audio_mode.active_pad_index = ch_idx;
3093                 return result;
3094         }
3095
3096         mainbin = player->pipeline->mainbin;
3097
3098         if (mainbin[MMPLAYER_M_A_SELECTOR].gst == NULL)
3099         {
3100                 if (player->max_audio_channels < 2)
3101                 {
3102                         debug_log ("mono channel track only\n");
3103                         return result;
3104                 }
3105
3106                 debug_warning ("selector doesn't exist\n");
3107                 return result;  /* keep playing */
3108         }
3109
3110         debug_log ("total_ch_num : %d\n", player->audio_mode.total_track_num);
3111
3112         if (player->audio_mode.total_track_num < 2)
3113         {
3114                 debug_warning ("there is no another audio path\n");
3115                 return result;  /* keep playing */
3116         }
3117
3118         if ((ch_idx < 0) || (ch_idx >= player->audio_mode.total_track_num))
3119         {
3120                 debug_warning ("Not a proper ch_idx : %d \n", ch_idx);
3121                 return result;  /* keep playing */
3122         }
3123
3124         /*To get the new pad from the selector*/
3125         change_pad_name = g_strdup_printf ("sink%d", ch_idx);
3126         if (change_pad_name == NULL)
3127         {
3128                 debug_warning ("Pad does not exists\n");
3129                 goto ERROR;     /* keep playing */
3130         }
3131
3132         debug_log ("new active pad name: %s\n", change_pad_name);
3133
3134         sinkpad = gst_element_get_static_pad (mainbin[MMPLAYER_M_A_SELECTOR].gst, change_pad_name);
3135         if (sinkpad == NULL)
3136         {
3137                 //result = MM_ERROR_PLAYER_INTERNAL;
3138                 goto ERROR;     /* keep playing */
3139         }
3140
3141         debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3142         g_object_set (mainbin[MMPLAYER_M_A_SELECTOR].gst, "active-pad", sinkpad, NULL);
3143
3144         caps = gst_pad_get_current_caps(sinkpad);
3145         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3146
3147         __mmplayer_set_audio_attrs (player, caps);
3148         player->audio_mode.active_pad_index = ch_idx;
3149
3150 ERROR:
3151
3152         if (sinkpad)
3153                 gst_object_unref (sinkpad);
3154
3155         MMPLAYER_FREEIF(change_pad_name);
3156
3157         MMPLAYER_FLEAVE();
3158         return result;
3159 }
3160
3161
3162
3163 static void
3164 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
3165 {
3166         mm_player_t* player = (mm_player_t*)data;
3167         GstElement* selector = NULL;
3168         GstElement* queue = NULL;
3169
3170         GstPad* srcpad = NULL;
3171         GstPad* sinkpad = NULL;
3172         gchar* caps_str= NULL;
3173
3174         MMPLAYER_FENTER();
3175         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3176
3177         caps_str = gst_caps_to_string(gst_pad_get_current_caps(pad));
3178         debug_log ("deinterleave new caps : %s\n", caps_str);
3179         MMPLAYER_FREEIF(caps_str);
3180
3181         if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL)
3182         {
3183                 debug_error ("ERROR : queue create error\n");
3184                 goto ERROR;
3185         }
3186
3187         g_object_set(G_OBJECT(queue),
3188                                 "max-size-buffers", 10,
3189                                 "max-size-bytes", 0,
3190                                 "max-size-time", (guint64)0,
3191                                 NULL);
3192
3193         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3194
3195         if (!selector)
3196         {
3197                 debug_error("there is no audio channel selector.\n");
3198                 goto ERROR;
3199         }
3200
3201         srcpad = gst_element_get_static_pad (queue, "src");
3202         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3203
3204         debug_log ("link (%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
3205
3206         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3207         {
3208                 debug_warning ("failed to link deinterleave - selector\n");
3209                 goto ERROR;
3210         }
3211
3212         gst_element_set_state (queue, GST_STATE_PAUSED);
3213         player->audio_mode.total_track_num++;
3214
3215 ERROR:
3216
3217         if (srcpad)
3218         {
3219                 gst_object_unref ( GST_OBJECT(srcpad) );
3220                 srcpad = NULL;
3221         }
3222
3223         if (sinkpad)
3224         {
3225                 gst_object_unref ( GST_OBJECT(sinkpad) );
3226                 sinkpad = NULL;
3227         }
3228
3229         MMPLAYER_FLEAVE();
3230         return;
3231 }
3232
3233 static void
3234 __mmplayer_gst_deinterleave_no_more_pads (GstElement *elem, gpointer data)
3235 {
3236         mm_player_t* player = NULL;
3237         GstElement* selector = NULL;
3238         GstPad* sinkpad = NULL;
3239         gint active_index = 0;
3240         gchar* change_pad_name = NULL;
3241         GstCaps* caps = NULL;   // no need to unref
3242         gint default_audio_ch = 0;
3243
3244         MMPLAYER_FENTER();
3245         player = (mm_player_t*) data;
3246
3247         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3248
3249         if (!selector)
3250         {
3251                 debug_error("there is no audio channel selector.\n");
3252                 goto ERROR;
3253         }
3254
3255         active_index = player->audio_mode.active_pad_index;
3256
3257         if (active_index != default_audio_ch)
3258         {
3259                 gint audio_ch = default_audio_ch;
3260
3261                 /*To get the new pad from the selector*/
3262                 change_pad_name = g_strdup_printf ("sink%d", active_index);
3263                 if (change_pad_name != NULL)
3264                 {
3265                         sinkpad = gst_element_get_static_pad (selector, change_pad_name);
3266                         if (sinkpad != NULL)
3267                         {
3268                                 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3269                                 g_object_set (selector, "active-pad", sinkpad, NULL);
3270
3271                                 audio_ch = active_index;
3272
3273                                 caps = gst_pad_get_current_caps(sinkpad);
3274                                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3275
3276                                 __mmplayer_set_audio_attrs (player, caps);
3277                         }
3278                 }
3279
3280                 player->audio_mode.active_pad_index = audio_ch;
3281                 debug_log("audio LR info (0:stereo) = %d\n", player->audio_mode.active_pad_index);
3282         }
3283
3284 ERROR:
3285
3286         if (sinkpad)
3287                 gst_object_unref (sinkpad);
3288
3289         MMPLAYER_FLEAVE();
3290         return;
3291 }
3292
3293 static void
3294 __mmplayer_gst_build_deinterleave_path (GstElement *elem, GstPad *pad, gpointer data)
3295 {
3296         mm_player_t* player = NULL;
3297         MMPlayerGstElement *mainbin = NULL;
3298
3299         GstElement* tee = NULL;
3300         GstElement* stereo_queue = NULL;
3301         GstElement* mono_queue = NULL;
3302         GstElement* conv = NULL;
3303         GstElement* filter = NULL;
3304         GstElement* deinterleave = NULL;
3305         GstElement* selector = NULL;
3306
3307         GstPad* srcpad = NULL;
3308         GstPad* selector_srcpad = NULL;
3309         GstPad* sinkpad = NULL;
3310         GstCaps* caps = NULL;
3311         gulong block_id = 0;
3312
3313         MMPLAYER_FENTER();
3314
3315         /* check handles */
3316         player = (mm_player_t*) data;
3317
3318         return_if_fail( elem && pad );
3319         return_if_fail( player && player->pipeline && player->pipeline->mainbin );
3320
3321         mainbin = player->pipeline->mainbin;
3322
3323         /* tee */
3324         if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL)
3325         {
3326                 debug_error ("ERROR : tee create error\n");
3327                 goto ERROR;
3328         }
3329
3330         mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
3331         mainbin[MMPLAYER_M_A_TEE].gst = tee;
3332
3333         gst_element_set_state (tee, GST_STATE_PAUSED);
3334
3335         /* queue */
3336         srcpad = gst_element_get_request_pad (tee, "src_%u");
3337         if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3338         {
3339                 debug_error ("ERROR : stereo queue create error\n");
3340                 goto ERROR;
3341         }
3342
3343         g_object_set(G_OBJECT(stereo_queue),
3344                                 "max-size-buffers", 10,
3345                                 "max-size-bytes", 0,
3346                                 "max-size-time", (guint64)0,
3347                                 NULL);
3348
3349         player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
3350         player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
3351
3352         if (srcpad)
3353         {
3354                 gst_object_unref (GST_OBJECT(srcpad));
3355                 srcpad = NULL;
3356         }
3357
3358         srcpad = gst_element_get_request_pad (tee, "src_%u");
3359
3360         if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3361         {
3362                 debug_error ("ERROR : mono queue create error\n");
3363                 goto ERROR;
3364         }
3365
3366         g_object_set(G_OBJECT(mono_queue),
3367                                 "max-size-buffers", 10,
3368                                 "max-size-bytes", 0,
3369                                 "max-size-time", (guint64)0,
3370                                 NULL);
3371
3372         player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3373         player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3374
3375         gst_element_set_state (stereo_queue, GST_STATE_PAUSED);
3376         gst_element_set_state (mono_queue, GST_STATE_PAUSED);
3377
3378         /* audioconvert */
3379         srcpad = gst_element_get_static_pad (mono_queue, "src");
3380         if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL)
3381         {
3382                 debug_error ("ERROR : audioconvert create error\n");
3383                 goto ERROR;
3384         }
3385
3386         player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3387         player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3388
3389         /* caps filter */
3390         if (srcpad)
3391         {
3392                 gst_object_unref (GST_OBJECT(srcpad));
3393                 srcpad = NULL;
3394         }
3395         srcpad = gst_element_get_static_pad (conv, "src");
3396
3397         if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL)
3398         {
3399                 debug_error ("ERROR : capsfilter create error\n");
3400                 goto ERROR;
3401         }
3402
3403         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3404         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3405
3406         caps = gst_caps_from_string( "audio/x-raw-int, "
3407                                 "width = (int) 16, "
3408                                 "depth = (int) 16, "
3409                                 "channels = (int) 2");
3410
3411         g_object_set (GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL );
3412         gst_caps_unref( caps );
3413
3414         gst_element_set_state (conv, GST_STATE_PAUSED);
3415         gst_element_set_state (filter, GST_STATE_PAUSED);
3416
3417         /* deinterleave */
3418         if (srcpad)
3419         {
3420                 gst_object_unref (GST_OBJECT(srcpad));
3421                 srcpad = NULL;
3422         }
3423         srcpad = gst_element_get_static_pad (filter, "src");
3424
3425         if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL)
3426         {
3427                 debug_error ("ERROR : deinterleave create error\n");
3428                 goto ERROR;
3429         }
3430
3431         g_object_set (deinterleave, "keep-positions", TRUE, NULL);
3432
3433         MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3434                                                         G_CALLBACK (__mmplayer_gst_deinterleave_pad_added), player);
3435
3436         MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3437                                                         G_CALLBACK (__mmplayer_gst_deinterleave_no_more_pads), player);
3438
3439         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3440         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3441
3442         /* selector */
3443         selector = gst_element_factory_make ("input-selector", "audio-channel-selector");
3444         if (selector == NULL)
3445         {
3446                 debug_error ("ERROR : audio-selector create error\n");
3447                 goto ERROR;
3448         }
3449
3450         g_object_set (selector, "sync-streams", TRUE, NULL);
3451         gst_bin_add (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3452
3453         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3454         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3455
3456         selector_srcpad = gst_element_get_static_pad (selector, "src");
3457
3458         debug_log ("blocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3459         block_id =
3460                 gst_pad_add_probe(selector_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3461                         __mmplayer_gst_selector_blocked, NULL, NULL);
3462
3463         if (srcpad)
3464         {
3465                 gst_object_unref (GST_OBJECT(srcpad));
3466                 srcpad = NULL;
3467         }
3468
3469         srcpad = gst_element_get_static_pad(stereo_queue, "src");
3470         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3471
3472         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3473         {
3474                 debug_warning ("failed to link queue_stereo - selector\n");
3475                 goto ERROR;
3476         }
3477
3478         player->audio_mode.total_track_num++;
3479
3480         g_object_set (selector, "active-pad", sinkpad, NULL);
3481         gst_element_set_state (deinterleave, GST_STATE_PAUSED);
3482         gst_element_set_state (selector, GST_STATE_PAUSED);
3483
3484         __mmplayer_gst_decode_callback (selector, selector_srcpad, player);
3485
3486 ERROR:
3487
3488         debug_log ("unblocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3489         if (block_id != 0)
3490         {
3491                 gst_pad_remove_probe (selector_srcpad, block_id);
3492                 block_id = 0;
3493         }
3494
3495         if (sinkpad)
3496         {
3497                 gst_object_unref (GST_OBJECT(sinkpad));
3498                 sinkpad = NULL;
3499         }
3500
3501         if (srcpad)
3502         {
3503                 gst_object_unref (GST_OBJECT(srcpad));
3504                 srcpad = NULL;
3505         }
3506
3507         if (selector_srcpad)
3508         {
3509                 gst_object_unref (GST_OBJECT(selector_srcpad));
3510                 selector_srcpad = NULL;
3511         }
3512
3513         MMPLAYER_FLEAVE();
3514         return;
3515 }
3516
3517 static void
3518 __mmplayer_gst_decode_no_more_pads (GstElement *elem, gpointer data)
3519 {
3520         mm_player_t* player = NULL;
3521         GstPad* srcpad = NULL;
3522         GstElement* audio_selector = NULL;
3523         GstElement* text_selector = NULL;
3524         MMHandleType attrs = 0;
3525         gint active_index = 0;
3526         gint64 dur_bytes = 0L;
3527
3528         player = (mm_player_t*) data;
3529
3530         debug_log("no-more-pad signal handling\n");
3531
3532         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3533                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
3534         {
3535                 debug_warning("no need to go more");
3536
3537                 if (player->gapless.reconfigure)
3538                 {
3539                         player->gapless.reconfigure = FALSE;
3540                         MMPLAYER_PLAYBACK_UNLOCK(player);
3541                 }
3542
3543                 return;
3544         }
3545
3546         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3547                 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3548                 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3549                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
3550         {
3551                 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
3552
3553                 if (NULL == player->streamer)
3554                 {
3555                         debug_warning("invalid state for buffering");
3556                         goto ERROR;
3557                 }
3558
3559                 gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
3560                 guint buffer_bytes = init_buffering_time * ESTIMATED_BUFFER_UNIT;
3561
3562                 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
3563                 debug_log("[Decodebin2] set use-buffering on Q2 (pre buffer time: %d sec, buffer size : %d)\n", (gint)init_buffering_time, buffer_bytes);
3564
3565                 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
3566
3567                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
3568                         debug_error("fail to get duration.\n");
3569
3570                 // enable use-buffering on queue2 instead of multiqueue (ex)audio only streaming
3571                 // use file information was already set on Q2 when it was created.
3572                 __mm_player_streaming_set_queue2(player->streamer,
3573                                                 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
3574                                                 TRUE,                                                           // use_buffering
3575                                                 buffer_bytes,
3576                                                 init_buffering_time,
3577                                                 1.0,                                                            // low percent
3578                                                 player->ini.http_buffering_limit,       // high percent
3579                                                 FALSE,
3580                                                 NULL,
3581                                                 ((dur_bytes>0)?((guint64)dur_bytes):0));
3582         }
3583         audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
3584         text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3585         if (audio_selector)
3586         {
3587                 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
3588                 if ((active_index != DEFAULT_TRACK) &&
3589                         (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE))
3590                 {
3591                         debug_warning("failed to change audio track\n");
3592                         player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
3593                 }
3594
3595                 // [link] input-selector :: audiobin
3596                 srcpad = gst_element_get_static_pad (audio_selector, "src");
3597                 if (!srcpad)
3598                 {
3599                         debug_error("failed to get srcpad from selector\n");
3600                         goto ERROR;
3601                 }
3602
3603                 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3604                 if (!text_selector)
3605                         player->no_more_pad = TRUE;
3606
3607                 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2))
3608                 {
3609                         debug_log ("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3610                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id)
3611                         {
3612                                 gst_pad_remove_probe (srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3613                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3614                         }
3615
3616                         __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
3617                 }
3618                 else
3619                 {
3620                         __mmplayer_gst_decode_callback (audio_selector, srcpad, player);
3621
3622                         debug_log ("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3623                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id)
3624                         {
3625                                 gst_pad_remove_probe (srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3626                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3627                         }
3628                 }
3629
3630                 debug_log("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3631
3632                 attrs = MMPLAYER_GET_ATTRS(player);
3633                 if ( attrs )
3634                 {
3635                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3636                         if (mmf_attrs_commit (attrs))
3637                                 debug_error("failed to commit.\n");
3638                 }
3639                 else
3640                 {
3641                         debug_error("cannot get content attribute");
3642                 }
3643         }
3644         else
3645         {
3646                 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst))
3647                 {
3648                         debug_log ("There is no audio track : remove audiobin");
3649
3650                         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN );
3651                         __mmplayer_del_sink ( player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst );
3652
3653                         MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->audiobin, MMPLAYER_A_BIN );
3654                         MMPLAYER_FREEIF ( player->pipeline->audiobin )
3655                 }
3656
3657                 if (player->num_dynamic_pad == 0)
3658                 {
3659                         __mmplayer_pipeline_complete (NULL, player);
3660                 }
3661         }
3662
3663
3664         if (!MMPLAYER_IS_ES_BUFF_SRC(player))
3665         {
3666                 if (text_selector)
3667                 {
3668                         __mmplayer_handle_text_decode_path(player, text_selector);
3669                 }
3670         }
3671
3672         MMPLAYER_FLEAVE();
3673
3674 ERROR:
3675         if (srcpad)
3676         {
3677                 gst_object_unref ( GST_OBJECT(srcpad) );
3678                 srcpad = NULL;
3679         }
3680
3681         if (player->gapless.reconfigure)
3682         {
3683                 player->gapless.reconfigure = FALSE;
3684                 MMPLAYER_PLAYBACK_UNLOCK(player);
3685         }
3686 }
3687
3688 static void
3689 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // @
3690 {
3691         mm_player_t* player = NULL;
3692         MMHandleType attrs = 0;
3693         GstElement* pipeline = NULL;
3694         GstCaps* caps = NULL;
3695         gchar* caps_str = NULL;
3696         GstStructure* str = NULL;
3697         const gchar* name = NULL;
3698         GstPad* sinkpad = NULL;
3699         GstElement* sinkbin = NULL;
3700         gboolean reusing = FALSE;
3701         GstElement *text_selector = NULL;
3702
3703         /* check handles */
3704         player = (mm_player_t*) data;
3705
3706         return_if_fail( elem && pad );
3707         return_if_fail(player && player->pipeline && player->pipeline->mainbin);
3708
3709         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3710
3711         attrs = MMPLAYER_GET_ATTRS(player);
3712         if ( !attrs )
3713         {
3714                 debug_error("cannot get content attribute\n");
3715                 goto ERROR;
3716         }
3717
3718         /* get mimetype from caps */
3719         caps = gst_pad_query_caps( pad, NULL );
3720         if ( !caps )
3721         {
3722                 debug_error("cannot get caps from pad.\n");
3723                 goto ERROR;
3724         }
3725         caps_str = gst_caps_to_string(caps);
3726
3727         str = gst_caps_get_structure( caps, 0 );
3728         if ( ! str )
3729         {
3730                 debug_error("cannot get structure from caps.\n");
3731                 goto ERROR;
3732         }
3733
3734         name = gst_structure_get_name(str);
3735         if ( ! name )
3736         {
3737                 debug_error("cannot get mimetype from structure.\n");
3738                 goto ERROR;
3739         }
3740
3741         //debug_log("detected mimetype : %s\n", name);
3742
3743         if (strstr(name, "audio"))
3744         {
3745                 if (player->pipeline->audiobin == NULL)
3746                 {
3747                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player))
3748                         {
3749                                 debug_error("failed to create audiobin. continuing without audio\n");
3750                                 goto ERROR;
3751                         }
3752
3753                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3754                         debug_log("creating audiosink bin success\n");
3755                 }
3756                 else
3757                 {
3758                         reusing = TRUE;
3759                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3760                         debug_log("reusing audiobin\n");
3761                         _mmplayer_update_content_attrs( player, ATTR_AUDIO);
3762                 }
3763
3764                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
3765                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
3766
3767                 player->audiosink_linked  = 1;
3768
3769                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
3770                 if ( !sinkpad )
3771                 {
3772                         debug_error("failed to get pad from sinkbin\n");
3773                         goto ERROR;
3774                 }
3775         }
3776         else if (strstr(name, "video"))
3777         {
3778                 if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
3779                 {
3780                         player->set_mode.video_zc = TRUE;
3781                 }
3782
3783                 if (player->pipeline->videobin == NULL)
3784                 {
3785                         /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
3786                         /* get video surface type */
3787                         int surface_type = 0;
3788                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
3789
3790                         if (surface_type == MM_DISPLAY_SURFACE_NULL)
3791                         {
3792                                 debug_log("not make videobin because it dose not want\n");
3793                                 goto ERROR;
3794                         }
3795
3796                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type) )
3797                         {
3798                                 debug_error("failed to create videobin. continuing without video\n");
3799                                 goto ERROR;
3800                         }
3801
3802                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3803                         debug_log("creating videosink bin success\n");
3804                 }
3805                 else
3806                 {
3807                         reusing = TRUE;
3808                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3809                         debug_log("re-using videobin\n");
3810                         _mmplayer_update_content_attrs( player, ATTR_VIDEO);
3811                 }
3812
3813                 /* FIXIT : track number shouldn't be hardcoded */
3814                 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 1);
3815                 player->videosink_linked  = 1;
3816
3817                 /* NOTE : intermediate code before doing H/W subtitle compositon */
3818                 if ( player->use_textoverlay && player->play_subtitle )
3819                 {
3820                         debug_log("using textoverlay for external subtitle");
3821                         /* check text bin has created well */
3822                         if ( player->pipeline && player->pipeline->textbin )
3823                         {
3824                                 /* get sinkpad from textoverlay */
3825                                 sinkpad = gst_element_get_static_pad(
3826                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
3827                                         "video_sink" );
3828                                 if ( ! sinkpad )
3829                                 {
3830                                         debug_error("failed to get sink pad from textoverlay");
3831                                         goto ERROR;
3832                                 }
3833
3834                                 /* link new pad with textoverlay first */
3835                                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
3836                                 {
3837                                         debug_error("failed to get pad from sinkbin\n");
3838                                         goto ERROR;
3839                                 }
3840
3841                                 gst_object_unref(sinkpad);
3842                                 sinkpad = NULL;
3843
3844                                 /* alright, override pad to textbin.src for futher link */
3845                                 pad = gst_element_get_static_pad(
3846                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
3847                                         "src" );
3848                                 if ( ! pad )
3849                                 {
3850                                         debug_error("failed to get sink pad from textoverlay");
3851                                         goto ERROR;
3852                                 }
3853                         }
3854                         else
3855                         {
3856                                 debug_error("should not reach here.");
3857                                 goto ERROR;
3858                         }
3859                 }
3860
3861                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
3862                 if ( !sinkpad )
3863                 {
3864                         debug_error("failed to get pad from sinkbin\n");
3865                         goto ERROR;
3866                 }
3867         }
3868         else if (strstr(name, "text"))
3869         {
3870                 if (player->pipeline->textbin == NULL)
3871                 {
3872                         MMPlayerGstElement* mainbin = NULL;
3873
3874                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
3875                         {
3876                                 debug_error("failed to create textbin. continuing without text\n");
3877                                 goto ERROR;
3878                         }
3879
3880                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3881                         debug_log("creating textsink bin success\n");
3882
3883                         /* FIXIT : track number shouldn't be hardcoded */
3884                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
3885
3886                         player->textsink_linked  = 1;
3887                         debug_msg("player->textsink_linked set to 1\n");
3888
3889                         sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "text_sink" );
3890                         if ( !sinkpad )
3891                         {
3892                                 debug_error("failed to get pad from sinkbin\n");
3893                                 goto ERROR;
3894                         }
3895
3896                         mainbin = player->pipeline->mainbin;
3897
3898                         if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst)
3899                         {
3900                           /* input selector */
3901                           text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
3902                           if ( !text_selector )
3903                           {
3904                             debug_error ( "failed to create subtitle input selector element\n" );
3905                             goto ERROR;
3906                           }
3907                           g_object_set (text_selector, "sync-streams", TRUE, NULL);
3908
3909                           mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
3910                           mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
3911
3912                           /* warm up */
3913                           if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_READY))
3914                           {
3915                             debug_error("failed to set state(READY) to sinkbin\n");
3916                             goto ERROR;
3917                           }
3918
3919                           if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector))
3920                           {
3921                             debug_warning("failed to add subtitle input selector\n");
3922                             goto ERROR;
3923                           }
3924
3925                           debug_log ("created element input-selector");
3926
3927                         }
3928                         else
3929                         {
3930                           debug_log ("already having subtitle input selector");
3931                           text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3932                         }
3933                 }
3934
3935                 else
3936                 {
3937                         if (!player->textsink_linked)
3938                         {
3939                                 debug_log("re-using textbin\n");
3940
3941                                 reusing = TRUE;
3942                                 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3943
3944                                 player->textsink_linked  = 1;
3945                                 debug_msg("player->textsink_linked set to 1\n");
3946                         }
3947                         else
3948                         {
3949                                 debug_log("ignoring internal subtutle since external subtitle is available");
3950                         }
3951                 }
3952         }
3953         else
3954         {
3955                 debug_warning("unknown type of elementary stream! ignoring it...\n");
3956                 goto ERROR;
3957         }
3958
3959         if ( sinkbin )
3960         {
3961                 if(!reusing)
3962                 {
3963                         /* warm up */
3964                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_READY ) )
3965                         {
3966                                 debug_error("failed to set state(READY) to sinkbin\n");
3967                                 goto ERROR;
3968                         }
3969
3970                         /* Added for multi audio support to avoid adding audio bin again*/
3971                         /* add */
3972                         if ( FALSE == gst_bin_add( GST_BIN(pipeline), sinkbin ) )
3973                         {
3974                                 debug_error("failed to add sinkbin to pipeline\n");
3975                                 goto ERROR;
3976                         }
3977                 }
3978
3979                 /* link */
3980                 if (GST_PAD_LINK_OK != GST_PAD_LINK (pad, sinkpad))
3981                 {
3982                         debug_error("failed to get pad from sinkbin\n");
3983                         goto ERROR;
3984                 }
3985
3986                 if (!reusing)
3987                 {
3988                         /* run */
3989                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (sinkbin, GST_STATE_PAUSED))
3990                         {
3991                                 debug_error("failed to set state(PAUSED) to sinkbin\n");
3992                                 goto ERROR;
3993                         }
3994
3995                         if (text_selector)
3996                         {
3997                           if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_PAUSED))
3998                           {
3999                             debug_error("failed to set state(PAUSED) to sinkbin\n");
4000                             goto ERROR;
4001                           }
4002                         }
4003                 }
4004
4005                 gst_object_unref (sinkpad);
4006                 sinkpad = NULL;
4007         }
4008
4009         debug_log ("linking sink bin success\n");
4010
4011         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
4012          * streaming task. if the task blocked, then buffer will not flow to the next element
4013          * ( autoplugging element ). so this is special hack for streaming. please try to remove it
4014          */
4015         /* dec stream count. we can remove fakesink if it's zero */
4016         if (player->num_dynamic_pad)
4017                 player->num_dynamic_pad--;
4018
4019         debug_log ("no more pads: %d stream count dec : %d (num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
4020
4021         if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
4022         {
4023                 __mmplayer_pipeline_complete (NULL, player);
4024         }
4025
4026         /* FIXIT : please leave a note why this code is needed */
4027         if(MMPLAYER_IS_WFD_STREAMING( player ))
4028         {
4029                 player->no_more_pad = TRUE;
4030         }
4031
4032 ERROR:
4033
4034         MMPLAYER_FREEIF(caps_str);
4035
4036         if ( caps )
4037                 gst_caps_unref( caps );
4038
4039         if ( sinkpad )
4040                 gst_object_unref(GST_OBJECT(sinkpad));
4041
4042         /* flusing out new attributes */
4043         if (  mmf_attrs_commit ( attrs ) )
4044         {
4045                 debug_error("failed to comit attributes\n");
4046         }
4047
4048         return;
4049 }
4050
4051 static int
4052 __mmplayer_gst_element_link_bucket(GList* element_bucket) // @
4053 {
4054         GList* bucket = element_bucket;
4055         MMPlayerGstElement* element = NULL;
4056         MMPlayerGstElement* prv_element = NULL;
4057         gint successful_link_count = 0;
4058
4059         MMPLAYER_FENTER();
4060
4061         return_val_if_fail(element_bucket, -1);
4062
4063         prv_element = (MMPlayerGstElement*)bucket->data;
4064         bucket = bucket->next;
4065
4066         for ( ; bucket; bucket = bucket->next )
4067         {
4068                 element = (MMPlayerGstElement*)bucket->data;
4069
4070                 if ( element && element->gst )
4071                 {
4072                         /* If next element is audio appsrc then make a seprate audio pipeline */
4073                         if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),"audio_appsrc") ||
4074                                 !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),"subtitle_appsrc"))
4075                         {
4076                                 prv_element = element;
4077                                 continue;
4078                         }
4079
4080                         if ( GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst)) )
4081                         {
4082                                 debug_log("linking [%s] to [%s] success\n",
4083                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4084                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
4085                                 successful_link_count ++;
4086                         }
4087                         else
4088                         {
4089                                 debug_log("linking [%s] to [%s] failed\n",
4090                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4091                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
4092                                 return -1;
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         return_val_if_fail(element_bucket, 0);
4114         return_val_if_fail(bin, 0);
4115
4116         for ( ; bucket; bucket = bucket->next )
4117         {
4118                 element = (MMPlayerGstElement*)bucket->data;
4119
4120                 if ( element && element->gst )
4121                 {
4122                         if( !gst_bin_add(bin, GST_ELEMENT(element->gst)) )
4123                         {
4124                                 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
4125                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
4126                                         GST_ELEMENT_NAME(GST_ELEMENT(bin) ) );
4127                                 return 0;
4128                         }
4129                         successful_add_count ++;
4130                 }
4131         }
4132
4133         MMPLAYER_FLEAVE();
4134
4135         return successful_add_count;
4136 }
4137
4138 static void __mmplayer_gst_caps_notify_cb (GstPad * pad, GParamSpec * unused, gpointer data)
4139 {
4140         mm_player_t* player = (mm_player_t*) data;
4141         GstCaps *caps = NULL;
4142         GstStructure *str = NULL;
4143         const char *name;
4144
4145         MMPLAYER_FENTER();
4146
4147         return_if_fail ( pad )
4148         return_if_fail ( unused )
4149         return_if_fail ( data )
4150
4151         caps = gst_pad_get_current_caps( pad );
4152         if ( !caps )
4153         {
4154                 return;
4155         }
4156
4157         str = gst_caps_get_structure(caps, 0);
4158         if ( !str )
4159         {
4160                 goto ERROR;
4161         }
4162
4163         name = gst_structure_get_name(str);
4164         if ( !name )
4165         {
4166                 goto ERROR;
4167         }
4168
4169         debug_log("name = %s\n", name);
4170
4171         if (strstr(name, "audio"))
4172         {
4173                 _mmplayer_update_content_attrs (player, ATTR_AUDIO);
4174
4175                 if (player->audio_stream_changed_cb)
4176                 {
4177                         debug_error("call the audio stream changed cb\n");
4178                         player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
4179                 }
4180         }
4181         else if (strstr(name, "video"))
4182         {
4183                 _mmplayer_update_content_attrs (player, ATTR_VIDEO);
4184
4185                 if (player->video_stream_changed_cb)
4186                 {
4187                         debug_error("call the video stream changed cb\n");
4188                         player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
4189                 }
4190         }
4191         else
4192         {
4193                 goto ERROR;
4194         }
4195
4196 ERROR:
4197
4198         gst_caps_unref(caps);
4199
4200         MMPLAYER_FLEAVE();
4201
4202         return;
4203 }
4204
4205
4206
4207 /**
4208  * This function is to create audio pipeline for playing.
4209  *
4210  * @param       player          [in]    handle of player
4211  *
4212  * @return      This function returns zero on success.
4213  * @remark
4214  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
4215  */
4216 #define MMPLAYER_CREATEONLY_ELEMENT(x_bin, x_id, x_factory, x_name) \
4217 x_bin[x_id].id = x_id;\
4218 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4219 if ( ! x_bin[x_id].gst )\
4220 {\
4221         debug_error("failed to create %s \n", x_factory);\
4222         goto ERROR;\
4223 }\
4224
4225 #define MMPLAYER_CREATE_ELEMENT_ADD_BIN(x_bin, x_id, x_factory, x_name, y_bin, x_player) \
4226 x_bin[x_id].id = x_id;\
4227 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4228 if ( ! x_bin[x_id].gst )\
4229 {\
4230         debug_error("failed to create %s \n", x_factory);\
4231         goto ERROR;\
4232 }\
4233 else\
4234 {\
4235         if (x_player->ini.set_dump_element_flag)\
4236                 __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
4237 }\
4238 if( !gst_bin_add(GST_BIN(y_bin), GST_ELEMENT(x_bin[x_id].gst)))\
4239 {\
4240         debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",\
4241                 GST_ELEMENT_NAME(GST_ELEMENT(x_bin[x_id].gst)),\
4242                 GST_ELEMENT_NAME(GST_ELEMENT(y_bin) ) );\
4243         goto ERROR;\
4244 }\
4245
4246 /* macro for code readability. just for sinkbin-creation functions */
4247 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
4248 do \
4249 { \
4250         x_bin[x_id].id = x_id;\
4251         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4252         if ( ! x_bin[x_id].gst )\
4253         {\
4254                 debug_error("failed to create %s \n", x_factory);\
4255                 goto ERROR;\
4256         }\
4257         else\
4258         {\
4259                 if (x_player->ini.set_dump_element_flag)\
4260                         __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
4261         }\
4262         if ( x_add_bucket )\
4263                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
4264 } while(0);
4265
4266 static void
4267 __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
4268 {
4269         mm_player_t* player = (mm_player_t*) data;
4270
4271         gint channel = 0;
4272         gint rate = 0;
4273         gint depth = 0;
4274         gint endianness = 0;
4275         guint64 channel_mask = 0;
4276
4277         MMPlayerAudioStreamDataType audio_stream = { 0, };
4278         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
4279
4280         MMPLAYER_FENTER();
4281         return_if_fail(player->audio_stream_render_cb_ex);
4282
4283         debug_log ("__mmplayer_audio_stream_decoded_render_cb new pad: %s", GST_PAD_NAME (pad));
4284
4285         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
4286         audio_stream.data = mapinfo.data;
4287         audio_stream.data_size = mapinfo.size;
4288
4289         GstCaps *caps = gst_pad_get_current_caps( pad );
4290         GstStructure *structure = gst_caps_get_structure (caps, 0);
4291
4292         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
4293         gst_structure_get_int (structure, "rate", &rate);
4294         gst_structure_get_int (structure, "channels", &channel);
4295         gst_structure_get_int (structure, "depth", &depth);
4296         gst_structure_get_int (structure, "endianness", &endianness);
4297         gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
4298
4299         gst_caps_unref(GST_CAPS(caps));
4300
4301         audio_stream.bitrate = rate;
4302         audio_stream.channel = channel;
4303         audio_stream.depth = depth;
4304         audio_stream.is_little_endian = (endianness == 1234 ? 1 : 0);
4305         audio_stream.channel_mask = channel_mask;
4306         debug_log ("bitrate : %d channel : %d depth: %d ls_little_endian : %d channel_mask: %d, %p", rate, channel, depth, endianness, channel_mask, player->audio_stream_cb_user_param);
4307         player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param);
4308         gst_buffer_unmap(buffer, &mapinfo);
4309
4310         MMPLAYER_FLEAVE();
4311 }
4312
4313 static void
4314 __mmplayer_gst_audio_deinterleave_pad_added (GstElement *elem, GstPad *pad, gpointer data)
4315 {
4316         mm_player_t* player = (mm_player_t*)data;
4317         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
4318         GstPad* sinkpad = NULL;
4319         GstElement *queue = NULL, *sink = NULL;
4320
4321         MMPLAYER_FENTER();
4322         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
4323
4324         queue = gst_element_factory_make ("queue", NULL);
4325         if (queue == NULL)
4326         {
4327                 debug_log ("fail make queue\n");
4328                 goto ERROR;
4329         }
4330
4331         sink = gst_element_factory_make ("fakesink", NULL);
4332         if (sink == NULL)
4333         {
4334                 debug_log ("fail make fakesink\n");
4335                 goto ERROR;
4336         }
4337
4338         gst_bin_add_many (GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
4339
4340         if (!gst_element_link_pads_full (queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING))
4341         {
4342                 debug_warning("failed to link queue & sink\n");
4343                 goto ERROR;
4344         }
4345
4346         sinkpad = gst_element_get_static_pad (queue, "sink");
4347
4348         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
4349         {
4350                 debug_warning ("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
4351                 goto ERROR;
4352         }
4353
4354         debug_error("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
4355
4356         gst_object_unref (sinkpad);
4357         g_object_set (sink, "sync", player->audio_stream_sink_sync, NULL);
4358         g_object_set (sink, "signal-handoffs", TRUE, NULL);
4359
4360         gst_element_set_state (sink, GST_STATE_PAUSED);
4361         gst_element_set_state (queue, GST_STATE_PAUSED);
4362
4363         MMPLAYER_SIGNAL_CONNECT( player,
4364                 G_OBJECT(sink),
4365                 MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4366                 "handoff",
4367                 G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
4368                 (gpointer)player );
4369
4370         MMPLAYER_FLEAVE();
4371         return ;
4372
4373 ERROR:
4374         debug_error("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
4375         if (queue)
4376         {
4377                 gst_object_unref(GST_OBJECT(queue));
4378                 queue = NULL;
4379         }
4380         if (sink)
4381         {
4382                 gst_object_unref(GST_OBJECT(sink));
4383                 sink = NULL;
4384         }
4385         if (sinkpad)
4386         {
4387                 gst_object_unref ( GST_OBJECT(sinkpad) );
4388                 sinkpad = NULL;
4389         }
4390
4391         return;
4392 }
4393
4394 void __mmplayer_gst_set_audiosink_property(mm_player_t* player, MMHandleType attrs)
4395 {
4396         #define MAX_PROPS_LEN 64
4397         gint volume_type = 0;
4398         gint latency_mode = 0;
4399         gchar *stream_type = NULL;
4400         gchar *latency = NULL;
4401         gint stream_id = 0;
4402         gchar stream_props[MAX_PROPS_LEN] = {0,};
4403         GstStructure *props = NULL;
4404
4405         /* set volume table
4406          * It should be set after player creation through attribute.
4407          * But, it can not be changed during playing.
4408          */
4409         MMPLAYER_FENTER();
4410         mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
4411         mm_attrs_get_string_by_name (attrs, "sound_stream_type", &stream_type );
4412
4413         if (!stream_type)
4414         {
4415                 debug_error("stream_type is null.\n");
4416         }
4417         else
4418         {
4419                 snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d", stream_type, stream_id);
4420                 props = gst_structure_from_string(stream_props, NULL);
4421                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
4422                 debug_log("stream_id[%d], stream_type[%s], result[%s].\n", stream_id, stream_type, stream_props);
4423         }
4424
4425         mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
4426         mm_attrs_get_int_by_name(attrs, "sound_volume_type", &volume_type);
4427
4428         switch (latency_mode)
4429         {
4430                 case AUDIO_LATENCY_MODE_LOW:
4431                         latency = g_strndup("low", 3);
4432                         break;
4433                 case AUDIO_LATENCY_MODE_MID:
4434                         latency = g_strndup("mid", 3);
4435                         break;
4436                 case AUDIO_LATENCY_MODE_HIGH:
4437                         latency = g_strndup("high", 4);
4438                         break;
4439         };
4440
4441         /* hook sound_type if emergency case */
4442         if (player->sound_focus.focus_changed_msg == MM_PLAYER_FOCUS_CHANGED_BY_EMERGENCY)
4443         {
4444                 debug_log ("emergency session, hook sound_type from [%d] to [%d]\n", volume_type, MM_SOUND_VOLUME_TYPE_EMERGENCY);
4445                 volume_type = MM_SOUND_VOLUME_TYPE_EMERGENCY;
4446         }
4447 #if 0 //need to check
4448         if (player->sound_focus.user_route_policy != 0)
4449         {
4450                 route_path = player->sound_focus.user_route_policy;
4451         }
4452
4453         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
4454                         "latency", latency_mode,
4455                         NULL);
4456
4457         debug_log("audiosink property status...volume type:%d, user-route=%d, latency=%d \n",
4458                 volume_type, route_path, latency_mode);
4459         MMPLAYER_FLEAVE();
4460
4461 #endif
4462
4463         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
4464                         "latency", latency,
4465                         NULL);
4466
4467         debug_log("audiosink property - volume type=%d, latency=%s \n",
4468                 volume_type, latency);
4469
4470         g_free(latency);
4471
4472         MMPLAYER_FLEAVE();
4473 }
4474
4475 static int
4476 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
4477 {
4478         MMPlayerGstElement* first_element = NULL;
4479         MMPlayerGstElement* audiobin = NULL;
4480         MMHandleType attrs = 0;
4481         GstPad *pad = NULL;
4482         GstPad *ghostpad = NULL;
4483         GList* element_bucket = NULL;
4484         gboolean link_audio_sink_now = TRUE;
4485         int i =0;
4486
4487         MMPLAYER_FENTER();
4488
4489         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
4490
4491         /* alloc handles */
4492         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
4493         if ( ! audiobin )
4494         {
4495                 debug_error("failed to allocate memory for audiobin\n");
4496                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
4497         }
4498
4499         attrs = MMPLAYER_GET_ATTRS(player);
4500
4501         /* create bin */
4502         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
4503         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
4504         if ( !audiobin[MMPLAYER_A_BIN].gst )
4505         {
4506                 debug_error("failed to create audiobin\n");
4507                 goto ERROR;
4508         }
4509
4510         /* take it */
4511         player->pipeline->audiobin = audiobin;
4512
4513         player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
4514
4515         /* Adding audiotp plugin for reverse trickplay feature */
4516 //      MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
4517
4518         /* converter */
4519         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
4520
4521         /* resampler */
4522         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER,  player->ini.audioresampler_element, "audio resampler", TRUE, player);
4523
4524         if (player->set_mode.pcm_extraction) // pcm extraction only and no sound output
4525         {
4526                 if(player->audio_stream_render_cb_ex)
4527                 {
4528                         char *caps_str = NULL;
4529                         GstCaps* caps = NULL;
4530                         gchar *format = NULL;
4531
4532                         /* capsfilter */
4533                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4534
4535                         mm_attrs_get_string_by_name (player->attrs, "pcm_audioformat", &format );
4536
4537                         debug_log("contents : format: %s samplerate : %d pcm_channel: %d", format, player->pcm_samplerate, player->pcm_channel);
4538
4539                         caps = gst_caps_new_simple ("audio/x-raw",
4540                                         "format", G_TYPE_STRING, format,
4541                                         "rate", G_TYPE_INT, player->pcm_samplerate,
4542                                         "channels", G_TYPE_INT, player->pcm_channel,
4543                                         NULL);
4544                         caps_str = gst_caps_to_string(caps);
4545                         debug_log("new caps : %s\n", caps_str);
4546
4547                         g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
4548
4549                         /* clean */
4550                         gst_caps_unref( caps );
4551                         MMPLAYER_FREEIF( caps_str );
4552
4553                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
4554
4555                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
4556                         /* raw pad handling signal */
4557                         MMPLAYER_SIGNAL_CONNECT( player,
4558                                 (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
4559                                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
4560                                                                                                 G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
4561                 }
4562                 else
4563                 {
4564                         int dst_samplerate = 0;
4565                         int dst_channels = 0;
4566                         int dst_depth = 0;
4567                         char *caps_str = NULL;
4568                         GstCaps* caps = NULL;
4569
4570                         /* get conf. values */
4571                         mm_attrs_multiple_get(player->attrs,
4572                                                 NULL,
4573                                                 "pcm_extraction_samplerate", &dst_samplerate,
4574                                                 "pcm_extraction_channels", &dst_channels,
4575                                                 "pcm_extraction_depth", &dst_depth,
4576                                                 NULL);
4577
4578                         /* capsfilter */
4579                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4580                         caps = gst_caps_new_simple ("audio/x-raw",
4581                                         "rate", G_TYPE_INT, dst_samplerate,
4582                                         "channels", G_TYPE_INT, dst_channels,
4583                                         "depth", G_TYPE_INT, dst_depth,
4584                                         NULL);
4585                         caps_str = gst_caps_to_string(caps);
4586                         debug_log("new caps : %s\n", caps_str);
4587
4588                         g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
4589
4590                         /* clean */
4591                         gst_caps_unref( caps );
4592                         MMPLAYER_FREEIF( caps_str );
4593
4594                         /* fake sink */
4595                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
4596
4597                         /* set sync */
4598                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
4599                 }
4600         }
4601         else // normal playback
4602         {
4603                 //GstCaps* caps = NULL;
4604                 gint channels = 0;
4605
4606                 /* for logical volume control */
4607                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
4608                 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
4609
4610                 if (player->sound.mute)
4611                 {
4612                         debug_log("mute enabled\n");
4613                         g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
4614                 }
4615
4616 #if 0
4617                 /*capsfilter */
4618                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
4619                 caps = gst_caps_from_string( "audio/x-raw-int, "
4620                                         "endianness = (int) LITTLE_ENDIAN, "
4621                                         "signed = (boolean) true, "
4622                                         "width = (int) 16, "
4623                                         "depth = (int) 16" );
4624                 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
4625                 gst_caps_unref( caps );
4626 #endif
4627
4628                 /* chech if multi-chennels */
4629                 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)
4630                 {
4631                         GstPad *srcpad = NULL;
4632                         GstCaps *caps = NULL;
4633
4634                         if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src")))
4635                         {
4636                                 if ((caps = gst_pad_query_caps(srcpad, NULL)))
4637                                 {
4638                                         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
4639                                         GstStructure *str = gst_caps_get_structure(caps, 0);
4640                                         if (str)
4641                                                 gst_structure_get_int (str, "channels", &channels);
4642                                         gst_caps_unref(caps);
4643                                 }
4644                                 gst_object_unref(srcpad);
4645                         }
4646                 }
4647
4648                 /* audio effect element. if audio effect is enabled */
4649                 if ( (strcmp(player->ini.audioeffect_element, ""))
4650                         && (channels <= 2)
4651                         && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom))
4652                 {
4653                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.audioeffect_element, "audio effect filter", TRUE, player);
4654
4655                         debug_log("audio effect config. bypass = %d, effect type  = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
4656
4657                         if ( (!player->bypass_audio_effect)
4658                                 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom) )
4659                         {
4660                                 if ( MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type )
4661                                 {
4662                                         if (!_mmplayer_audio_effect_custom_apply(player))
4663                                         {
4664                                                 debug_msg("apply audio effect(custom) setting success\n");
4665                                         }
4666                                 }
4667                         }
4668
4669                         if ( (strcmp(player->ini.audioeffect_element_custom, ""))
4670                                 && (player->set_mode.rich_audio) )
4671                         {
4672                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.audioeffect_element_custom, "audio effect filter custom", TRUE, player);
4673                         }
4674                 }
4675                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
4676                 {
4677                         if (player->set_mode.rich_audio && channels <= 2)
4678                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VSP, "audiovsp", "x-speed", TRUE, player);
4679                 }
4680
4681                 /* create audio sink */
4682                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", link_audio_sink_now, player);
4683
4684                 /* qos on */
4685                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);     /* qos on */
4686                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
4687
4688                 if (player->videodec_linked && player->ini.use_system_clock)
4689                 {
4690                         debug_log("system clock will be used.\n");
4691                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE,  NULL);
4692                 }
4693
4694                 if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
4695                         __mmplayer_gst_set_audiosink_property(player, attrs);
4696         }
4697
4698         if (audiobin[MMPLAYER_A_SINK].gst)
4699         {
4700                 GstPad *sink_pad = NULL;
4701                 sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
4702                 MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4703                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
4704                 gst_object_unref (GST_OBJECT(sink_pad));
4705         }
4706
4707         __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
4708
4709         /* adding created elements to bin */
4710         debug_log("adding created elements to bin\n");
4711         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket ))
4712         {
4713                 debug_error("failed to add elements\n");
4714                 goto ERROR;
4715         }
4716
4717         /* linking elements in the bucket by added order. */
4718         debug_log("Linking elements in the bucket by added order.\n");
4719         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
4720         {
4721                 debug_error("failed to link elements\n");
4722                 goto ERROR;
4723         }
4724
4725         /* get first element's sinkpad for creating ghostpad */
4726         first_element = (MMPlayerGstElement *)element_bucket->data;
4727
4728         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
4729         if ( ! pad )
4730         {
4731                 debug_error("failed to get pad from first element of audiobin\n");
4732                 goto ERROR;
4733         }
4734
4735         ghostpad = gst_ghost_pad_new("sink", pad);
4736         if ( ! ghostpad )
4737         {
4738                 debug_error("failed to create ghostpad\n");
4739                 goto ERROR;
4740         }
4741
4742         if ( FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad) )
4743         {
4744                 debug_error("failed to add ghostpad to audiobin\n");
4745                 goto ERROR;
4746         }
4747
4748         player->gapless.audio_data_probe_id = gst_pad_add_probe(ghostpad, GST_PAD_PROBE_TYPE_BUFFER,
4749                         __mmplayer_audio_data_probe, player, NULL);
4750
4751         gst_object_unref(pad);
4752
4753         g_list_free(element_bucket);
4754
4755         mm_attrs_set_int_by_name(attrs, "content_audio_found", TRUE);
4756
4757         MMPLAYER_FLEAVE();
4758
4759         return MM_ERROR_NONE;
4760
4761 ERROR:
4762
4763         debug_log("ERROR : releasing audiobin\n");
4764
4765         if ( pad )
4766                 gst_object_unref(GST_OBJECT(pad));
4767
4768         if ( ghostpad )
4769                 gst_object_unref(GST_OBJECT(ghostpad));
4770
4771         g_list_free( element_bucket );
4772
4773         /* release element which are not added to bin */
4774         for ( i = 1; i < MMPLAYER_A_NUM; i++ )  /* NOTE : skip bin */
4775         {
4776                 if ( audiobin[i].gst )
4777                 {
4778                         GstObject* parent = NULL;
4779                         parent = gst_element_get_parent( audiobin[i].gst );
4780
4781                         if ( !parent )
4782                         {
4783                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
4784                                 audiobin[i].gst = NULL;
4785                         }
4786                         else
4787                         {
4788                                 gst_object_unref(GST_OBJECT(parent));
4789                         }
4790                 }
4791         }
4792
4793         /* release audiobin with it's childs */
4794         if ( audiobin[MMPLAYER_A_BIN].gst )
4795         {
4796                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
4797         }
4798
4799         MMPLAYER_FREEIF( audiobin );
4800
4801         player->pipeline->audiobin = NULL;
4802
4803         return MM_ERROR_PLAYER_INTERNAL;
4804 }
4805
4806 static GstPadProbeReturn
4807 __mmplayer_audio_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
4808 {
4809         mm_player_t* player = (mm_player_t*) u_data;
4810         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
4811         GstMapInfo probe_info = GST_MAP_INFO_INIT;
4812
4813         gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
4814
4815         if (player->audio_stream_cb && probe_info.size && probe_info.data)
4816                 player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
4817
4818         return GST_PAD_PROBE_OK;
4819 }
4820
4821 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
4822 {
4823     return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
4824 }
4825
4826 static GstPadProbeReturn
4827 __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
4828 {
4829         GstCaps *caps = NULL;
4830         MMPlayerVideoStreamDataType stream;
4831         MMVideoBuffer *video_buffer = NULL;
4832         GstMemory *dataBlock = NULL;
4833         GstMemory *metaBlock = NULL;
4834         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
4835         GstStructure *structure = NULL;
4836         const gchar *string_format = NULL;
4837         unsigned int fourcc = 0;
4838         mm_player_t* player = (mm_player_t*)user_data;
4839         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
4840
4841         return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
4842         return_val_if_fail(gst_buffer_n_memory(buffer)  , GST_PAD_PROBE_DROP);
4843
4844         caps = gst_pad_get_current_caps(pad);
4845         if (caps == NULL) {
4846                 debug_error( "Caps is NULL." );
4847                 return GST_PAD_PROBE_OK;
4848         }
4849
4850         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
4851
4852         /* clear stream data structure */
4853         memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
4854
4855         structure = gst_caps_get_structure( caps, 0 );
4856         gst_structure_get_int(structure, "width", &(stream.width));
4857         gst_structure_get_int(structure, "height", &(stream.height));
4858         string_format = gst_structure_get_string(structure, "format");
4859         if(string_format) {
4860                 fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
4861         }
4862         stream.format = util_get_pixtype(fourcc);
4863         gst_caps_unref( caps );
4864         caps = NULL;
4865
4866     /*
4867         debug_log( "Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
4868                         GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format );
4869     */
4870
4871         if (stream.width == 0 || stream.height == 0 || stream.format == MM_PIXEL_FORMAT_INVALID) {
4872                 debug_error("Wrong condition!!");
4873                 return TRUE;
4874         }
4875
4876         /* set size and timestamp */
4877         dataBlock = gst_buffer_peek_memory(buffer, 0);
4878         stream.length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
4879         stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano sec -> mili sec */
4880
4881         /* check zero-copy */
4882         if (player->set_mode.video_zc &&
4883                 player->set_mode.media_packet_video_stream &&
4884                 gst_buffer_n_memory(buffer) > 1) {
4885                 metaBlock = gst_buffer_peek_memory(buffer, 1);
4886                 gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
4887                 video_buffer = (MMVideoBuffer *)mapinfo.data;
4888         }
4889
4890         if (video_buffer) {
4891                 /* set tbm bo */
4892                 if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
4893                         /* copy pointer of tbm bo, stride, elevation */
4894                         memcpy(stream.bo, video_buffer->handle.bo,
4895                                         sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
4896                 }
4897                 else if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
4898                         memcpy(stream.data, video_buffer->data,
4899                                         sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
4900                 }
4901                 memcpy(stream.stride, video_buffer->stride_width,
4902                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
4903                 memcpy(stream.elevation, video_buffer->stride_height,
4904                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
4905                 /* set gst buffer */
4906                 stream.internal_buffer = buffer;
4907         } else {
4908                 tbm_bo_handle thandle;
4909                 int stride = ((stream.width + 3) & (~3));
4910                 int elevation = stream.height;
4911                 int size = stride * elevation * 3 / 2;
4912                 gboolean gst_ret;
4913                 gst_ret = gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
4914                 if(!gst_ret) {
4915                         debug_error("fail to gst_memory_map");
4916                         return GST_PAD_PROBE_OK;
4917                 }
4918
4919                 stream.stride[0] = stride;
4920                 stream.elevation[0] = elevation;
4921                 if(stream.format == MM_PIXEL_FORMAT_I420) {
4922                         stream.stride[1] = stream.stride[2] = stride / 2;
4923                         stream.elevation[1] = stream.elevation[2] = elevation / 2;
4924                 }
4925                 else {
4926                         debug_error("Not support format %d", stream.format);
4927                         gst_memory_unmap(dataBlock, &mapinfo);
4928                         return GST_PAD_PROBE_OK;
4929                 }
4930
4931                 stream.bo[0] = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
4932                 if(!stream.bo[0]) {
4933                         debug_error("Fail to tbm_bo_alloc!!");
4934                         gst_memory_unmap(dataBlock, &mapinfo);
4935                         return GST_PAD_PROBE_OK;
4936                 }
4937                 thandle = tbm_bo_map(stream.bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
4938                 if(thandle.ptr && mapinfo.data)
4939                         memcpy(thandle.ptr, mapinfo.data, size);
4940                 else
4941                         debug_error("data pointer is wrong. dest : %p, src : %p",
4942                                         thandle.ptr, mapinfo.data);
4943
4944                 tbm_bo_unmap(stream.bo[0]);
4945         }
4946
4947         if (player->video_stream_cb) {
4948                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
4949         }
4950
4951         if (metaBlock) {
4952                 gst_memory_unmap(metaBlock, &mapinfo);
4953         }else {
4954                 gst_memory_unmap(dataBlock, &mapinfo);
4955                 tbm_bo_unref(stream.bo[0]);
4956         }
4957
4958         return GST_PAD_PROBE_OK;
4959 }
4960
4961 static int
4962 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket, gboolean use_video_stream)
4963 {
4964         gchar* video_csc = "videoconvert"; // default colorspace converter
4965         GList* element_bucket = *bucket;
4966
4967         return_val_if_fail(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
4968
4969         MMPLAYER_FENTER();
4970
4971         if (!player->set_mode.media_packet_video_stream && use_video_stream)
4972         {
4973                 if (player->set_mode.video_zc && strlen(player->ini.videoconverter_element) > 0)
4974                 {
4975                         video_csc = player->ini.videoconverter_element;
4976                 }
4977
4978                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
4979                 debug_log("using video converter: %s", video_csc);
4980
4981                 if ( !player->set_mode.video_zc)
4982                 {
4983                         gint width = 0;         //width of video
4984                         gint height = 0;                //height of video
4985                         GstCaps* video_caps = NULL;
4986                         GstStructure *structure = NULL;
4987
4988                         /* rotator, scaler and capsfilter */
4989                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
4990                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "video scaler", TRUE, player);
4991                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CAPS, "capsfilter", "videocapsfilter", TRUE, player);
4992
4993                         /* get video stream caps parsed by demuxer */
4994
4995                         mm_attrs_get_int_by_name(player->attrs, "display_width", &width);
4996
4997                         if(width)
4998                                 structure = gst_structure_new("video/x-raw", "width", G_TYPE_INT, width, NULL);
4999
5000                         mm_attrs_get_int_by_name(player->attrs, "display_height", &height);
5001
5002                         if(structure && height) {
5003                                 gst_structure_set (structure, "height", G_TYPE_INT, height, NULL);
5004
5005                                 video_caps = gst_caps_new_full(structure, NULL);
5006                                 g_object_set (GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_CAPS].gst), "caps", video_caps, NULL );
5007                                 MMPLAYER_LOG_GST_CAPS_TYPE(video_caps);
5008                                 gst_caps_unref(video_caps);
5009                         }
5010                         else
5011                                 debug_error("fail to set capsfilter %p, width %d, height %d", structure, width, height);
5012
5013                         if(structure)
5014                                 gst_structure_free(structure);
5015
5016                 }
5017         }
5018         else
5019         {
5020                 MMDisplaySurfaceType surface_type = MM_DISPLAY_SURFACE_NULL;
5021                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", (int *)&surface_type);
5022
5023                 if (player->set_mode.video_zc)
5024                 {
5025                         if ( (surface_type == MM_DISPLAY_SURFACE_EVAS) && ( !strcmp(player->ini.videosink_element_evas, "evasimagesink")) )
5026                         {
5027                                 video_csc = player->ini.videoconverter_element;
5028                         }
5029                         else
5030                         {
5031                                 video_csc = "";
5032                         }
5033                 }
5034
5035                 if (video_csc && (strcmp(video_csc, "")))
5036                 {
5037                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5038                         debug_log("using video converter: %s", video_csc);
5039                 }
5040
5041                 /* set video rotator */
5042                 if ( !player->set_mode.video_zc )
5043                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5044
5045                 /* videoscaler */
5046                 #if !defined(__arm__)
5047                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "videoscaler", TRUE, player);
5048                 #endif
5049         }
5050
5051         *bucket = element_bucket;
5052         MMPLAYER_FLEAVE();
5053         return MM_ERROR_NONE;
5054
5055 ERROR:
5056         *bucket = NULL;
5057         MMPLAYER_FLEAVE();
5058         return MM_ERROR_PLAYER_INTERNAL;
5059 }
5060
5061 /**
5062  * This function is to create video pipeline.
5063  *
5064  * @param       player          [in]    handle of player
5065  *              caps            [in]    src caps of decoder
5066  *              surface_type    [in]    surface type for video rendering
5067  *
5068  * @return      This function returns zero on success.
5069  * @remark
5070  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5071  */
5072 /**
5073   * VIDEO PIPELINE
5074   * - x surface (arm/x86) : xvimagesink
5075   * - evas surface  (arm) : evaspixmapsink
5076   *                         fimcconvert ! evasimagesink
5077   * - evas surface  (x86) : videoconvertor ! videoflip ! evasimagesink
5078   */
5079 static int
5080 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5081 {
5082         GstPad *pad = NULL;
5083         MMHandleType attrs;
5084         GList*element_bucket = NULL;
5085         MMPlayerGstElement* first_element = NULL;
5086         MMPlayerGstElement* videobin = NULL;
5087         gchar *videosink_element = NULL;
5088
5089         MMPLAYER_FENTER();
5090
5091         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5092
5093         /* alloc handles */
5094         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5095         if ( !videobin )
5096         {
5097                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5098         }
5099
5100         player->pipeline->videobin = videobin;
5101
5102         attrs = MMPLAYER_GET_ATTRS(player);
5103         if ( !attrs )
5104         {
5105                 debug_error("cannot get content attribute");
5106                 return MM_ERROR_PLAYER_INTERNAL;
5107         }
5108
5109         /* create bin */
5110         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
5111         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
5112         if ( !videobin[MMPLAYER_V_BIN].gst )
5113         {
5114                 debug_error("failed to create videobin");
5115                 goto ERROR;
5116         }
5117
5118         if( player->use_video_stream ) // video stream callback, so send raw video data to application
5119         {
5120                 debug_log("using memsink\n");
5121
5122                 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, TRUE) != MM_ERROR_NONE)
5123                         goto ERROR;
5124
5125                 /* finally, create video sink. output will be BGRA8888. */
5126                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, "avsysmemsink", "videosink", TRUE, player);
5127
5128                 MMPLAYER_SIGNAL_CONNECT( player,
5129                                                                          videobin[MMPLAYER_V_SINK].gst,
5130                                                                          MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5131                                                                          "video-stream",
5132                                                                          G_CALLBACK(__mmplayer_videostream_cb),
5133                                                                          player );
5134         }
5135         else // render video data using sink plugin like xvimagesink
5136         {
5137                 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, FALSE) != MM_ERROR_NONE)
5138                         goto ERROR;
5139
5140                 /* set video sink */
5141                 switch (surface_type)
5142                 {
5143                         case MM_DISPLAY_SURFACE_X:
5144                                 if (strlen(player->ini.videosink_element_x) > 0)
5145                                         videosink_element = player->ini.videosink_element_x;
5146                                 else
5147                                         goto ERROR;
5148                                 break;
5149                         case MM_DISPLAY_SURFACE_EVAS:
5150                                 if (strlen(player->ini.videosink_element_evas) > 0)
5151                                         videosink_element = player->ini.videosink_element_evas;
5152                                 else
5153                                         goto ERROR;
5154                                 break;
5155                         case MM_DISPLAY_SURFACE_X_EXT:
5156                         {
5157                                 void *pixmap_id_cb = NULL;
5158                                 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
5159                                 if (pixmap_id_cb) /* this is used for the videoTextue(canvasTexture) overlay */
5160                                 {
5161                                         videosink_element = player->ini.videosink_element_x;
5162                                 }
5163                                 else
5164                                 {
5165                                         debug_error("something wrong.. callback function for getting pixmap id is null");
5166                                         goto ERROR;
5167                                 }
5168                                 break;
5169                         }
5170                         case MM_DISPLAY_SURFACE_NULL:
5171                                 if (strlen(player->ini.videosink_element_fake) > 0)
5172                                         videosink_element = player->ini.videosink_element_fake;
5173                                 else
5174                                         goto ERROR;
5175                                 break;
5176                         case MM_DISPLAY_SURFACE_REMOTE:
5177                                 if (strlen(player->ini.videosink_element_remote) > 0)
5178                                         videosink_element = player->ini.videosink_element_remote;
5179                                 else
5180                                         goto ERROR;
5181                                 break;
5182                         default:
5183                                 debug_error("unidentified surface type");
5184                                 goto ERROR;
5185                 }
5186
5187                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, videosink_element, TRUE, player);
5188                 debug_log("selected videosink name: %s", videosink_element);
5189
5190                 /* additional setting for sink plug-in */
5191                 switch (surface_type) {
5192                         case MM_DISPLAY_SURFACE_X_EXT:
5193                                 MMPLAYER_SIGNAL_CONNECT( player,
5194                                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5195                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5196                                                                                 "frame-render-error",
5197                                                                                 G_CALLBACK(__mmplayer_videoframe_render_error_cb),
5198                                                                                 player );
5199                                 debug_log("videoTexture usage, connect a signal handler for pixmap rendering error");
5200                                 break;
5201                         case MM_DISPLAY_SURFACE_REMOTE:
5202                         {
5203                                 char *stream_path = NULL;
5204                                 /* viceo_zc is the result of check ST12/SN12 */
5205                                 bool use_tbm = player->set_mode.video_zc;
5206                                 int attr_ret = mm_attrs_get_string_by_name (
5207                                                 attrs, "shm_stream_path", &stream_path );
5208                                 if(attr_ret == MM_ERROR_NONE && stream_path) {
5209                                         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5210                                                         "socket-path", stream_path,
5211                                                         "wait-for-connection", FALSE,
5212                                                         "sync", TRUE,
5213                                                         "perms", 0777,
5214                                                         "use-tbm", use_tbm,
5215                                                         NULL);
5216                                         debug_log("set path \"%s\" for shmsink", stream_path);
5217                                 } else {
5218                                         debug_error("Not set attribute of shm_stream_path");
5219                                         goto ERROR;
5220                                 }
5221                                 break;
5222                         }
5223                         default:
5224                                 break;
5225                 }
5226         }
5227
5228         if (_mmplayer_update_video_param(player) != MM_ERROR_NONE)
5229                 goto ERROR;
5230
5231         if (videobin[MMPLAYER_V_SINK].gst)
5232         {
5233                 GstPad *sink_pad = NULL;
5234                 sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
5235                 if (sink_pad)
5236                 {
5237                         MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5238                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
5239                         gst_object_unref (GST_OBJECT(sink_pad));
5240                 }
5241                 else
5242                 {
5243                         debug_warning("failed to get sink pad from videosink\n");
5244                 }
5245         }
5246
5247         /* store it as it's sink element */
5248         __mmplayer_add_sink( player, videobin[MMPLAYER_V_SINK].gst );
5249
5250         /* adding created elements to bin */
5251         if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket) )
5252         {
5253                 debug_error("failed to add elements\n");
5254                 goto ERROR;
5255         }
5256
5257         /* Linking elements in the bucket by added order */
5258         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5259         {
5260                 debug_error("failed to link elements\n");
5261                 goto ERROR;
5262         }
5263
5264         /* get first element's sinkpad for creating ghostpad */
5265         first_element = (MMPlayerGstElement *)element_bucket->data;
5266         if ( !first_element )
5267         {
5268                 debug_error("failed to get first element from bucket\n");
5269                 goto ERROR;
5270         }
5271
5272         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5273         if ( !pad )
5274         {
5275                 debug_error("failed to get pad from first element\n");
5276                 goto ERROR;
5277         }
5278
5279         /* create ghostpad */
5280         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
5281         if ( FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
5282         {
5283                 debug_error("failed to add ghostpad to videobin\n");
5284                 goto ERROR;
5285         }
5286         gst_object_unref(pad);
5287
5288         /* done. free allocated variables */
5289         g_list_free(element_bucket);
5290
5291         mm_attrs_set_int_by_name(attrs, "content_video_found", TRUE);
5292
5293         if(surface_type == MM_DISPLAY_SURFACE_REMOTE &&
5294                         MMPLAYER_IS_HTTP_PD(player) )
5295         {
5296                 MMMessageParamType msg = {0, };
5297                 msg.data = gst_caps_to_string(caps);
5298                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_VIDEO_BIN_CREATED, &msg );
5299         }
5300
5301         MMPLAYER_FLEAVE();
5302
5303         return MM_ERROR_NONE;
5304
5305 ERROR:
5306         debug_error("ERROR : releasing videobin\n");
5307
5308         g_list_free( element_bucket );
5309
5310         if (pad)
5311                 gst_object_unref(GST_OBJECT(pad));
5312
5313         /* release videobin with it's childs */
5314         if ( videobin[MMPLAYER_V_BIN].gst )
5315         {
5316                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
5317         }
5318
5319
5320         MMPLAYER_FREEIF( videobin );
5321
5322         player->pipeline->videobin = NULL;
5323
5324         return MM_ERROR_PLAYER_INTERNAL;
5325 }
5326
5327 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
5328 {
5329         GList *element_bucket = NULL;
5330         MMPlayerGstElement *textbin = player->pipeline->textbin;
5331
5332         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", TRUE, player);
5333         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", TRUE, player);
5334         g_object_set (G_OBJECT (textbin[MMPLAYER_T_IDENTITY].gst),
5335                                                         "signal-handoffs", FALSE,
5336                                                         NULL);
5337
5338         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
5339         MMPLAYER_SIGNAL_CONNECT( player,
5340                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
5341                                                         MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
5342                                                         "handoff",
5343                                                         G_CALLBACK(__mmplayer_update_subtitle),
5344                                                         (gpointer)player );
5345
5346         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
5347         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
5348         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
5349
5350         if (!player->play_subtitle)
5351         {
5352                 debug_log ("add textbin sink as sink element of whole pipeline.\n");
5353                 __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
5354         }
5355
5356         /* adding created elements to bin */
5357         debug_log("adding created elements to bin\n");
5358         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
5359         {
5360                 debug_error("failed to add elements\n");
5361                 goto ERROR;
5362         }
5363
5364         /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
5365         GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
5366         GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
5367
5368         /* linking elements in the bucket by added order. */
5369         debug_log("Linking elements in the bucket by added order.\n");
5370         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5371         {
5372                 debug_error("failed to link elements\n");
5373                 goto ERROR;
5374         }
5375
5376         /* done. free allocated variables */
5377         g_list_free(element_bucket);
5378
5379         if (textbin[MMPLAYER_T_QUEUE].gst)
5380         {
5381                 GstPad *pad = NULL;
5382                 GstPad *ghostpad = NULL;
5383
5384                 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_QUEUE].gst), "sink");
5385                 if (!pad)
5386                 {
5387                         debug_error("failed to get video pad of textbin\n");
5388                         return MM_ERROR_PLAYER_INTERNAL;
5389                 }
5390
5391                 ghostpad = gst_ghost_pad_new("text_sink", pad);
5392                 gst_object_unref(pad);
5393
5394                 if (!ghostpad)
5395                 {
5396                         debug_error("failed to create ghostpad of textbin\n");
5397                         goto ERROR;
5398                 }
5399
5400                 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad))
5401                 {
5402                         debug_error("failed to add ghostpad to textbin\n");
5403                         goto ERROR;
5404                 }
5405         }
5406
5407         return MM_ERROR_NONE;
5408
5409 ERROR:
5410         g_list_free(element_bucket);
5411
5412         return MM_ERROR_PLAYER_INTERNAL;
5413 }
5414
5415 static int __mmplayer_gst_create_text_pipeline(mm_player_t* player)
5416 {
5417         MMPlayerGstElement *textbin = NULL;
5418         GList *element_bucket = NULL;
5419         gint i = 0;
5420
5421         MMPLAYER_FENTER();
5422
5423         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5424
5425         /* alloc handles */
5426         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
5427         if ( ! textbin )
5428         {
5429                 debug_error("failed to allocate memory for textbin\n");
5430                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5431         }
5432
5433         /* create bin */
5434         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
5435         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
5436         if ( !textbin[MMPLAYER_T_BIN].gst )
5437         {
5438                 debug_error("failed to create textbin\n");
5439                 goto ERROR;
5440         }
5441
5442         /* take it */
5443         player->pipeline->textbin = textbin;
5444
5445         /* fakesink */
5446         if (player->use_textoverlay)
5447         {
5448                 debug_log ("use textoverlay for displaying \n");
5449
5450                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_QUEUE, "queue", "text_t_queue", textbin[MMPLAYER_T_BIN].gst, player);
5451
5452                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_QUEUE, "queue", "text_v_queue", textbin[MMPLAYER_T_BIN].gst, player);
5453
5454                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_CONVERTER, "fimcconvert", "text_v_converter", textbin[MMPLAYER_T_BIN].gst, player);
5455
5456                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_OVERLAY, "textoverlay", "text_overlay", textbin[MMPLAYER_T_BIN].gst, player);
5457
5458                 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_QUEUE].gst, "src", textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "sink"))
5459                 {
5460                         debug_error("failed to link queue and converter\n");
5461                         goto ERROR;
5462                 }
5463
5464                 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "video_sink"))
5465                 {
5466                         debug_error("failed to link queue and textoverlay\n");
5467                         goto ERROR;
5468                 }
5469
5470                 if (!gst_element_link_pads (textbin[MMPLAYER_T_QUEUE].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "text_sink"))
5471                 {
5472                         debug_error("failed to link queue and textoverlay\n");
5473                         goto ERROR;
5474                 }
5475         }
5476         else
5477         {
5478                 int surface_type = 0;
5479
5480                 debug_log ("use subtitle message for displaying \n");
5481
5482                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
5483
5484                 switch(surface_type)
5485                 {
5486                         case MM_DISPLAY_SURFACE_X:
5487                         case MM_DISPLAY_SURFACE_EVAS:
5488                         case MM_DISPLAY_SURFACE_GL:
5489                         case MM_DISPLAY_SURFACE_NULL:
5490                         case MM_DISPLAY_SURFACE_X_EXT:
5491                         case MM_DISPLAY_SURFACE_REMOTE:
5492                                 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE)
5493                                 {
5494                                         debug_error("failed to make plain text elements\n");
5495                                         goto ERROR;
5496                                 }
5497                                 break;
5498
5499                         default:
5500                                 break;
5501                 }
5502         }
5503
5504         MMPLAYER_FLEAVE();
5505
5506         return MM_ERROR_NONE;
5507
5508 ERROR:
5509
5510         debug_log("ERROR : releasing textbin\n");
5511
5512         g_list_free( element_bucket );
5513
5514         /* release element which are not added to bin */
5515         for ( i = 1; i < MMPLAYER_T_NUM; i++ )  /* NOTE : skip bin */
5516         {
5517                 if ( textbin[i].gst )
5518                 {
5519                         GstObject* parent = NULL;
5520                         parent = gst_element_get_parent( textbin[i].gst );
5521
5522                         if ( !parent )
5523                         {
5524                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
5525                                 textbin[i].gst = NULL;
5526                         }
5527                         else
5528                         {
5529                                 gst_object_unref(GST_OBJECT(parent));
5530                         }
5531                 }
5532         }
5533
5534         /* release textbin with it's childs */
5535         if ( textbin[MMPLAYER_T_BIN].gst )
5536         {
5537                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
5538         }
5539
5540         MMPLAYER_FREEIF( textbin );
5541
5542         player->pipeline->textbin = NULL;
5543
5544         return MM_ERROR_PLAYER_INTERNAL;
5545 }
5546
5547
5548 static int
5549 __mmplayer_gst_create_subtitle_src(mm_player_t* player)
5550 {
5551         MMPlayerGstElement* mainbin = NULL;
5552         MMHandleType attrs = 0;
5553         GstElement *subsrc = NULL;
5554         GstElement *subparse = NULL;
5555         gchar *subtitle_uri =NULL;
5556         const gchar *charset = NULL;
5557         GstPad *pad = NULL;
5558
5559         MMPLAYER_FENTER();
5560
5561         /* get mainbin */
5562         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5563
5564         mainbin = player->pipeline->mainbin;
5565
5566         attrs = MMPLAYER_GET_ATTRS(player);
5567         if ( !attrs )
5568         {
5569                 debug_error("cannot get content attribute\n");
5570                 return MM_ERROR_PLAYER_INTERNAL;
5571         }
5572
5573         mm_attrs_get_string_by_name ( attrs, "subtitle_uri", &subtitle_uri );
5574         if ( !subtitle_uri || strlen(subtitle_uri) < 1)
5575         {
5576                 debug_error("subtitle uri is not proper filepath.\n");
5577                 return MM_ERROR_PLAYER_INVALID_URI;
5578         }
5579         debug_log("subtitle file path is [%s].\n", subtitle_uri);
5580
5581
5582         /* create the subtitle source */
5583         subsrc = gst_element_factory_make("filesrc", "subtitle_source");
5584         if ( !subsrc )
5585         {
5586                 debug_error ( "failed to create filesrc element\n" );
5587                 goto ERROR;
5588         }
5589         g_object_set(G_OBJECT (subsrc), "location", subtitle_uri, NULL);
5590
5591         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
5592         mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
5593
5594         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc))
5595         {
5596                 debug_warning("failed to add queue\n");
5597                 goto ERROR;
5598         }
5599
5600         /* subparse */
5601         subparse = gst_element_factory_make("subparse", "subtitle_parser");
5602         if ( !subparse )
5603         {
5604                 debug_error ( "failed to create subparse element\n" );
5605                 goto ERROR;
5606         }
5607
5608         charset = util_get_charset(subtitle_uri);
5609         if (charset)
5610         {
5611                 debug_log ("detected charset is %s\n", charset );
5612                 g_object_set (G_OBJECT (subparse), "subtitle-encoding", charset, NULL);
5613         }
5614
5615         mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE;
5616         mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
5617
5618         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse))
5619         {
5620                 debug_warning("failed to add subparse\n");
5621                 goto ERROR;
5622         }
5623
5624         if (!gst_element_link_pads (subsrc, "src", subparse, "sink"))
5625         {
5626                 debug_warning("failed to link subsrc and subparse\n");
5627                 goto ERROR;
5628         }
5629
5630         player->play_subtitle = TRUE;
5631         player->adjust_subtitle_pos = 0;
5632
5633         debug_log ("play subtitle using subtitle file\n");
5634
5635         if (player->pipeline->textbin == NULL)
5636         {
5637                 if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
5638                 {
5639                         debug_error("failed to create textbin. continuing without text\n");
5640                         goto ERROR;
5641                 }
5642
5643                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst)))
5644                 {
5645                         debug_warning("failed to add textbin\n");
5646                         goto ERROR;
5647                 }
5648
5649                 debug_log ("link text input selector and textbin ghost pad");
5650
5651                 player->textsink_linked = 1;
5652                 player->external_text_idx = 0;
5653                 debug_msg("player->textsink_linked set to 1\n");
5654         }
5655         else
5656         {
5657                 debug_log("text bin has been created. reuse it.");
5658                 player->external_text_idx = 1;
5659         }
5660
5661         if (!gst_element_link_pads (subparse, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink"))
5662         {
5663                 debug_warning("failed to link subparse and textbin\n");
5664                 goto ERROR;
5665         }
5666
5667         pad = gst_element_get_static_pad (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
5668
5669         if (!pad)
5670         {
5671                 debug_error("failed to get sink pad from textsink to probe data");
5672                 return MM_ERROR_PLAYER_INTERNAL;
5673         }
5674
5675         gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
5676                                 __mmplayer_subtitle_adjust_position_probe, player, NULL);
5677
5678         gst_object_unref(pad);
5679         pad=NULL;
5680
5681         /* create dot. for debugging */
5682         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-with-subtitle" );
5683         MMPLAYER_FLEAVE();
5684
5685         return MM_ERROR_NONE;
5686
5687 ERROR:
5688         player->textsink_linked = 0;
5689         return MM_ERROR_PLAYER_INTERNAL;
5690 }
5691
5692 gboolean
5693 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5694 {
5695         mm_player_t* player = (mm_player_t*) data;
5696         MMMessageParamType msg = {0, };
5697         GstClockTime duration = 0;
5698         gpointer text = NULL;
5699         guint text_size = 0;
5700         gboolean ret = TRUE;
5701         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5702
5703         MMPLAYER_FENTER();
5704
5705         return_val_if_fail ( player, FALSE );
5706         return_val_if_fail ( buffer, FALSE );
5707
5708         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
5709         text = g_memdup(mapinfo.data, mapinfo.size);
5710         text_size = mapinfo.size;
5711         duration = GST_BUFFER_DURATION(buffer);
5712
5713
5714         if ( player->set_mode.subtitle_off )
5715         {
5716                 debug_log("subtitle is OFF.\n" );
5717                 return TRUE;
5718         }
5719
5720         if ( !text || (text_size == 0))
5721         {
5722                 debug_log("There is no subtitle to be displayed.\n" );
5723                 return TRUE;
5724         }
5725
5726         msg.data = (void *) text;
5727         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
5728
5729         debug_log("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
5730
5731         MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
5732         gst_buffer_unmap(buffer, &mapinfo);
5733
5734         MMPLAYER_FLEAVE();
5735
5736         return ret;
5737 }
5738
5739 static GstPadProbeReturn
5740 __mmplayer_subtitle_adjust_position_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
5741
5742 {
5743         mm_player_t *player = (mm_player_t *) u_data;
5744         GstClockTime cur_timestamp = 0;
5745         gint64 adjusted_timestamp = 0;
5746         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
5747
5748         return_val_if_fail ( player, FALSE );
5749
5750         if ( player->set_mode.subtitle_off )
5751         {
5752                 debug_log("subtitle is OFF.\n" );
5753                 return TRUE;
5754         }
5755
5756         if (player->adjust_subtitle_pos == 0 )
5757         {
5758                 debug_log("nothing to do");
5759                 return TRUE;
5760         }
5761
5762         cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
5763         adjusted_timestamp = (gint64) cur_timestamp + ((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
5764
5765         if ( adjusted_timestamp < 0)
5766         {
5767                 debug_log("adjusted_timestamp under zero");
5768                 MMPLAYER_FLEAVE();
5769                 return FALSE;
5770         }
5771
5772         GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
5773         debug_log("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
5774                                 GST_TIME_ARGS(cur_timestamp),
5775                                 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
5776
5777         return GST_PAD_PROBE_OK;
5778 }
5779 static int      __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
5780 {
5781         MMPLAYER_FENTER();
5782
5783         /* check player and subtitlebin are created */
5784         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5785         return_val_if_fail ( player->play_subtitle, MM_ERROR_NOT_SUPPORT_API );
5786
5787         if (position == 0)
5788         {
5789                 debug_log ("nothing to do\n");
5790                 MMPLAYER_FLEAVE();
5791                 return MM_ERROR_NONE;
5792         }
5793
5794         switch (format)
5795         {
5796                 case MM_PLAYER_POS_FORMAT_TIME:
5797                 {
5798                         /* check current postion */
5799                         player->adjust_subtitle_pos = position;
5800
5801                         debug_log("save adjust_subtitle_pos in player") ;
5802                 }
5803                 break;
5804
5805                 default:
5806                 {
5807                         debug_warning("invalid format.\n");
5808                         MMPLAYER_FLEAVE();
5809                         return MM_ERROR_INVALID_ARGUMENT;
5810                 }
5811         }
5812
5813         MMPLAYER_FLEAVE();
5814
5815         return MM_ERROR_NONE;
5816 }
5817 static int __gst_adjust_video_position(mm_player_t* player, int offset)
5818 {
5819         MMPLAYER_FENTER();
5820         debug_log("adjusting video_pos in player") ;
5821         int current_pos = 0;
5822         /* check player and videobin are created */
5823         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5824         if ( !player->pipeline->videobin ||
5825                         !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
5826         {
5827                 debug_log("no video pipeline or sink is there");
5828                 return MM_ERROR_PLAYER_INVALID_STATE ;
5829         }
5830         if (offset == 0)
5831         {
5832                 debug_log ("nothing to do\n");
5833                 MMPLAYER_FLEAVE();
5834                 return MM_ERROR_NONE;
5835         }
5836         if(__gst_get_position ( player, MM_PLAYER_POS_FORMAT_TIME, (unsigned long*)&current_pos ) != MM_ERROR_NONE )
5837         {
5838                 debug_log("failed to get current position");
5839                 return MM_ERROR_PLAYER_INTERNAL;
5840         }
5841         if ( (current_pos - offset ) < GST_TIME_AS_MSECONDS(player->duration) )
5842         {
5843                 debug_log("enter video delay is valid");
5844         }
5845         else {
5846                 debug_log("enter video delay is crossing content boundary");
5847                 return MM_ERROR_INVALID_ARGUMENT ;
5848         }
5849         g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst),"ts-offset",((gint64) offset * G_GINT64_CONSTANT(1000000)),NULL);
5850         debug_log("video delay has been done");
5851         MMPLAYER_FLEAVE();
5852
5853         return MM_ERROR_NONE;
5854 }
5855
5856 static void
5857 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data) // @
5858 {
5859         GstElement *appsrc = element;
5860         tBuffer *buf = (tBuffer *)user_data;
5861         GstBuffer *buffer = NULL;
5862         GstFlowReturn ret = GST_FLOW_OK;
5863         gint len = size;
5864
5865         return_if_fail ( element );
5866         return_if_fail ( buf );
5867
5868         buffer = gst_buffer_new ();
5869
5870         if (buf->offset >= buf->len)
5871         {
5872                 debug_log("call eos appsrc\n");
5873                 g_signal_emit_by_name (appsrc, "end-of-stream", &ret);
5874                 return;
5875         }
5876
5877         if ( buf->len - buf->offset < size)
5878         {
5879                 len = buf->len - buf->offset + buf->offset;
5880         }
5881
5882         gst_buffer_insert_memory(buffer, -1, gst_memory_new_wrapped(0, (guint8 *)(buf->buf + buf->offset), len, 0, len, (guint8*)(buf->buf + buf->offset), g_free));
5883         GST_BUFFER_OFFSET(buffer) = buf->offset;
5884         GST_BUFFER_OFFSET_END(buffer) = buf->offset + len;
5885
5886         //debug_log("feed buffer %p, offset %u-%u length %u\n", buffer, buf->offset, buf->len,len);
5887         g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
5888
5889         buf->offset += len;
5890 }
5891
5892 static gboolean
5893 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data) // @
5894 {
5895         tBuffer *buf = (tBuffer *)user_data;
5896
5897         return_val_if_fail ( buf, FALSE );
5898
5899         buf->offset  = (int)size;
5900
5901         return TRUE;
5902 }
5903
5904 static void
5905 __gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data) // @
5906 {
5907         mm_player_t *player  = (mm_player_t*)user_data;
5908         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
5909
5910         return_if_fail ( player );
5911
5912         debug_msg("app-src: feed data\n");
5913
5914         if (player->media_stream_buffer_status_cb[type])
5915                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
5916 }
5917
5918 static gboolean
5919 __gst_appsrc_seek_data(GstElement *element, guint64 offset, gpointer user_data) // @
5920 {
5921         mm_player_t *player  = (mm_player_t*)user_data;
5922         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
5923
5924         return_val_if_fail ( player, FALSE );
5925
5926         debug_msg("app-src: seek data\n");
5927
5928         if(player->media_stream_seek_data_cb[type])
5929                 player->media_stream_seek_data_cb[type](type, offset, player->buffer_cb_user_param);
5930
5931         return TRUE;
5932 }
5933
5934
5935 static gboolean
5936 __gst_appsrc_enough_data(GstElement *element, gpointer user_data) // @
5937 {
5938         mm_player_t *player  = (mm_player_t*)user_data;
5939         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
5940
5941         return_val_if_fail ( player, FALSE );
5942
5943         debug_msg("app-src: enough data:%p\n", player->media_stream_buffer_status_cb[type]);
5944
5945         if (player->media_stream_buffer_status_cb[type])
5946                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
5947
5948         return TRUE;
5949 }
5950
5951 int
5952 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
5953 {
5954         mm_player_t* player = (mm_player_t*)hplayer;
5955         GstBuffer *buffer = NULL;
5956         GstFlowReturn gst_ret = GST_FLOW_OK;
5957         int ret = MM_ERROR_NONE;
5958 //      gint len = size;
5959
5960         MMPLAYER_FENTER();
5961
5962         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5963
5964         /* check current state */
5965 //      MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
5966
5967
5968         /* NOTE : we should check and create pipeline again if not created as we destroy
5969          * whole pipeline when stopping in streamming playback
5970          */
5971         if ( ! player->pipeline )
5972         {
5973                 if ( MM_ERROR_NONE != __gst_realize( player ) )
5974                 {
5975                         debug_error("failed to realize before starting. only in streamming\n");
5976                         return MM_ERROR_PLAYER_INTERNAL;
5977                 }
5978         }
5979
5980         debug_msg("app-src: pushing data\n");
5981
5982         if ( buf == NULL )
5983         {
5984                 debug_error("buf is null\n");
5985                 return MM_ERROR_NONE;
5986         }
5987
5988         buffer = gst_buffer_new ();
5989
5990         if (size <= 0)
5991         {
5992                 debug_log("call eos appsrc\n");
5993                 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
5994                 return MM_ERROR_NONE;
5995         }
5996
5997         //gst_buffer_insert_memory(buffer, -1, gst_memory_new_wrapped(0, (guint8 *)(buf->buf + buf->offset), len, 0, len, (guint8*)(buf->buf + buf->offset), g_free));
5998
5999         debug_log("feed buffer %p, length %u\n", buf, size);
6000         g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
6001
6002         MMPLAYER_FLEAVE();
6003
6004         return ret;
6005 }
6006
6007 static GstBusSyncReply
6008 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
6009 {
6010         mm_player_t *player = (mm_player_t *)data;
6011         GstBusSyncReply reply = GST_BUS_DROP;
6012
6013         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
6014         {
6015                 debug_error("player pipeline handle is null");
6016                 return GST_BUS_PASS;
6017         }
6018
6019         if (!__mmplayer_check_useful_message(player, message))
6020         {
6021                 gst_message_unref (message);
6022                 return GST_BUS_DROP;
6023         }
6024
6025         switch (GST_MESSAGE_TYPE (message))
6026         {
6027                 case GST_MESSAGE_STATE_CHANGED:
6028                         /* post directly for fast launch */
6029                         if (player->sync_handler) {
6030                                 __mmplayer_gst_callback(NULL, message, player);
6031                                 reply = GST_BUS_DROP;
6032                         }
6033                         else {
6034                                 reply = GST_BUS_PASS;
6035                         }
6036                         break;
6037                 case GST_MESSAGE_TAG:
6038                         __mmplayer_gst_extract_tag_from_msg(player, message);
6039
6040                         #if 0 // debug
6041                         {
6042                                 GstTagList *tags = NULL;
6043
6044                                 gst_message_parse_tag (message, &tags);
6045                                 if (tags) {
6046                                         debug_error("TAGS received from element \"%s\".\n",
6047                                         GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
6048
6049                                         gst_tag_list_foreach (tags, print_tag, NULL);
6050                                         gst_tag_list_free (tags);
6051                                         tags = NULL;
6052                                 }
6053                                 break;
6054                         }
6055                         #endif
6056                         break;
6057
6058                 case GST_MESSAGE_DURATION_CHANGED:
6059                         __mmplayer_gst_handle_duration(player, message);
6060                         break;
6061                 case GST_MESSAGE_ASYNC_DONE:
6062                         /* NOTE:Don't call gst_callback directly
6063                          * because previous frame can be showed even though this message is received for seek.
6064                          */
6065                 default:
6066                         reply = GST_BUS_PASS;
6067                         break;
6068         }
6069
6070         if (reply == GST_BUS_DROP)
6071                 gst_message_unref (message);
6072
6073         return reply;
6074 }
6075
6076 static gboolean
6077 __mmplayer_gst_create_decoder ( mm_player_t *player,
6078                                                                 MMPlayerTrackType track,
6079                                                                 GstPad* srcpad,
6080                                                                 enum MainElementID elemId,
6081                                                                 const gchar* name)
6082 {
6083         gboolean ret = TRUE;
6084         GstPad *sinkpad = NULL;
6085
6086         MMPLAYER_FENTER();
6087
6088         return_val_if_fail( player &&
6089                                                 player->pipeline &&
6090                                                 player->pipeline->mainbin, FALSE);
6091         return_val_if_fail((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE);
6092         return_val_if_fail(srcpad, FALSE);
6093         return_val_if_fail((player->pipeline->mainbin[elemId].gst == NULL), FALSE);
6094
6095         GstElement *decodebin = NULL;
6096         GstCaps *dec_caps = NULL;
6097
6098         /* create decodebin */
6099         decodebin = gst_element_factory_make("decodebin", name);
6100
6101         if (!decodebin)
6102         {
6103                 debug_error("error : fail to create decodebin for %d decoder\n", track);
6104                 ret = FALSE;
6105                 goto ERROR;
6106         }
6107
6108         /* raw pad handling signal */
6109         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6110                                                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
6111
6112         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
6113         before looking for any elements that can handle that stream.*/
6114         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
6115                                                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
6116
6117         /* This signal is emitted when a element is added to the bin.*/
6118         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
6119                                                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
6120
6121         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), decodebin))
6122         {
6123                 debug_error("failed to add new decodebin\n");
6124                 ret = FALSE;
6125                 goto ERROR;
6126         }
6127
6128         dec_caps = gst_pad_query_caps (srcpad, NULL);
6129         if (dec_caps)
6130         {
6131                 //debug_log ("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
6132                 g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
6133                 gst_caps_unref(dec_caps);
6134         }
6135
6136         player->pipeline->mainbin[elemId].id = elemId;
6137         player->pipeline->mainbin[elemId].gst = decodebin;
6138
6139         sinkpad = gst_element_get_static_pad (decodebin, "sink");
6140
6141         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
6142         {
6143                 debug_warning ("failed to link [%s:%s] to decoder\n", GST_DEBUG_PAD_NAME(srcpad));
6144                 gst_object_unref (GST_OBJECT(decodebin));
6145         }
6146
6147         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (decodebin))
6148         {
6149                 debug_error("failed to sync second level decodebin state with parent\n");
6150         }
6151
6152         debug_log("Total num of %d tracks = %d \n", track, player->selector[track].total_track_num);
6153
6154 ERROR:
6155         if (sinkpad)
6156         {
6157                 gst_object_unref ( GST_OBJECT(sinkpad) );
6158                 sinkpad = NULL;
6159         }
6160         MMPLAYER_FLEAVE();
6161
6162         return ret;
6163 }
6164
6165 /**
6166  * This function is to create  audio or video pipeline for playing.
6167  *
6168  * @param       player          [in]    handle of player
6169  *
6170  * @return      This function returns zero on success.
6171  * @remark
6172  * @see
6173  */
6174 static int
6175 __mmplayer_gst_create_pipeline(mm_player_t* player) // @
6176 {
6177         GstBus  *bus = NULL;
6178         MMPlayerGstElement *mainbin = NULL;
6179         MMHandleType attrs = 0;
6180         GstElement* element = NULL;
6181         GstElement* elem_src_audio = NULL;
6182         GstElement* elem_src_subtitle = NULL;
6183         GstElement* es_video_queue = NULL;
6184         GstElement* es_audio_queue = NULL;
6185         GstElement* es_subtitle_queue = NULL;
6186         GList* element_bucket = NULL;
6187         gboolean need_state_holder = TRUE;
6188         gint i = 0;
6189 #ifdef SW_CODEC_ONLY
6190         int surface_type = 0;
6191 #endif
6192         MMPLAYER_FENTER();
6193
6194         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6195
6196         /* get profile attribute */
6197         attrs = MMPLAYER_GET_ATTRS(player);
6198         if ( !attrs )
6199         {
6200                 debug_error("cannot get content attribute\n");
6201                 goto INIT_ERROR;
6202         }
6203
6204         /* create pipeline handles */
6205         if ( player->pipeline )
6206         {
6207                 debug_warning("pipeline should be released before create new one\n");
6208                 goto INIT_ERROR;
6209         }
6210
6211         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0( sizeof(MMPlayerGstPipelineInfo) );
6212         if (player->pipeline == NULL)
6213                 goto INIT_ERROR;
6214
6215         memset( player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo) );
6216
6217
6218         /* create mainbin */
6219         mainbin = (MMPlayerGstElement*) g_malloc0( sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM );
6220         if (mainbin == NULL)
6221                 goto INIT_ERROR;
6222
6223         memset( mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
6224
6225         /* create pipeline */
6226         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
6227         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
6228         if ( ! mainbin[MMPLAYER_M_PIPE].gst )
6229         {
6230                 debug_error("failed to create pipeline\n");
6231                 goto INIT_ERROR;
6232         }
6233         player->demux_pad_index = 0;
6234         player->subtitle_language_list = NULL;
6235
6236         player->is_subtitle_force_drop = FALSE;
6237         player->last_multiwin_status = FALSE;
6238
6239         _mmplayer_track_initialize(player);
6240
6241         /* create source element */
6242         switch ( player->profile.uri_type )
6243         {
6244                 /* rtsp streamming */
6245                 case MM_PLAYER_URI_TYPE_URL_RTSP:
6246                 {
6247                         gint network_bandwidth;
6248                         gchar *user_agent, *wap_profile;
6249
6250                         element = gst_element_factory_make("rtspsrc", "rtsp source");
6251
6252                         if ( !element )
6253                         {
6254                                 debug_error("failed to create streaming source element\n");
6255                                 break;
6256                         }
6257
6258                         /* make it zero */
6259                         network_bandwidth = 0;
6260                         user_agent = wap_profile = NULL;
6261
6262                         /* get attribute */
6263                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
6264                         mm_attrs_get_string_by_name ( attrs,"streaming_wap_profile", &wap_profile );
6265                         mm_attrs_get_int_by_name ( attrs, "streaming_network_bandwidth", &network_bandwidth );
6266
6267                         secure_debug_log("user_agent : %s\n", user_agent);
6268                         secure_debug_log("wap_profile : %s\n", wap_profile);
6269
6270                         /* setting property to streaming source */
6271                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6272                         if ( user_agent )
6273                                 g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6274                         if ( wap_profile )
6275                                 g_object_set(G_OBJECT(element), "wap_profile", wap_profile, NULL);
6276
6277                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6278                                 G_CALLBACK (__mmplayer_gst_rtp_dynamic_pad), player );
6279                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
6280                                 G_CALLBACK (__mmplayer_gst_rtp_no_more_pads), player );
6281
6282                         player->use_decodebin = FALSE;
6283                 }
6284                 break;
6285
6286                 /* http streaming*/
6287                 case MM_PLAYER_URI_TYPE_URL_HTTP:
6288                 {
6289                         gchar *user_agent, *proxy, *cookies, **cookie_list;
6290                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6291                         user_agent = proxy = cookies = NULL;
6292                         cookie_list = NULL;
6293                         gint mode = MM_PLAYER_PD_MODE_NONE;
6294
6295                         mm_attrs_get_int_by_name ( attrs, "pd_mode", &mode );
6296
6297                         player->pd_mode = mode;
6298
6299                         debug_log("http playback, PD mode : %d\n", player->pd_mode);
6300
6301                         if ( ! MMPLAYER_IS_HTTP_PD(player) )
6302                         {
6303                                 element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
6304                                 if ( !element )
6305                                 {
6306                                         debug_error("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
6307                                         break;
6308                                 }
6309                                 debug_log("using http streamming source [%s].\n", player->ini.httpsrc_element);
6310
6311                                 /* get attribute */
6312                                 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
6313                                 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
6314                                 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
6315                                 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
6316
6317                                 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
6318                                         (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
6319                                 {
6320                                         debug_log("get timeout from ini\n");
6321                                         http_timeout = player->ini.http_timeout;
6322                                 }
6323
6324                                 /* get attribute */
6325                                 secure_debug_log("location : %s\n", player->profile.uri);
6326                                 secure_debug_log("cookies : %s\n", cookies);
6327                                 secure_debug_log("proxy : %s\n", proxy);
6328                                 secure_debug_log("user_agent :  %s\n",  user_agent);
6329                                 debug_log("timeout : %d\n",  http_timeout);
6330
6331                                 /* setting property to streaming source */
6332                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6333                                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6334                                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
6335
6336                                 /* check if prosy is vailid or not */
6337                                 if ( util_check_valid_url ( proxy ) )
6338                                         g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
6339                                 /* parsing cookies */
6340                                 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
6341                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
6342                                 if ( user_agent )
6343                                         g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6344
6345                                 if ( MMPLAYER_URL_HAS_DASH_SUFFIX(player) )
6346                                 {
6347                                         debug_warning("it's dash. and it's still experimental feature.");
6348                                 }
6349                         }
6350                         else // progressive download
6351                         {
6352                                 gchar* location = NULL;
6353
6354                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
6355                                 {
6356                                         gchar *path = NULL;
6357
6358                                         mm_attrs_get_string_by_name ( attrs, "pd_location", &path );
6359
6360                                         MMPLAYER_FREEIF(player->pd_file_save_path);
6361
6362                                         debug_log("PD Location : %s\n", path);
6363
6364                                         if ( path )
6365                                         {
6366                                                 player->pd_file_save_path = g_strdup(path);
6367                                         }
6368                                         else
6369                                         {
6370                                                 debug_error("can't find pd location so, it should be set \n");
6371                                                 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
6372                                         }
6373                                 }
6374
6375                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
6376                                 if ( !element )
6377                                 {
6378                                         debug_error("failed to create PD push source element[%s].\n", "pdpushsrc");
6379                                         break;
6380                                 }
6381
6382                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
6383                                         g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
6384                                 else
6385                                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6386
6387                                 g_object_get(element, "location", &location, NULL);
6388                                 debug_log("PD_LOCATION [%s].\n", location);
6389                                 if (location)
6390                                         g_free (location);
6391                         }
6392                 }
6393                 break;
6394
6395                 /* file source */
6396                 case MM_PLAYER_URI_TYPE_FILE:
6397                 {
6398
6399                         debug_log("using filesrc for 'file://' handler.\n");
6400
6401                         element = gst_element_factory_make("filesrc", "source");
6402
6403                         if ( !element )
6404                         {
6405                                 debug_error("failed to create filesrc\n");
6406                                 break;
6407                         }
6408
6409                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
6410                         //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL);
6411                 }
6412                 break;
6413
6414                 case MM_PLAYER_URI_TYPE_SS:
6415                 {
6416                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6417                         element = gst_element_factory_make("souphttpsrc", "http streaming source");
6418                         if ( !element )
6419                         {
6420                                 debug_error("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
6421                                 break;
6422                         }
6423
6424                         mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
6425
6426                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
6427                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
6428                         {
6429                                 debug_log("get timeout from ini\n");
6430                                 http_timeout = player->ini.http_timeout;
6431                         }
6432
6433                         /* setting property to streaming source */
6434                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6435                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6436                 }
6437                 break;
6438
6439                 /* appsrc */
6440                 case MM_PLAYER_URI_TYPE_BUFF:
6441                 {
6442                         guint64 stream_type = GST_APP_STREAM_TYPE_STREAM;
6443
6444                         debug_log("mem src is selected\n");
6445
6446                         element = gst_element_factory_make("appsrc", "buff-source");
6447                         if ( !element )
6448                         {
6449                                 debug_error("failed to create appsrc element\n");
6450                                 break;
6451                         }
6452
6453                         g_object_set( element, "stream-type", stream_type, NULL );
6454                         //g_object_set( element, "size", player->mem_buf.len, NULL );
6455                         //g_object_set( element, "blocksize", (guint64)20480, NULL );
6456
6457                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6458                                 G_CALLBACK(__gst_appsrc_seek_data), player);
6459                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6460                                 G_CALLBACK(__gst_appsrc_feed_data), player);
6461                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6462                                 G_CALLBACK(__gst_appsrc_enough_data), player);
6463                 }
6464                 break;
6465                 case MM_PLAYER_URI_TYPE_ES_BUFF:
6466                 {
6467                         debug_log("es buff src is selected\n");
6468
6469                         if (player->v_stream_caps)
6470                         {
6471                                 element = gst_element_factory_make("appsrc", "video_appsrc");
6472                                 if ( !element )
6473                                 {
6474                                         debug_critical("failed to create video app source element[appsrc].\n" );
6475                                         break;
6476                                 }
6477
6478                                 if ( player->a_stream_caps )
6479                                 {
6480                                         elem_src_audio = gst_element_factory_make("appsrc", "audio_appsrc");
6481                                         if ( !elem_src_audio )
6482                                         {
6483                                                 debug_critical("failed to create audio app source element[appsrc].\n" );
6484                                                 break;
6485                                         }
6486                                 }
6487                         }
6488                         else if ( player->a_stream_caps )
6489                         {
6490                                 /* no video, only audio pipeline*/
6491                                 element = gst_element_factory_make("appsrc", "audio_appsrc");
6492                                 if ( !element )
6493                                 {
6494                                         debug_critical("failed to create audio app source element[appsrc].\n" );
6495                                         break;
6496                                 }
6497                         }
6498
6499                         if ( player->s_stream_caps )
6500                         {
6501                                 elem_src_subtitle = gst_element_factory_make("appsrc", "subtitle_appsrc");
6502                                 if ( !elem_src_subtitle )
6503                                 {
6504                                         debug_critical("failed to create subtitle app source element[appsrc].\n" );
6505                                         break;
6506                                 }
6507                         }
6508
6509                         debug_log("setting app sources properties.\n");
6510                         debug_log("location : %s\n", player->profile.uri);
6511
6512                         if ( player->v_stream_caps && element )
6513                         {
6514                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6515                                                                                             "blocksize", (guint)1048576,        /* size of many video frames are larger than default blocksize as 4096 */
6516                                                                                                 "caps", player->v_stream_caps, NULL);
6517
6518                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6519                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6520                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6521                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6522
6523                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6524                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6525                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6526                                                                                                                 G_CALLBACK(__gst_seek_video_data), player);
6527
6528                                 if (player->a_stream_caps && elem_src_audio)
6529                                 {
6530                                         g_object_set(G_OBJECT(elem_src_audio), "format", GST_FORMAT_TIME,
6531                                                                                                                         "caps", player->a_stream_caps, NULL);
6532
6533                                         if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6534                                                 g_object_set(G_OBJECT(elem_src_audio), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6535                                         if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6536                                                 g_object_set(G_OBJECT(elem_src_audio), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6537
6538                                         /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6539                                         gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_audio), GST_APP_STREAM_TYPE_SEEKABLE);
6540                                         MMPLAYER_SIGNAL_CONNECT( player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6541                                                                                                                 G_CALLBACK(__gst_seek_audio_data), player);
6542                                 }
6543                         }
6544                         else if (player->a_stream_caps && element)
6545                         {
6546                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6547                                                                                                 "caps", player->a_stream_caps, NULL);
6548
6549                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6550                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6551                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6552                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6553
6554                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6555                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6556                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6557                                                                                                                         G_CALLBACK(__gst_seek_audio_data), player);
6558                         }
6559
6560                         if (player->s_stream_caps && elem_src_subtitle)
6561                         {
6562                                 g_object_set(G_OBJECT(elem_src_subtitle), "format", GST_FORMAT_TIME,
6563                                                                                                                  "caps", player->s_stream_caps, NULL);
6564
6565                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6566                                         g_object_set(G_OBJECT(elem_src_subtitle), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6567                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6568                                         g_object_set(G_OBJECT(elem_src_subtitle), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6569
6570                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_subtitle), GST_APP_STREAM_TYPE_SEEKABLE);
6571
6572                                 MMPLAYER_SIGNAL_CONNECT( player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6573                                                                                                                                 G_CALLBACK(__gst_seek_subtitle_data), player);
6574                         }
6575
6576                         if (player->v_stream_caps && element)
6577                         {
6578                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6579                                                                                                                 G_CALLBACK(__gst_appsrc_feed_video_data), player);
6580                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6581                                                                                                                 G_CALLBACK(__gst_appsrc_enough_video_data), player);
6582
6583                                 if (player->a_stream_caps && elem_src_audio)
6584                                 {
6585                                         MMPLAYER_SIGNAL_CONNECT( player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6586                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6587                                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6588                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6589                                 }
6590                         }
6591                         else if (player->a_stream_caps && element)
6592                         {
6593                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6594                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6595                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6596                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6597                         }
6598
6599                         if (player->s_stream_caps && elem_src_subtitle)
6600                         {
6601                                 MMPLAYER_SIGNAL_CONNECT( player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6602                                                                                                                 G_CALLBACK(__gst_appsrc_feed_subtitle_data), player);
6603                         }
6604
6605                         need_state_holder = FALSE;
6606                 }
6607                 break;
6608                 /* appsrc */
6609                 case MM_PLAYER_URI_TYPE_MEM:
6610                 {
6611                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
6612
6613                         debug_log("mem src is selected\n");
6614
6615                         element = gst_element_factory_make("appsrc", "mem-source");
6616                         if ( !element )
6617                         {
6618                                 debug_error("failed to create appsrc element\n");
6619                                 break;
6620                         }
6621
6622                         g_object_set( element, "stream-type", stream_type, NULL );
6623                         g_object_set( element, "size", player->mem_buf.len, NULL );
6624                         g_object_set( element, "blocksize", (guint64)20480, NULL );
6625
6626                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6627                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->mem_buf );
6628                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6629                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->mem_buf );
6630                 }
6631                 break;
6632                 case MM_PLAYER_URI_TYPE_URL:
6633                 break;
6634
6635                 case MM_PLAYER_URI_TYPE_TEMP:
6636                 break;
6637
6638                 case MM_PLAYER_URI_TYPE_NONE:
6639                 default:
6640                 break;
6641         }
6642
6643         /* check source element is OK */
6644         if ( ! element )
6645         {
6646                 debug_error("no source element was created.\n");
6647                 goto INIT_ERROR;
6648         }
6649
6650         /* take source element */
6651         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
6652         mainbin[MMPLAYER_M_SRC].gst = element;
6653         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
6654
6655         if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL))
6656         {
6657                 player->streamer = __mm_player_streaming_create();
6658                 __mm_player_streaming_initialize(player->streamer);
6659         }
6660
6661         if ( MMPLAYER_IS_HTTP_PD(player) )
6662         {
6663                 gdouble pre_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
6664
6665                 debug_log ("Picked queue2 element(pre buffer : %d sec)....\n", pre_buffering_time);
6666                 element = gst_element_factory_make("queue2", "queue2");
6667                 if ( !element )
6668                 {
6669                         debug_error ( "failed to create http streaming buffer element\n" );
6670                         goto INIT_ERROR;
6671                 }
6672
6673                 /* take it */
6674                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
6675                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
6676                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
6677
6678                 pre_buffering_time = (pre_buffering_time > 0)?(pre_buffering_time):(player->ini.http_buffering_time);
6679
6680                 __mm_player_streaming_set_queue2(player->streamer,
6681                                 element,
6682                                 TRUE,
6683                                 player->ini.http_max_size_bytes,
6684                                 pre_buffering_time,
6685                                 1.0,
6686                                 player->ini.http_buffering_limit,
6687                                 FALSE,
6688                                 NULL,
6689                                 0);
6690         }
6691         if (MMPLAYER_IS_ES_BUFF_SRC(player))
6692         {
6693                 if (player->v_stream_caps)
6694                 {
6695                         es_video_queue = gst_element_factory_make("queue2", "video_queue");
6696                         if (!es_video_queue)
6697                         {
6698                                 debug_error ("create es_video_queue for es player failed\n");
6699                                 goto INIT_ERROR;
6700                         }
6701                         mainbin[MMPLAYER_M_V_BUFFER].id = MMPLAYER_M_V_BUFFER;
6702                         mainbin[MMPLAYER_M_V_BUFFER].gst = es_video_queue;
6703                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_V_BUFFER]);
6704
6705                         /* Adding audio appsrc to bucket */
6706                         if (player->a_stream_caps && elem_src_audio)
6707                         {
6708                                 mainbin[MMPLAYER_M_2ND_SRC].id = MMPLAYER_M_2ND_SRC;
6709                                 mainbin[MMPLAYER_M_2ND_SRC].gst = elem_src_audio;
6710                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_2ND_SRC]);
6711
6712                                 es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6713                                 if (!es_audio_queue)
6714                                 {
6715                                         debug_error ("create es_audio_queue for es player failed\n");
6716                                         goto INIT_ERROR;
6717                                 }
6718                                 mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6719                                 mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6720                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6721                         }
6722                 }
6723                 /* Only audio stream, no video */
6724                 else if (player->a_stream_caps)
6725                 {
6726                         es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6727                         if (!es_audio_queue)
6728                         {
6729                                 debug_error ("create es_audio_queue for es player failed\n");
6730                                 goto INIT_ERROR;
6731                         }
6732                         mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6733                         mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6734                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6735                 }
6736
6737                 if (player->s_stream_caps && elem_src_subtitle)
6738                 {
6739                         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6740                         mainbin[MMPLAYER_M_SUBSRC].gst = elem_src_subtitle;
6741                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SUBSRC]);
6742
6743                         es_subtitle_queue = gst_element_factory_make("queue2", "subtitle_queue");
6744                         if (!es_subtitle_queue)
6745                         {
6746                                 debug_error ("create es_subtitle_queue for es player failed\n");
6747                                 goto INIT_ERROR;
6748                         }
6749                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_V_BUFFER;
6750                         mainbin[MMPLAYER_M_S_BUFFER].gst = es_subtitle_queue;
6751                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
6752                 }
6753         }
6754
6755         /* create autoplugging element if src element is not a rtsp src */
6756         if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
6757                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_WFD) &&
6758                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_ES_BUFF))
6759         {
6760                 element = NULL;
6761                 enum MainElementID elemId = MMPLAYER_M_NUM;
6762
6763                 if ((player->use_decodebin) &&
6764                         ((MMPLAYER_IS_HTTP_PD(player)) ||
6765                          (!MMPLAYER_IS_HTTP_STREAMING(player))))
6766                 {
6767                         elemId = MMPLAYER_M_AUTOPLUG;
6768                         element = __mmplayer_create_decodebin(player);
6769                         need_state_holder = FALSE;
6770                 }
6771                 else
6772                 {
6773                         elemId = MMPLAYER_M_TYPEFIND;
6774                         element = gst_element_factory_make("typefind", "typefinder");
6775                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
6776                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
6777                 }
6778
6779
6780                 /* check autoplug element is OK */
6781                 if ( ! element )
6782                 {
6783                         debug_error("can not create element (%d)\n", elemId);
6784                         goto INIT_ERROR;
6785                 }
6786
6787                 mainbin[elemId].id = elemId;
6788                 mainbin[elemId].gst = element;
6789
6790                 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
6791         }
6792
6793         /* add elements to pipeline */
6794         if( !__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket))
6795         {
6796                 debug_error("Failed to add elements to pipeline\n");
6797                 goto INIT_ERROR;
6798         }
6799
6800
6801         /* linking elements in the bucket by added order. */
6802         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
6803         {
6804                 debug_error("Failed to link some elements\n");
6805                 goto INIT_ERROR;
6806         }
6807
6808
6809         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
6810         if ( need_state_holder )
6811         {
6812                 /* create */
6813                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
6814                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make ("fakesink", "state-holder");
6815
6816                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
6817                 {
6818                         debug_error ("fakesink element could not be created\n");
6819                         goto INIT_ERROR;
6820                 }
6821                 GST_OBJECT_FLAG_UNSET (mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
6822
6823                 /* take ownership of fakesink. we are reusing it */
6824                 gst_object_ref( mainbin[MMPLAYER_M_SRC_FAKESINK].gst );
6825
6826                 /* add */
6827                 if ( FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
6828                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst) )
6829                 {
6830                         debug_error("failed to add fakesink to bin\n");
6831                         goto INIT_ERROR;
6832                 }
6833         }
6834
6835         /* now we have completed mainbin. take it */
6836         player->pipeline->mainbin = mainbin;
6837
6838         if (MMPLAYER_IS_ES_BUFF_SRC(player))
6839         {
6840                 GstPad *srcpad = NULL;
6841
6842                 if (mainbin[MMPLAYER_M_V_BUFFER].gst)
6843                 {
6844                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_V_BUFFER].gst, "src");
6845                         if (srcpad)
6846                         {
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                 {
6860                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_BUFFER].gst, "src");
6861                         if (srcpad)
6862                         {
6863                                 __mmplayer_gst_create_decoder ( player,
6864                                                                                                 MM_PLAYER_TRACK_TYPE_AUDIO,
6865                                                                                                 srcpad,
6866                                                                                                 MMPLAYER_M_AUTOPLUG_A_DEC,
6867                                                                                                 "audio_decodebin");
6868
6869                                 gst_object_unref ( GST_OBJECT(srcpad) );
6870                                 srcpad = NULL;
6871                         } // else error
6872                 } //  else error
6873
6874                 if (mainbin[MMPLAYER_M_S_BUFFER].gst)
6875                 {
6876                         __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
6877                 }
6878         }
6879
6880         /* connect bus callback */
6881         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
6882         if ( !bus )
6883         {
6884                 debug_error ("cannot get bus from pipeline.\n");
6885                 goto INIT_ERROR;
6886         }
6887
6888         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
6889
6890         player->context.thread_default = g_main_context_get_thread_default();
6891
6892         if (NULL == player->context.thread_default)
6893         {
6894                 player->context.thread_default = g_main_context_default();
6895                 debug_log("thread-default context is the global default context");
6896         }
6897         debug_warning("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
6898
6899         /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
6900         if ( __mmplayer_check_subtitle ( player ) )
6901         {
6902                 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
6903                         debug_error("fail to create subtitle src\n");
6904         }
6905
6906         /* set sync handler to get tag synchronously */
6907         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL);
6908
6909         /* finished */
6910         gst_object_unref(GST_OBJECT(bus));
6911         g_list_free(element_bucket);
6912
6913         MMPLAYER_FLEAVE();
6914
6915         return MM_ERROR_NONE;
6916
6917 INIT_ERROR:
6918
6919         __mmplayer_gst_destroy_pipeline(player);
6920         g_list_free(element_bucket);
6921
6922         /* release element which are not added to bin */
6923         for ( i = 1; i < MMPLAYER_M_NUM; i++ )  /* NOTE : skip pipeline */
6924         {
6925                 if ( mainbin[i].gst )
6926                 {
6927                         GstObject* parent = NULL;
6928                         parent = gst_element_get_parent( mainbin[i].gst );
6929
6930                         if ( !parent )
6931                         {
6932                                 gst_object_unref(GST_OBJECT(mainbin[i].gst));
6933                                 mainbin[i].gst = NULL;
6934                         }
6935                         else
6936                         {
6937                                 gst_object_unref(GST_OBJECT(parent));
6938                         }
6939                 }
6940         }
6941
6942         /* release pipeline with it's childs */
6943         if ( mainbin[MMPLAYER_M_PIPE].gst )
6944         {
6945                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
6946         }
6947
6948         MMPLAYER_FREEIF( player->pipeline );
6949         MMPLAYER_FREEIF( mainbin );
6950
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         return_if_fail(player
6959                 && player->pipeline
6960                 && player->pipeline->audiobin
6961                 && player->pipeline->audiobin[MMPLAYER_A_BIN].gst);
6962
6963         if (player->gapless.audio_data_probe_id != 0)
6964         {
6965                 GstPad *sinkpad;
6966                 sinkpad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_BIN].gst, "sink");
6967                 gst_pad_remove_probe (sinkpad, player->gapless.audio_data_probe_id);
6968                 gst_object_unref (sinkpad);
6969         }
6970         memset(&player->gapless, 0, sizeof(mm_player_gapless_t));
6971
6972         MMPLAYER_FLEAVE();
6973         return;
6974 }
6975
6976 static int
6977 __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
6978 {
6979         gint timeout = 0;
6980         int ret = MM_ERROR_NONE;
6981
6982         MMPLAYER_FENTER();
6983
6984         return_val_if_fail ( player, MM_ERROR_INVALID_HANDLE );
6985
6986         /* cleanup stuffs */
6987         MMPLAYER_FREEIF(player->type);
6988         player->have_dynamic_pad = FALSE;
6989         player->no_more_pad = FALSE;
6990         player->num_dynamic_pad = 0;
6991         player->demux_pad_index = 0;
6992         player->subtitle_language_list = NULL;
6993         player->use_deinterleave = FALSE;
6994         player->max_audio_channels = 0;
6995         player->video_share_api_delta = 0;
6996         player->video_share_clock_delta = 0;
6997         player->video_hub_download_mode = 0;
6998         __mmplayer_reset_gapless_state(player);
6999         __mmplayer_post_proc_reset(player);
7000
7001         if (player->streamer)
7002         {
7003                 __mm_player_streaming_deinitialize (player->streamer);
7004                 __mm_player_streaming_destroy(player->streamer);
7005                 player->streamer = NULL;
7006         }
7007
7008         /* cleanup unlinked mime type */
7009         MMPLAYER_FREEIF(player->unlinked_audio_mime);
7010         MMPLAYER_FREEIF(player->unlinked_video_mime);
7011         MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
7012
7013         /* cleanup running stuffs */
7014         __mmplayer_cancel_eos_timer( player );
7015 #if 0 //need to change and test
7016         /* remove sound cb */
7017         if ( MM_ERROR_NONE != mm_sound_remove_device_information_changed_callback())
7018         {
7019                 debug_error("failed to mm_sound_remove_device_information_changed_callback()");
7020         }
7021 #endif
7022         /* cleanup gst stuffs */
7023         if ( player->pipeline )
7024         {
7025                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
7026                 GstTagList* tag_list = player->pipeline->tag_list;
7027
7028                 /* first we need to disconnect all signal hander */
7029                 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_ALL );
7030
7031                 /* disconnecting bus watch */
7032                 if ( player->bus_watcher )
7033                         __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
7034                 player->bus_watcher = 0;
7035
7036                 if ( mainbin )
7037                 {
7038                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
7039                         MMPlayerGstElement* videobin = player->pipeline->videobin;
7040                         MMPlayerGstElement* textbin = player->pipeline->textbin;
7041                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mainbin[MMPLAYER_M_PIPE].gst));
7042                         gst_bus_set_sync_handler (bus, NULL, NULL, NULL);
7043                         gst_object_unref(bus);
7044
7045                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7046                         ret = __mmplayer_gst_set_state ( player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout );
7047                         if ( ret != MM_ERROR_NONE )
7048                         {
7049                                 debug_error("fail to change state to NULL\n");
7050                                 return MM_ERROR_PLAYER_INTERNAL;
7051                         }
7052
7053                         debug_warning("succeeded in chaning state to NULL\n");
7054
7055                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7056
7057                         /* free fakesink */
7058                         if ( mainbin[MMPLAYER_M_SRC_FAKESINK].gst )
7059                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
7060
7061                         /* free avsysaudiosink
7062                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
7063                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
7064                         */
7065                         MMPLAYER_FREEIF( audiobin );
7066                         MMPLAYER_FREEIF( videobin );
7067                         MMPLAYER_FREEIF( textbin );
7068                         MMPLAYER_FREEIF( mainbin );
7069                 }
7070
7071                 if ( tag_list )
7072                         gst_tag_list_free(tag_list);
7073
7074                 MMPLAYER_FREEIF( player->pipeline );
7075         }
7076         MMPLAYER_FREEIF(player->album_art);
7077
7078         if (player->v_stream_caps)
7079         {
7080                 gst_caps_unref(player->v_stream_caps);
7081                 player->v_stream_caps = NULL;
7082         }
7083         if (player->a_stream_caps)
7084         {
7085                 gst_caps_unref(player->a_stream_caps);
7086                 player->a_stream_caps = NULL;
7087         }
7088         if (player->s_stream_caps)
7089         {
7090                 gst_caps_unref(player->s_stream_caps);
7091                 player->s_stream_caps = NULL;
7092         }
7093         _mmplayer_track_destroy(player);
7094
7095         if ( player->sink_elements )
7096                 g_list_free ( player->sink_elements );
7097         player->sink_elements = NULL;
7098
7099         debug_warning("finished destroy pipeline\n");
7100
7101         MMPLAYER_FLEAVE();
7102
7103         return ret;
7104 }
7105
7106 static int __gst_realize(mm_player_t* player) // @
7107 {
7108         gint timeout = 0;
7109         int ret = MM_ERROR_NONE;
7110
7111         MMPLAYER_FENTER();
7112
7113         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7114
7115         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7116
7117         ret = __mmplayer_gst_create_pipeline(player);
7118         if ( ret )
7119         {
7120                 debug_error("failed to create pipeline\n");
7121                 return ret;
7122         }
7123
7124         /* set pipeline state to READY */
7125         /* NOTE : state change to READY must be performed sync. */
7126         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7127         ret = __mmplayer_gst_set_state(player,
7128                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
7129
7130         if ( ret != MM_ERROR_NONE )
7131         {
7132                 /* return error if failed to set state */
7133                 debug_error("failed to set READY state");
7134                 return ret;
7135         }
7136         else
7137         {
7138                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
7139         }
7140
7141         /* create dot before error-return. for debugging */
7142         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-realize" );
7143
7144         MMPLAYER_FLEAVE();
7145
7146         return ret;
7147 }
7148
7149 static int __gst_unrealize(mm_player_t* player) // @
7150 {
7151         int ret = MM_ERROR_NONE;
7152
7153         MMPLAYER_FENTER();
7154
7155         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7156
7157         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
7158         MMPLAYER_PRINT_STATE(player);
7159
7160         /* release miscellaneous information */
7161         __mmplayer_release_misc( player );
7162
7163         /* destroy pipeline */
7164         ret = __mmplayer_gst_destroy_pipeline( player );
7165         if ( ret != MM_ERROR_NONE )
7166         {
7167                 debug_error("failed to destory pipeline\n");
7168                 return ret;
7169         }
7170
7171         /* release miscellaneous information.
7172            these info needs to be released after pipeline is destroyed. */
7173         __mmplayer_release_misc_post( player );
7174
7175         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
7176
7177         MMPLAYER_FLEAVE();
7178
7179         return ret;
7180 }
7181
7182 static int __gst_pending_seek ( mm_player_t* player )
7183 {
7184         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7185         int ret = MM_ERROR_NONE;
7186
7187         MMPLAYER_FENTER();
7188
7189         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7190
7191         if ( !player->pending_seek.is_pending )
7192         {
7193                 debug_log("pending seek is not reserved. nothing to do.\n" );
7194                 return ret;
7195         }
7196
7197         /* check player state if player could pending seek or not. */
7198         current_state = MMPLAYER_CURRENT_STATE(player);
7199
7200         if ( current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING  )
7201         {
7202                 debug_warning("try to pending seek in %s state, try next time. \n",
7203                         MMPLAYER_STATE_GET_NAME(current_state));
7204                 return ret;
7205         }
7206
7207         debug_log("trying to play from (%lu) pending position\n", player->pending_seek.pos);
7208
7209         ret = __gst_set_position ( player, player->pending_seek.format, player->pending_seek.pos, FALSE );
7210
7211         if ( MM_ERROR_NONE != ret )
7212                 debug_error("failed to seek pending postion. just keep staying current position.\n");
7213
7214         player->pending_seek.is_pending = FALSE;
7215
7216         MMPLAYER_FLEAVE();
7217
7218         return ret;
7219 }
7220
7221 static int __gst_start(mm_player_t* player) // @
7222 {
7223         gboolean sound_extraction = 0;
7224         int ret = MM_ERROR_NONE;
7225         gboolean async = FALSE;
7226
7227         MMPLAYER_FENTER();
7228
7229         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7230
7231         /* get sound_extraction property */
7232         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
7233
7234         /* NOTE : if SetPosition was called before Start. do it now */
7235         /* streaming doesn't support it. so it should be always sync */
7236         /* !! create one more api to check if there is pending seek rather than checking variables */
7237         if ( (player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player))
7238         {
7239                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
7240                 ret = __gst_pause(player, FALSE);
7241                 if ( ret != MM_ERROR_NONE )
7242                 {
7243                         debug_error("failed to set state to PAUSED for pending seek\n");
7244                         return ret;
7245                 }
7246
7247                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
7248
7249                 if ( sound_extraction )
7250                 {
7251                         debug_log("setting pcm extraction\n");
7252
7253                         ret = __mmplayer_set_pcm_extraction(player);
7254                         if ( MM_ERROR_NONE != ret )
7255                         {
7256                                 debug_warning("failed to set pcm extraction\n");
7257                                 return ret;
7258                         }
7259                 }
7260                 else
7261                 {
7262                         if ( MM_ERROR_NONE != __gst_pending_seek(player) )
7263                         {
7264                                 debug_warning("failed to seek pending postion. starting from the begin of content.\n");
7265                         }
7266                 }
7267         }
7268
7269         debug_log("current state before doing transition");
7270         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7271         MMPLAYER_PRINT_STATE(player);
7272
7273         /* set pipeline state to PLAYING  */
7274         if (player->es_player_push_mode)
7275         {
7276                 async = TRUE;
7277         }
7278         /* set pipeline state to PLAYING  */
7279         ret = __mmplayer_gst_set_state(player,
7280                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
7281
7282         if (ret == MM_ERROR_NONE)
7283         {
7284                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7285         }
7286         else
7287         {
7288                 debug_error("failed to set state to PLAYING");
7289                 return ret;
7290         }
7291
7292         /* generating debug info before returning error */
7293         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-start" );
7294
7295         MMPLAYER_FLEAVE();
7296
7297         return ret;
7298 }
7299
7300 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
7301 {
7302         MMPLAYER_FENTER();
7303
7304         return_if_fail(player
7305                 && player->pipeline
7306                 && player->pipeline->audiobin
7307                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
7308
7309         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
7310
7311         usleep(time);
7312
7313         MMPLAYER_FLEAVE();
7314 }
7315
7316 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
7317 {
7318         MMPLAYER_FENTER();
7319
7320         return_if_fail(player
7321                 && player->pipeline
7322                 && player->pipeline->audiobin
7323                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
7324
7325         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
7326
7327         MMPLAYER_FLEAVE();
7328 }
7329
7330 static int __gst_stop(mm_player_t* player) // @
7331 {
7332         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
7333         MMHandleType attrs = 0;
7334         gboolean fadedown = FALSE;
7335         gboolean rewind = FALSE;
7336         gint timeout = 0;
7337         int ret = MM_ERROR_NONE;
7338         GstState state;
7339         gboolean async = FALSE;
7340
7341         MMPLAYER_FENTER();
7342
7343         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7344         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7345
7346         debug_log("current state before doing transition");
7347         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7348         MMPLAYER_PRINT_STATE(player);
7349
7350         attrs = MMPLAYER_GET_ATTRS(player);
7351         if ( !attrs )
7352         {
7353                 debug_error("cannot get content attribute\n");
7354                 return MM_ERROR_PLAYER_INTERNAL;
7355         }
7356
7357         mm_attrs_get_int_by_name(attrs, "sound_fadedown", &fadedown);
7358
7359         /* enable fadedown */
7360         if (fadedown || player->sound_focus.by_asm_cb)
7361                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
7362
7363         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
7364         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
7365
7366         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_BUFF ||
7367                 player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS)
7368         {
7369                 state = GST_STATE_READY;
7370         }
7371         else
7372         {
7373                 state = GST_STATE_PAUSED;
7374
7375                 if ( ! MMPLAYER_IS_STREAMING(player) ||
7376                         (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked)) {
7377                         rewind = TRUE;
7378                 }
7379         }
7380
7381         if (player->es_player_push_mode)
7382         {
7383                 async = TRUE;
7384         }
7385         /* set gst state */
7386         ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, async, timeout );
7387
7388         /* disable fadeout */
7389         if (fadedown || player->sound_focus.by_asm_cb)
7390                 __mmplayer_undo_sound_fadedown(player);
7391
7392         /* return if set_state has failed */
7393         if ( ret != MM_ERROR_NONE )
7394         {
7395                 debug_error("failed to set state.\n");
7396                 return ret;
7397         }
7398
7399         /* rewind */
7400         if ( rewind )
7401         {
7402                 if ( ! __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7403                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
7404                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE) )
7405                 {
7406                         debug_warning("failed to rewind\n");
7407                         ret = MM_ERROR_PLAYER_SEEK;
7408                 }
7409         }
7410
7411         /* initialize */
7412         player->sent_bos = FALSE;
7413
7414         if (player->es_player_push_mode) //for cloudgame
7415         {
7416                 timeout = 0;
7417         }
7418
7419         /* wait for seek to complete */
7420         change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
7421         if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL )
7422         {
7423                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
7424         }
7425         else
7426         {
7427                 debug_error("fail to stop player.\n");
7428                 ret = MM_ERROR_PLAYER_INTERNAL;
7429                 __mmplayer_dump_pipeline_state(player);
7430         }
7431
7432         /* generate dot file if enabled */
7433         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-stop" );
7434
7435         MMPLAYER_FLEAVE();
7436
7437         return ret;
7438 }
7439
7440 int __gst_pause(mm_player_t* player, gboolean async) // @
7441 {
7442         int ret = MM_ERROR_NONE;
7443
7444         MMPLAYER_FENTER();
7445
7446         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7447         return_val_if_fail(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7448
7449         debug_log("current state before doing transition");
7450         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
7451         MMPLAYER_PRINT_STATE(player);
7452
7453         /* set pipeline status to PAUSED */
7454         player->ignore_asyncdone = TRUE;
7455
7456         ret = __mmplayer_gst_set_state(player,
7457                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
7458
7459         player->ignore_asyncdone = FALSE;
7460
7461         if ( FALSE == async )
7462         {
7463                 if ( ret != MM_ERROR_NONE )
7464                 {
7465                         GstMessage *msg = NULL;
7466                         GTimer *timer = NULL;
7467                         gdouble MAX_TIMEOUT_SEC = 3;
7468
7469                         debug_error("failed to set state to PAUSED");
7470
7471                         timer = g_timer_new();
7472                         g_timer_start(timer);
7473
7474                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
7475                         gboolean got_msg = FALSE;
7476                         /* check if gst error posted or not */
7477                         do
7478                         {
7479                                 msg = gst_bus_timed_pop(bus, GST_SECOND /2);
7480                                 if (msg)
7481                                 {
7482                                         if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR)
7483                                         {
7484                                                 GError *error = NULL;
7485
7486                                                 /* parse error code */
7487                                                 gst_message_parse_error(msg, &error, NULL);
7488
7489                                                 if ( gst_structure_has_name ( gst_message_get_structure(msg), "streaming_error" ) )
7490                                                 {
7491                                                         /* Note : the streaming error from the streaming source is handled
7492                                                          *   using __mmplayer_handle_streaming_error.
7493                                                          */
7494                                                         __mmplayer_handle_streaming_error ( player, msg );
7495
7496                                                 }
7497                                                 else if (error)
7498                                                 {
7499                                                         debug_error("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
7500
7501                                                         if (error->domain == GST_STREAM_ERROR)
7502                                                         {
7503                                                                 ret = __gst_handle_stream_error( player, error, msg );
7504                                                         }
7505                                                         else if (error->domain == GST_RESOURCE_ERROR)
7506                                                         {
7507                                                                 ret = __gst_handle_resource_error( player, error->code );
7508                                                         }
7509                                                         else if (error->domain == GST_LIBRARY_ERROR)
7510                                                         {
7511                                                                 ret = __gst_handle_library_error( player, error->code );
7512                                                         }
7513                                                         else if (error->domain == GST_CORE_ERROR)
7514                                                         {
7515                                                                 ret = __gst_handle_core_error( player, error->code );
7516                                                         }
7517                                                 }
7518
7519                                                 got_msg = TRUE;
7520                                                 player->msg_posted = TRUE;
7521                                         }
7522                                         gst_message_unref(msg);
7523                                 }
7524                         } while (!got_msg && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
7525                         /* clean */
7526                         gst_object_unref(bus);
7527                         g_timer_stop (timer);
7528                         g_timer_destroy (timer);
7529
7530                         return ret;
7531                 }
7532                 else if ( (!player->pipeline->videobin) && (!player->pipeline->audiobin) )
7533                 {
7534                         if (MMPLAYER_IS_RTSP_STREAMING(player))
7535                                 return ret;
7536                         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
7537                 }
7538                 else if ( ret== MM_ERROR_NONE)
7539                 {
7540                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
7541                 }
7542         }
7543
7544         /* generate dot file before returning error */
7545         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-pause" );
7546
7547         MMPLAYER_FLEAVE();
7548
7549         return ret;
7550 }
7551
7552 int __gst_resume(mm_player_t* player, gboolean async) // @
7553 {
7554         int ret = MM_ERROR_NONE;
7555         gint timeout = 0;
7556
7557         MMPLAYER_FENTER();
7558
7559         return_val_if_fail(player && player->pipeline,
7560                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7561
7562         debug_log("current state before doing transition");
7563         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7564         MMPLAYER_PRINT_STATE(player);
7565
7566         /* generate dot file before returning error */
7567         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
7568
7569         if ( async )
7570                 debug_log("do async state transition to PLAYING.\n");
7571
7572         /* set pipeline state to PLAYING */
7573         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7574
7575         ret = __mmplayer_gst_set_state(player,
7576                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout );
7577         if (ret != MM_ERROR_NONE)
7578         {
7579                 debug_error("failed to set state to PLAYING\n");
7580                 return ret;
7581         }
7582         else
7583         {
7584                 if (async == FALSE)
7585                 {
7586                         // MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING );
7587                         debug_log("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
7588                         ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
7589                 }
7590         }
7591
7592         /* generate dot file before returning error */
7593         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
7594
7595         MMPLAYER_FLEAVE();
7596
7597         return ret;
7598 }
7599
7600 static int
7601 __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called) // @
7602 {
7603         unsigned long dur_msec = 0;
7604         gint64 dur_nsec = 0;
7605         gint64 pos_nsec = 0;
7606         gboolean ret = TRUE;
7607         gboolean accurated = FALSE;
7608         GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
7609
7610         MMPLAYER_FENTER();
7611         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7612         return_val_if_fail ( !MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP );
7613
7614         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
7615                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED )
7616                 goto PENDING;
7617
7618         if( !MMPLAYER_IS_ES_BUFF_SRC(player) )
7619         {
7620                 /* check duration */
7621                 /* NOTE : duration cannot be zero except live streaming.
7622                  *              Since some element could have some timing problemn with quering duration, try again.
7623                  */
7624                 if ( !player->duration )
7625                 {
7626                         if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
7627                         {
7628                                 goto SEEK_ERROR;
7629                         }
7630                         player->duration = dur_nsec;
7631                 }
7632
7633                 if ( player->duration )
7634                 {
7635                         dur_msec = GST_TIME_AS_MSECONDS(player->duration);
7636                 }
7637                 else
7638                 {
7639                         debug_error("could not get the duration. fail to seek.\n");
7640                         goto SEEK_ERROR;
7641                 }
7642         }
7643         debug_log("playback rate: %f\n", player->playback_rate);
7644
7645         mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
7646         if (accurated)
7647         {
7648                 seek_flags |= GST_SEEK_FLAG_ACCURATE;
7649         }
7650         else
7651         {
7652                 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
7653         }
7654
7655         /* do seek */
7656         switch ( format )
7657         {
7658                 case MM_PLAYER_POS_FORMAT_TIME:
7659                 {
7660                         if( !MMPLAYER_IS_ES_BUFF_SRC(player) )
7661                         {
7662                                 /* check position is valid or not */
7663                                 if ( position > dur_msec )
7664                                         goto INVALID_ARGS;
7665
7666                                 debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec);
7667
7668                                 if ( player->doing_seek )
7669                                 {
7670                                         debug_log("not completed seek");
7671                                         return MM_ERROR_PLAYER_DOING_SEEK;
7672                                 }
7673                         }
7674
7675                         if ( !internal_called )
7676                                 player->doing_seek = TRUE;
7677
7678                         pos_nsec = position * G_GINT64_CONSTANT(1000000);
7679
7680                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked))
7681                         {
7682                                 gint64 cur_time = 0;
7683
7684                                 /* get current position */
7685                                 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
7686
7687                                 /* flush */
7688                                 GstEvent *event = gst_event_new_seek (1.0,
7689                                                                 GST_FORMAT_TIME,
7690                                                                 (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
7691                                                                 GST_SEEK_TYPE_SET, cur_time,
7692                                                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7693                                 if(event) {
7694                                         __gst_send_event_to_sink(player, event);
7695                                 }
7696
7697                                 __gst_pause( player, FALSE );
7698                         }
7699
7700                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7701                                                         GST_FORMAT_TIME, seek_flags,
7702                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
7703                         if ( !ret  )
7704                         {
7705                                 debug_error("failed to set position. dur[%lu]  pos[%lu]  pos_msec[%llu]\n", dur_msec, position, pos_nsec);
7706                                 goto SEEK_ERROR;
7707                         }
7708                 }
7709                 break;
7710
7711                 case MM_PLAYER_POS_FORMAT_PERCENT:
7712                 {
7713                         debug_log("seeking to (%lu)%% \n", position);
7714
7715                         if (player->doing_seek)
7716                         {
7717                                 debug_log("not completed seek");
7718                                 return MM_ERROR_PLAYER_DOING_SEEK;
7719                         }
7720
7721                         if ( !internal_called)
7722                                 player->doing_seek = TRUE;
7723
7724                         /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
7725                         pos_nsec = (gint64) ( ( position * player->duration ) / 100 );
7726                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7727                                                         GST_FORMAT_TIME, seek_flags,
7728                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
7729                         if ( !ret  )
7730                         {
7731                                 debug_error("failed to set position. dur[%lud]  pos[%lud]  pos_msec[%"G_GUINT64_FORMAT"]\n", dur_msec, position, pos_nsec);
7732                                 goto SEEK_ERROR;
7733                         }
7734                 }
7735                 break;
7736
7737                 default:
7738                         goto INVALID_ARGS;
7739
7740         }
7741
7742         /* NOTE : store last seeking point to overcome some bad operation
7743           *      ( returning zero when getting current position ) of some elements
7744           */
7745         player->last_position = pos_nsec;
7746
7747         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
7748         if ( player->playback_rate > 1.0 )
7749                 _mmplayer_set_playspeed ( (MMHandleType)player, player->playback_rate );
7750
7751         MMPLAYER_FLEAVE();
7752         return MM_ERROR_NONE;
7753
7754 PENDING:
7755         player->pending_seek.is_pending = TRUE;
7756         player->pending_seek.format = format;
7757         player->pending_seek.pos = position;
7758
7759         debug_warning("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n",
7760                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
7761
7762         return MM_ERROR_NONE;
7763
7764 INVALID_ARGS:
7765         debug_error("invalid arguments, position : %ld  dur : %ld format : %d \n", position, dur_msec, format);
7766         return MM_ERROR_INVALID_ARGUMENT;
7767
7768 SEEK_ERROR:
7769         player->doing_seek = FALSE;
7770         return MM_ERROR_PLAYER_SEEK;
7771 }
7772
7773 #define TRICKPLAY_OFFSET GST_MSECOND
7774
7775 static int
7776 __gst_get_position(mm_player_t* player, int format, unsigned long* position) // @
7777 {
7778         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7779         gint64 pos_msec = 0;
7780         gboolean ret = TRUE;
7781
7782         return_val_if_fail( player && position && player->pipeline && player->pipeline->mainbin,
7783                 MM_ERROR_PLAYER_NOT_INITIALIZED );
7784
7785         current_state = MMPLAYER_CURRENT_STATE(player);
7786
7787         /* NOTE : query position except paused state to overcome some bad operation
7788          * please refer to below comments in details
7789          */
7790         if ( current_state != MM_PLAYER_STATE_PAUSED )
7791         {
7792                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
7793         }
7794
7795         /* NOTE : get last point to overcome some bad operation of some elements
7796          * ( returning zero when getting current position in paused state
7797          * and when failed to get postion during seeking
7798          */
7799         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
7800                 || ( ! ret ))
7801                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
7802         {
7803                 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
7804
7805                 if(player->playback_rate < 0.0)
7806                         pos_msec = player->last_position - TRICKPLAY_OFFSET;
7807                 else
7808                         pos_msec = player->last_position;
7809
7810                 if (!ret)
7811                         pos_msec = player->last_position;
7812                 else
7813                         player->last_position = pos_msec;
7814
7815                 debug_log("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
7816
7817         }
7818         else
7819         {
7820                 if (player->duration > 0 && pos_msec > player->duration) {
7821                         pos_msec = player->duration;
7822                 }
7823
7824                 if (player->sound_focus.keep_last_pos) {
7825                         debug_log("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position));
7826                         pos_msec = player->last_position;
7827                 }
7828                 else {
7829                         player->last_position = pos_msec;
7830                 }
7831         }
7832
7833         switch (format) {
7834                 case MM_PLAYER_POS_FORMAT_TIME:
7835                         *position = GST_TIME_AS_MSECONDS(pos_msec);
7836                         break;
7837
7838                 case MM_PLAYER_POS_FORMAT_PERCENT:
7839                 {
7840                         gint64 dur = 0;
7841                         gint64 pos = 0;
7842
7843                         dur = player->duration / GST_SECOND;
7844                         if (dur <= 0)
7845                         {
7846                                 debug_log ("duration is [%d], so returning position 0\n",dur);
7847                                 *position = 0;
7848                         }
7849                         else
7850                         {
7851                                 pos = pos_msec / GST_SECOND;
7852                                 *position = pos * 100 / dur;
7853                         }
7854                         break;
7855                 }
7856                 default:
7857                         return MM_ERROR_PLAYER_INTERNAL;
7858         }
7859
7860         return MM_ERROR_NONE;
7861 }
7862
7863
7864 static int      __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
7865 {
7866 #define STREAMING_IS_FINISHED   0
7867 #define BUFFERING_MAX_PER       100
7868
7869         GstQuery *query = NULL;
7870
7871         return_val_if_fail( player &&
7872                                                 player->pipeline &&
7873                                                 player->pipeline->mainbin,
7874                                                 MM_ERROR_PLAYER_NOT_INITIALIZED );
7875
7876         return_val_if_fail( start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT );
7877
7878         if (!MMPLAYER_IS_HTTP_STREAMING ( player ))
7879         {
7880                 /* and rtsp is not ready yet. */
7881                 debug_warning ( "it's only used for http streaming case.\n" );
7882                 return MM_ERROR_NONE;
7883         }
7884
7885         *start_pos = 0;
7886         *stop_pos = 0;
7887
7888         switch ( format )
7889         {
7890                 case MM_PLAYER_POS_FORMAT_PERCENT :
7891                 {
7892                         gint start_per = -1, stop_per = -1;
7893                         gint64 buffered_total = 0;
7894
7895                         unsigned long position = 0;
7896                         guint curr_size_bytes = 0;
7897                         gint64 buffering_left = -1;
7898                         gint buffered_sec = -1;
7899
7900                         gint64 content_duration = player->duration;
7901                         guint64 content_size = player->http_content_size;
7902
7903                         if (content_duration > 0)
7904                         {
7905                                 if (!__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position))
7906                                 {
7907                                         debug_log ("[Time] pos %d ms / dur %d sec / %lld bytes", position, (guint)(content_duration/GST_SECOND), content_size);
7908                                         start_per = 100 * (position*GST_MSECOND) / content_duration;
7909
7910                                         /* buffered size info from multiqueue */
7911                                         if (player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst)
7912                                         {
7913                                                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst), "curr-size-bytes", &curr_size_bytes, NULL);
7914                                                 debug_log ("[MQ] curr_size_bytes = %d", curr_size_bytes);
7915
7916                                                 buffered_total += curr_size_bytes;
7917                                         }
7918
7919                                         /* buffered size info from queue2 */
7920                                         if (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
7921                                         {
7922                                                 query = gst_query_new_buffering ( GST_FORMAT_BYTES );
7923                                                 if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query))
7924                                                 {
7925                                                         GstBufferingMode mode;
7926                                                         gint byte_in_rate = 0, byte_out_rate = 0;
7927                                                         gint64 start_byte = 0, stop_byte = 0;
7928                                                         guint num_of_ranges = 0;
7929                                                         guint idx = 0;
7930
7931                                                         num_of_ranges = gst_query_get_n_buffering_ranges(query);
7932                                                         for ( idx=0 ; idx<num_of_ranges ; idx++ )
7933                                                         {
7934                                                                 gst_query_parse_nth_buffering_range (query, idx, &start_byte, &stop_byte);
7935                                                                 debug_log ("[Q2][range %d] %lld ~ %lld\n", idx, start_byte, stop_byte);
7936
7937                                                                 buffered_total += (stop_byte - start_byte);
7938                                                         }
7939
7940                                                         gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, &buffering_left);
7941                                                         debug_log ("[Q2] in_rate %d, out_rate %d, left %lld\n", byte_in_rate, byte_out_rate, buffering_left);
7942                                                 }
7943                                                 gst_query_unref (query);
7944                                         }
7945
7946                                         if (buffering_left == STREAMING_IS_FINISHED)
7947                                         {
7948                                                 stop_per = BUFFERING_MAX_PER;
7949                                         }
7950                                         else
7951                                         {
7952                                                 guint dur_sec = (guint)(content_duration/GST_SECOND);
7953                                                 guint avg_byterate = (dur_sec>0)?((guint)(content_size/dur_sec)):(0);
7954
7955                                                 if (avg_byterate > 0)
7956                                                         buffered_sec = (gint)(buffered_total/avg_byterate);
7957                                                 else if (player->total_maximum_bitrate > 0)
7958                                                         buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_maximum_bitrate);
7959                                                 else if (player->total_bitrate > 0)
7960                                                         buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_bitrate);
7961
7962                                                 if ((buffered_sec >= 0) && (dur_sec > 0))
7963                                                         stop_per = start_per + (100 * buffered_sec / dur_sec);
7964                                         }
7965
7966                                         debug_log ("[Buffered Total] %lld bytes, %d sec, per %d~%d\n", buffered_total, buffered_sec, start_per, stop_per);
7967                                 }
7968                         }
7969
7970                         if (((buffered_total == 0) || (start_per < 0) || (stop_per < 0)) &&
7971                                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
7972                         {
7973                                 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
7974                                 if ( gst_element_query ( player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query ) )
7975                                 {
7976                                         GstFormat format;
7977                                         gint64 range_start_per = -1, range_stop_per = -1;
7978
7979                                         gst_query_parse_buffering_range ( query, &format, &range_start_per, &range_stop_per, NULL );
7980
7981                                         debug_log ("[Q2] range start %" G_GINT64_FORMAT " ~ stop %" G_GINT64_FORMAT "\n",  range_start_per , range_stop_per);
7982
7983                                         if (range_start_per != -1)
7984                                                 start_per = (gint)(100 * range_start_per / GST_FORMAT_PERCENT_MAX);
7985
7986                                         if (range_stop_per != -1)
7987                                                 stop_per = (gint)(100 * range_stop_per / GST_FORMAT_PERCENT_MAX);
7988                                 }
7989                                 gst_query_unref (query);
7990                         }
7991
7992                         if ( start_per > 0)
7993                                 *start_pos = (start_per < 100)?(start_per):(100);
7994                         else
7995                                 *start_pos = 0;
7996
7997                         if ( stop_per > 0)
7998                                 *stop_pos = (stop_per < 100)?(stop_per):(100);
7999                         else
8000                                 *stop_pos = 0;
8001
8002                         break;
8003                 }
8004                 case MM_PLAYER_POS_FORMAT_TIME :
8005                         debug_warning ( "Time format is not supported yet.\n" );
8006                         break;
8007
8008                 default :
8009                         break;
8010         }
8011
8012         debug_log("current buffer position : %lu~%lu \n", *start_pos, *stop_pos );
8013
8014         return MM_ERROR_NONE;
8015 }
8016
8017 static int
8018 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param) // @
8019 {
8020         MMPLAYER_FENTER();
8021
8022         if ( !player )
8023         {
8024                 debug_warning("set_message_callback is called with invalid player handle\n");
8025                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
8026         }
8027
8028         player->msg_cb = callback;
8029         player->msg_cb_param = user_param;
8030
8031         debug_log("msg_cb : %p     msg_cb_param : %p\n", callback, user_param);
8032
8033         MMPLAYER_FLEAVE();
8034
8035         return MM_ERROR_NONE;
8036 }
8037
8038 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
8039 {
8040         int ret = MM_ERROR_PLAYER_INVALID_URI;
8041         char *path = NULL;
8042
8043         MMPLAYER_FENTER();
8044
8045         return_val_if_fail ( uri , FALSE);
8046         return_val_if_fail ( data , FALSE);
8047         return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
8048
8049         memset(data, 0, sizeof(MMPlayerParseProfile));
8050
8051         if ((path = strstr(uri, "file://")))
8052         {
8053                 int file_stat = MM_ERROR_NONE;
8054
8055                 file_stat = util_exist_file_path(path + 7);
8056
8057                 if (file_stat == MM_ERROR_NONE)
8058                 {
8059                         strncpy(data->uri, path, MM_MAX_URL_LEN-1);
8060
8061                         if ( util_is_sdp_file ( path ) )
8062                         {
8063                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8064                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8065                         }
8066                         else
8067                         {
8068                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8069                         }
8070                         ret = MM_ERROR_NONE;
8071                 }
8072                 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
8073                 {
8074                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8075                 }
8076                 else
8077                 {
8078                         debug_warning("could  access %s.\n", path);
8079                 }
8080         }
8081         else if ((path = strstr(uri, "es_buff://")))
8082         {
8083                 if (strlen(path))
8084                 {
8085                         strcpy(data->uri, uri);
8086                         data->uri_type = MM_PLAYER_URI_TYPE_ES_BUFF;
8087                         ret = MM_ERROR_NONE;
8088                 }
8089         }
8090         else if ((path = strstr(uri, "buff://")))
8091         {
8092                         data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
8093                         ret = MM_ERROR_NONE;
8094         }
8095         else if ((path = strstr(uri, "rtsp://")))
8096         {
8097                 if (strlen(path)) {
8098                         if((path = strstr(uri, "/wfd1.0/"))) {
8099                                 strcpy(data->uri, uri);
8100                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_WFD;
8101                                 ret = MM_ERROR_NONE;
8102                                 debug_log("uri is actually a wfd client path. giving it to wfdrtspsrc\n");
8103                         }
8104                         else {
8105                                 strcpy(data->uri, uri);
8106                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8107                                 ret = MM_ERROR_NONE;
8108                         }
8109                 }
8110         }
8111         else if ((path = strstr(uri, "http://")))
8112         {
8113                 if (strlen(path)) {
8114                         strcpy(data->uri, uri);
8115
8116                         if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
8117                                 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
8118                         {
8119                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
8120                         }
8121                         else
8122                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
8123
8124                         ret = MM_ERROR_NONE;
8125                 }
8126         }
8127         else if ((path = strstr(uri, "https://")))
8128         {
8129                 if (strlen(path)) {
8130                         strcpy(data->uri, uri);
8131
8132                 if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
8133                                 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
8134                         {
8135                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
8136                         }
8137
8138                         data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
8139
8140                         ret = MM_ERROR_NONE;
8141                 }
8142         }
8143         else if ((path = strstr(uri, "rtspu://")))
8144         {
8145                 if (strlen(path)) {
8146                         strcpy(data->uri, uri);
8147                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8148                         ret = MM_ERROR_NONE;
8149                 }
8150         }
8151         else if ((path = strstr(uri, "rtspr://")))
8152         {
8153                 strcpy(data->uri, path);
8154                 char *separater =strstr(path, "*");
8155
8156                 if (separater) {
8157                         int urgent_len = 0;
8158                         char *urgent = separater + strlen("*");
8159
8160                         if ((urgent_len = strlen(urgent))) {
8161                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
8162                                 strcpy(data->urgent, urgent);
8163                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8164                                 ret = MM_ERROR_NONE;
8165                         }
8166                 }
8167         }
8168         else if ((path = strstr(uri, "mms://")))
8169         {
8170                 if (strlen(path)) {
8171                         strcpy(data->uri, uri);
8172                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
8173                         ret = MM_ERROR_NONE;
8174                 }
8175         }
8176         else if ((path = strstr(uri, "mem://")))
8177         {
8178                 if (strlen(path)) {
8179                         int mem_size = 0;
8180                         char *buffer = NULL;
8181                         char *seperator = strchr(path, ',');
8182                         char ext[100] = {0,}, size[100] = {0,};
8183
8184                         if (seperator) {
8185                                 if ((buffer = strstr(path, "ext="))) {
8186                                         buffer += strlen("ext=");
8187
8188                                         if (strlen(buffer)) {
8189                                                 strcpy(ext, buffer);
8190
8191                                                 if ((seperator = strchr(ext, ','))
8192                                                         || (seperator = strchr(ext, ' '))
8193                                                         || (seperator = strchr(ext, '\0'))) {
8194                                                         seperator[0] = '\0';
8195                                                 }
8196                                         }
8197                                 }
8198
8199                                 if ((buffer = strstr(path, "size="))) {
8200                                         buffer += strlen("size=");
8201
8202                                         if (strlen(buffer) > 0) {
8203                                                 strcpy(size, buffer);
8204
8205                                                 if ((seperator = strchr(size, ','))
8206                                                         || (seperator = strchr(size, ' '))
8207                                                         || (seperator = strchr(size, '\0'))) {
8208                                                         seperator[0] = '\0';
8209                                                 }
8210
8211                                                 mem_size = atoi(size);
8212                                         }
8213                                 }
8214                         }
8215
8216                         debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
8217                         if ( mem_size && param)
8218                         {
8219                                 data->mem = param;
8220                                 data->mem_size = mem_size;
8221                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
8222                                 ret = MM_ERROR_NONE;
8223                         }
8224                 }
8225         }
8226         else
8227         {
8228                 int file_stat = MM_ERROR_NONE;
8229
8230                 file_stat = util_exist_file_path(uri);
8231
8232                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
8233                 if (file_stat == MM_ERROR_NONE)
8234                 {
8235                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", uri);
8236
8237                         if ( util_is_sdp_file( (char*)uri ) )
8238                         {
8239                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8240                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8241                         }
8242                         else
8243                         {
8244                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8245                         }
8246                         ret = MM_ERROR_NONE;
8247                 }
8248                 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
8249                 {
8250                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8251                 }
8252                 else
8253                 {
8254                         debug_error ("invalid uri, could not play..\n");
8255                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8256                 }
8257         }
8258
8259         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
8260                 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
8261         } else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION){
8262                 ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
8263         }
8264
8265         /* dump parse result */
8266         secure_debug_warning("incomming uri : %s\n", uri);
8267         debug_log("uri_type : %d, mem : %p, mem_size : %d, urgent : %s\n",
8268                 data->uri_type, data->mem, data->mem_size, data->urgent);
8269
8270         MMPLAYER_FLEAVE();
8271
8272         return ret;
8273 }
8274
8275 gboolean _asm_postmsg(gpointer *data)
8276 {
8277         mm_player_t* player = (mm_player_t*)data;
8278         MMMessageParamType msg = {0, };
8279
8280         MMPLAYER_FENTER();
8281         return_val_if_fail ( player, FALSE );
8282         debug_warning("get notified");
8283
8284         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
8285                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
8286         {
8287                 debug_warning("dispatched");
8288                 return FALSE;
8289         }
8290
8291
8292         msg.union_type = MM_MSG_UNION_CODE;
8293         msg.code = player->sound_focus.focus_changed_msg;
8294
8295 #if 0 // should remove
8296         if (player->sm.event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
8297         {
8298                 /* fill the message with state of player */
8299                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
8300                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
8301                 player->resumable_cancel_id = 0;
8302         }
8303         else
8304 #endif
8305         {
8306                 MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
8307                 player->resume_event_id = 0;
8308         }
8309
8310         debug_warning("dispatched");
8311         return FALSE;
8312 }
8313
8314 gboolean _asm_lazy_pause(gpointer *data)
8315 {
8316         mm_player_t* player = (mm_player_t*)data;
8317         int ret = MM_ERROR_NONE;
8318
8319         MMPLAYER_FENTER();
8320
8321         return_val_if_fail ( player, FALSE );
8322
8323         if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
8324         {
8325                 debug_log ("Ready to proceed lazy pause\n");
8326                 ret = _mmplayer_pause((MMHandleType)player);
8327                 if(MM_ERROR_NONE != ret)
8328                 {
8329                         debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
8330                 }
8331         }
8332         else
8333         {
8334                 debug_log ("Invalid state to proceed lazy pause\n");
8335         }
8336
8337         /* unset mute */
8338         if (player->pipeline && player->pipeline->audiobin)
8339                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
8340
8341         player->sound_focus.by_asm_cb = FALSE; //should be reset here
8342
8343         MMPLAYER_FLEAVE();
8344
8345         return FALSE;
8346 }
8347
8348 static gboolean
8349 __mmplayer_can_do_interrupt(mm_player_t *player)
8350 {
8351         if (!player || !player->pipeline || !player->attrs)
8352         {
8353                 debug_warning("not initialized");
8354                 goto FAILED;
8355         }
8356
8357         if ((player->sound_focus.exit_cb) || (player->set_mode.pcm_extraction))
8358         {
8359                 debug_warning("leave from asm cb right now, %d, %d", player->sound_focus.exit_cb, player->set_mode.pcm_extraction);
8360                 goto FAILED;
8361         }
8362
8363         /* check if seeking */
8364         if (player->doing_seek)
8365         {
8366                 MMMessageParamType msg_param;
8367                 memset (&msg_param, 0, sizeof(MMMessageParamType));
8368                 msg_param.code = MM_ERROR_PLAYER_SEEK;
8369                 player->doing_seek = FALSE;
8370                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
8371                 goto FAILED;
8372         }
8373
8374         /* check other thread */
8375         if (!g_mutex_trylock(&player->cmd_lock))
8376         {
8377                 debug_warning("locked already, cmd state : %d", player->cmd);
8378
8379                 /* check application command */
8380                 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)
8381                 {
8382                         debug_warning("playing.. should wait cmd lock then, will be interrupted");
8383                         g_mutex_lock(&player->cmd_lock);
8384                         goto INTERRUPT;
8385                 }
8386                 debug_warning("nothing to do");
8387                 goto FAILED;
8388         }
8389         else
8390         {
8391                 debug_warning("can interrupt immediately");
8392                 goto INTERRUPT;
8393         }
8394
8395 FAILED:
8396         return FALSE;
8397
8398 INTERRUPT:
8399         return TRUE;
8400 }
8401
8402 /* if you want to enable USE_ASM, please check the history get the ASM cb code. */
8403 static int
8404 __mmplayer_convert_sound_focus_state(gboolean acquire, const char *reason_for_change, MMPlayerFocusChangedMsg *msg)
8405 {
8406         int ret = MM_ERROR_NONE;
8407         MMPlayerFocusChangedMsg focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
8408
8409         if (strstr(reason_for_change, "alarm")) {
8410                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_ALARM;
8411
8412         } else if (strstr(reason_for_change, "notification")) {
8413                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_NOTIFICATION;
8414
8415         } else if (strstr(reason_for_change, "emergency")) {
8416                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_EMERGENCY;
8417
8418         } else if (strstr(reason_for_change, "call-voice") ||
8419                strstr(reason_for_change, "call-video") ||
8420                strstr(reason_for_change, "voip") ||
8421                strstr(reason_for_change, "ringtone-voip") ||
8422                strstr(reason_for_change, "ringtone-call")) {
8423                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_CALL;
8424
8425         } else if (strstr(reason_for_change, "media") ||
8426                                 strstr(reason_for_change, "radio") ||
8427                                 strstr(reason_for_change, "loopback") ||
8428                                 strstr(reason_for_change, "system") ||
8429                                 strstr(reason_for_change, "voice-information") ||
8430                                 strstr(reason_for_change, "voice-recognition")) {
8431                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_MEDIA;
8432
8433         } else {
8434                 ret = MM_ERROR_INVALID_ARGUMENT;
8435                 debug_warning("not supported reason(%s), err(0x%08x)", reason_for_change, ret);
8436                 goto DONE;
8437         }
8438
8439         if (acquire && (focus_msg != MM_PLAYER_FOCUS_CHANGED_BY_MEDIA))
8440         {
8441                 /* can acqurie */
8442                 focus_msg = MM_PLAYER_FOCUS_CHANGED_COMPLETED;
8443         }
8444
8445         debug_log("converted from reason(%s) to msg(%d)", reason_for_change, focus_msg);
8446         *msg = focus_msg;
8447
8448 DONE:
8449         return ret;
8450 }
8451
8452 /* FIXME: will be updated with new funct */
8453 void __mmplayer_sound_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
8454                                        const char *reason_for_change, const char *additional_info, void *user_data)
8455 {
8456         mm_player_t* player = (mm_player_t*) user_data;
8457         int result = MM_ERROR_NONE;
8458         MMPlayerFocusChangedMsg msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
8459
8460         debug_warning("focus watch notified");
8461
8462         if (!__mmplayer_can_do_interrupt(player))
8463         {
8464                 debug_warning("no need to interrupt, so leave");
8465                 goto EXIT;
8466         }
8467
8468         if (player->sound_focus.session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE)
8469         {
8470                 debug_warning("flags is UNINTERRUPTIBLE. do nothing.");
8471                 goto EXIT;
8472         }
8473
8474         debug_warning("watch: state: %d, focus_type : %d, reason_for_change : %s",
8475                 focus_state, focus_type, (reason_for_change?reason_for_change:"N/A"));
8476
8477         player->sound_focus.cb_pending = TRUE;
8478         player->sound_focus.by_asm_cb = TRUE;
8479
8480         if (focus_state == FOCUS_IS_ACQUIRED)
8481         {
8482                 debug_warning("watch: FOCUS_IS_ACQUIRED");
8483                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(FALSE, reason_for_change, &msg))
8484                 {
8485                         player->sound_focus.focus_changed_msg = (int)msg;
8486                 }
8487
8488                 if (strstr(reason_for_change, "call") ||
8489                         strstr(reason_for_change, "voip") ||    /* FIXME: to check */
8490                         strstr(reason_for_change, "alarm") ||
8491                         strstr(reason_for_change, "media"))
8492                 {
8493                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
8494                         {
8495                                 // hold 0.7 second to excute "fadedown mute" effect
8496                                 debug_warning ("do fade down->pause->undo fade down");
8497
8498                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8499
8500                                 result = _mmplayer_pause((MMHandleType)player);
8501                                 if (result != MM_ERROR_NONE)
8502                                 {
8503                                         debug_warning("fail to set Pause state by asm");
8504                                         goto EXIT;
8505                                 }
8506                                 __mmplayer_undo_sound_fadedown(player);
8507                         }
8508                         else
8509                         {
8510                                 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
8511                                 _mmplayer_unrealize((MMHandleType)player);
8512                         }
8513                 }
8514                 else
8515                 {
8516                         debug_warning ("pause immediately");
8517                         result = _mmplayer_pause((MMHandleType)player);
8518                         if (result != MM_ERROR_NONE)
8519                         {
8520                                 debug_warning("fail to set Pause state by asm");
8521                                 goto EXIT;
8522                         }
8523                 }
8524         }
8525         else if (focus_state == FOCUS_IS_RELEASED)
8526         {
8527                 debug_warning("FOCUS_IS_RELEASED: Got msg from asm to resume");
8528                 player->sound_focus.antishock = TRUE;
8529                 player->sound_focus.by_asm_cb = FALSE;
8530
8531                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(TRUE, reason_for_change, &msg))
8532                 {
8533                         player->sound_focus.focus_changed_msg = (int)msg;
8534                 }
8535
8536                 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
8537                 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
8538                 goto DONE;
8539         }
8540         else
8541         {
8542                 debug_warning("unknown focus state %d", focus_state);
8543         }
8544
8545 DONE:
8546         player->sound_focus.by_asm_cb = FALSE;
8547         player->sound_focus.cb_pending = FALSE;
8548         MMPLAYER_CMD_UNLOCK( player );
8549
8550 EXIT:
8551         debug_warning("dispatched");
8552         return;
8553 }
8554
8555 void
8556 __mmplayer_sound_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
8557         const char *reason_for_change, const char *additional_info, void *user_data)
8558 {
8559         mm_player_t* player = (mm_player_t*) user_data;
8560         int result = MM_ERROR_NONE;
8561         gboolean lazy_pause = FALSE;
8562         MMPlayerFocusChangedMsg msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
8563
8564         debug_warning("get focus notified");
8565
8566         if (!__mmplayer_can_do_interrupt(player))
8567         {
8568                 debug_warning("no need to interrupt, so leave");
8569                 goto EXIT;
8570         }
8571
8572         if (player->sound_focus.session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE)
8573         {
8574                 debug_warning("flags is UNINTERRUPTIBLE. do nothing.");
8575                 goto EXIT;
8576         }
8577
8578         debug_warning("state: %d, focus_type : %d, reason_for_change : %s",
8579                 focus_state, focus_type, (reason_for_change?reason_for_change:"N/A"));
8580
8581         player->sound_focus.cb_pending = TRUE;
8582         player->sound_focus.by_asm_cb = TRUE;
8583 //      player->sound_focus.event_src = event_src;
8584
8585 #if 0
8586         /* first, check event source */
8587         if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG)
8588         {
8589                 int stop_by_asm = 0;
8590                 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
8591                 if (!stop_by_asm)
8592                         goto DONE;
8593         }
8594         else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
8595         {
8596                 /* can use video overlay simultaneously */
8597                 /* video resource conflict */
8598                 if(player->pipeline->videobin)
8599                 {
8600                         debug_log("video conflict but, can support multiple video");
8601                         result = _mmplayer_pause((MMHandleType)player);
8602                         cb_res = ASM_CB_RES_PAUSE;
8603                 }
8604                 else if (player->pipeline->audiobin)
8605                 {
8606                         debug_log("audio resource conflict");
8607                         result = _mmplayer_pause((MMHandleType)player);
8608                         if (result != MM_ERROR_NONE)
8609                         {
8610                                 debug_warning("fail to set pause by asm");
8611                         }
8612                         cb_res = ASM_CB_RES_PAUSE;
8613                 }
8614                 goto DONE;
8615         }
8616 #if 0 // should remove
8617         else if (event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
8618         {
8619                 debug_warning("Got msg from asm for resumable canceled.\n");
8620                 player->sound_focus.antishock = TRUE;
8621                 player->sound_focus.by_asm_cb = FALSE;
8622
8623                 player->resumable_cancel_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
8624                 cb_res = ASM_CB_RES_IGNORE;
8625                 goto DONE;
8626         }
8627 #endif
8628 #endif
8629
8630         if (focus_state == FOCUS_IS_RELEASED)
8631         {
8632                 debug_warning("FOCUS_IS_RELEASED");
8633
8634                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(FALSE, reason_for_change, &msg))
8635                 {
8636                         player->sound_focus.focus_changed_msg = (int)msg;
8637                 }
8638
8639                 if (strstr(reason_for_change, "call") ||
8640                         strstr(reason_for_change, "voip") ||    /* FIXME: to check */
8641                         strstr(reason_for_change, "alarm") ||
8642                         strstr(reason_for_change, "media"))
8643                 {
8644                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
8645                         {
8646                                 //hold 0.7 second to excute "fadedown mute" effect
8647                                 debug_warning ("do fade down->pause->undo fade down");
8648
8649                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8650
8651                                 result = _mmplayer_pause((MMHandleType)player);
8652                                 if (result != MM_ERROR_NONE)
8653                                 {
8654                                         debug_warning("fail to set Pause state by asm");
8655                                         goto EXIT;
8656                                 }
8657                                 __mmplayer_undo_sound_fadedown(player);
8658                         }
8659                         else
8660                         {
8661                                 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
8662                                 _mmplayer_unrealize((MMHandleType)player);
8663                         }
8664                 }
8665                 else
8666                 {
8667                         debug_warning ("pause immediately");
8668                         result = _mmplayer_pause((MMHandleType)player);
8669                         if (result != MM_ERROR_NONE)
8670                         {
8671                                 debug_warning("fail to set Pause state by asm");
8672                                 goto EXIT;
8673                         }
8674                 }
8675         }
8676         else if (focus_state == FOCUS_IS_ACQUIRED)
8677         {
8678                 debug_warning("FOCUS_IS_ACQUIRED: Got msg from asm to resume");
8679                 player->sound_focus.antishock = TRUE;
8680                 player->sound_focus.by_asm_cb = FALSE;
8681
8682                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(TRUE, reason_for_change, &msg))
8683                 {
8684                         player->sound_focus.focus_changed_msg = (int)msg;
8685                 }
8686
8687                 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
8688                 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
8689                 goto DONE;
8690         }
8691         else
8692         {
8693                 debug_warning("unknown focus state %d", focus_state);
8694         }
8695
8696 DONE:
8697         if ( !lazy_pause )
8698         {
8699                 player->sound_focus.by_asm_cb = FALSE;
8700         }
8701         player->sound_focus.cb_pending = FALSE;
8702         MMPLAYER_CMD_UNLOCK( player );
8703
8704 EXIT:
8705         debug_warning("dispatched");
8706         return;
8707 }
8708
8709
8710 int
8711 _mmplayer_create_player(MMHandleType handle) // @
8712 {
8713         mm_player_t* player = MM_PLAYER_CAST(handle);
8714
8715         MMPLAYER_FENTER();
8716
8717         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
8718
8719         /* initialize player state */
8720         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
8721         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
8722         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
8723         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
8724
8725         /* check current state */
8726         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
8727
8728         /* construct attributes */
8729         player->attrs = _mmplayer_construct_attribute(handle);
8730
8731         if ( !player->attrs )
8732         {
8733                 debug_error("Failed to construct attributes\n");
8734                 goto ERROR;
8735         }
8736
8737         /* initialize gstreamer with configured parameter */
8738         if ( ! __mmplayer_init_gstreamer(player) )
8739         {
8740                 debug_error("Initializing gstreamer failed\n");
8741                 goto ERROR;
8742         }
8743
8744         /* initialize factories if not using decodebin */
8745         if( player->factories == NULL )
8746                 __mmplayer_init_factories(player);
8747
8748         /* create lock. note that g_tread_init() has already called in gst_init() */
8749         g_mutex_init(&player->fsink_lock);
8750
8751         /* create repeat mutex */
8752         g_mutex_init(&player->repeat_thread_mutex);
8753
8754         /* create repeat cond */
8755         g_cond_init(&player->repeat_thread_cond);
8756
8757         /* create repeat thread */
8758         player->repeat_thread =
8759                 g_thread_try_new ("repeat_thread", __mmplayer_repeat_thread, (gpointer)player, NULL);
8760
8761
8762         /* create next play mutex */
8763         g_mutex_init(&player->next_play_thread_mutex);
8764
8765         /* create next play cond */
8766         g_cond_init(&player->next_play_thread_cond);
8767
8768         /* create next play thread */
8769         player->next_play_thread =
8770                 g_thread_try_new ("next_play_thread", __mmplayer_next_play_thread, (gpointer)player, NULL);
8771         if ( ! player->next_play_thread )
8772         {
8773                 debug_error("failed to create next play thread");
8774                 goto ERROR;
8775         }
8776
8777         if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
8778         {
8779                 debug_error("failed to initialize video capture\n");
8780                 goto ERROR;
8781         }
8782
8783         /* register to asm */
8784         if ( MM_ERROR_NONE != _mmplayer_sound_register(&player->sound_focus,
8785                                                 (mm_sound_focus_changed_cb)__mmplayer_sound_focus_callback,
8786                                                 (mm_sound_focus_changed_watch_cb)__mmplayer_sound_focus_watch_callback,
8787                                                 (void*)player) )
8788
8789         {
8790                 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
8791                 debug_error("failed to register asm server\n");
8792                 return MM_ERROR_POLICY_INTERNAL;
8793         }
8794 #if 0 //need to change and test
8795         /* to add active device callback */
8796         if ( MM_ERROR_NONE != mm_sound_add_device_information_changed_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, __mmplayer_sound_device_info_changed_cb_func, (void*)player))
8797         {
8798                 debug_error("failed mm_sound_add_device_information_changed_callback \n");
8799         }
8800 #endif
8801         if (MMPLAYER_IS_HTTP_PD(player))
8802         {
8803                 player->pd_downloader = NULL;
8804                 player->pd_file_save_path = NULL;
8805         }
8806
8807         player->streaming_type = STREAMING_SERVICE_NONE;
8808
8809         /* give default value of audio effect setting */
8810         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
8811         player->playback_rate = DEFAULT_PLAYBACK_RATE;
8812
8813         player->play_subtitle = FALSE;
8814         player->use_textoverlay = FALSE;
8815         player->play_count = 0;
8816         player->use_decodebin = TRUE;
8817         player->ignore_asyncdone = FALSE;
8818         player->use_deinterleave = FALSE;
8819         player->max_audio_channels = 0;
8820         player->video_share_api_delta = 0;
8821         player->video_share_clock_delta = 0;
8822         player->has_closed_caption = FALSE;
8823
8824         __mmplayer_post_proc_reset(player);
8825
8826         if (player->ini.dump_element_keyword[0][0] == '\0')
8827         {
8828                 player->ini.set_dump_element_flag= FALSE;
8829         }
8830         else
8831         {
8832                 player->ini.set_dump_element_flag = TRUE;
8833         }
8834
8835         /* set player state to null */
8836         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
8837         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
8838
8839         return MM_ERROR_NONE;
8840
8841 ERROR:
8842         /* free lock */
8843         g_mutex_clear(&player->fsink_lock );
8844
8845         /* free thread */
8846         if ( player->repeat_thread )
8847         {
8848                 player->repeat_thread_exit = TRUE;
8849                 g_cond_signal( &player->repeat_thread_cond );
8850
8851                 g_thread_join( player->repeat_thread );
8852                 player->repeat_thread = NULL;
8853
8854                 g_mutex_clear(&player->repeat_thread_mutex );
8855
8856                 g_cond_clear (&player->repeat_thread_cond );
8857         }
8858         /* clear repeat thread mutex/cond if still alive
8859          * this can happen if only thread creating has failed
8860          */
8861         g_mutex_clear(&player->repeat_thread_mutex );
8862         g_cond_clear ( &player->repeat_thread_cond );
8863
8864         /* free next play thread */
8865         if ( player->next_play_thread )
8866         {
8867                 player->next_play_thread_exit = TRUE;
8868                 g_cond_signal( &player->next_play_thread_cond );
8869
8870                 g_thread_join( player->next_play_thread );
8871                 player->next_play_thread = NULL;
8872
8873                 g_mutex_clear(&player->next_play_thread_mutex );
8874
8875                 g_cond_clear ( &player->next_play_thread_cond );
8876         }
8877         /* clear next play thread mutex/cond if still alive
8878          * this can happen if only thread creating has failed
8879          */
8880         g_mutex_clear(&player->next_play_thread_mutex );
8881
8882         g_cond_clear ( &player->next_play_thread_cond );
8883
8884         /* release attributes */
8885         _mmplayer_deconstruct_attribute(handle);
8886
8887         MMPLAYER_FLEAVE();
8888
8889         return MM_ERROR_PLAYER_INTERNAL;
8890 }
8891
8892 static gboolean
8893 __mmplayer_init_gstreamer(mm_player_t* player) // @
8894 {
8895         static gboolean initialized = FALSE;
8896         static const int max_argc = 50;
8897         gint* argc = NULL;
8898         gchar** argv = NULL;
8899         gchar** argv2 = NULL;
8900         GError *err = NULL;
8901         int i = 0;
8902         int arg_count = 0;
8903
8904         if ( initialized )
8905         {
8906                 debug_log("gstreamer already initialized.\n");
8907                 return TRUE;
8908         }
8909
8910         /* alloc */
8911         argc = malloc( sizeof(int) );
8912         argv = malloc( sizeof(gchar*) * max_argc );
8913         argv2 = malloc( sizeof(gchar*) * max_argc );
8914
8915         if ( !argc || !argv || !argv2)
8916                 goto ERROR;
8917
8918         memset( argv, 0, sizeof(gchar*) * max_argc );
8919         memset( argv2, 0, sizeof(gchar*) * max_argc );
8920
8921         /* add initial */
8922         *argc = 1;
8923         argv[0] = g_strdup( "mmplayer" );
8924
8925         /* add gst_param */
8926         for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
8927         {
8928                 if ( strlen( player->ini.gst_param[i] ) > 0 )
8929                 {
8930                         argv[*argc] = g_strdup( player->ini.gst_param[i] );
8931                         (*argc)++;
8932                 }
8933         }
8934
8935         /* we would not do fork for scanning plugins */
8936         argv[*argc] = g_strdup("--gst-disable-registry-fork");
8937         (*argc)++;
8938
8939         /* check disable registry scan */
8940         if ( player->ini.skip_rescan )
8941         {
8942                 argv[*argc] = g_strdup("--gst-disable-registry-update");
8943                 (*argc)++;
8944         }
8945
8946         /* check disable segtrap */
8947         if ( player->ini.disable_segtrap )
8948         {
8949                 argv[*argc] = g_strdup("--gst-disable-segtrap");
8950                 (*argc)++;
8951         }
8952
8953         debug_log("initializing gstreamer with following parameter\n");
8954         debug_log("argc : %d\n", *argc);
8955         arg_count = *argc;
8956
8957         for ( i = 0; i < arg_count; i++ )
8958         {
8959                 argv2[i] = argv[i];
8960                 debug_log("argv[%d] : %s\n", i, argv2[i]);
8961         }
8962
8963
8964         /* initializing gstreamer */
8965         if ( ! gst_init_check (argc, &argv, &err))
8966         {
8967                 debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
8968                 if (err)
8969                 {
8970                         g_error_free (err);
8971                 }
8972
8973                 goto ERROR;
8974         }
8975         /* release */
8976         for ( i = 0; i < arg_count; i++ )
8977         {
8978                 //debug_log("release - argv[%d] : %s\n", i, argv2[i]);
8979                 MMPLAYER_FREEIF( argv2[i] );
8980         }
8981
8982         MMPLAYER_FREEIF( argv );
8983         MMPLAYER_FREEIF( argv2 );
8984         MMPLAYER_FREEIF( argc );
8985
8986         /* done */
8987         initialized = TRUE;
8988
8989         return TRUE;
8990
8991 ERROR:
8992
8993         /* release */
8994         for ( i = 0; i < arg_count; i++ )
8995         {
8996                 debug_log("free[%d] : %s\n", i, argv2[i]);
8997                 MMPLAYER_FREEIF( argv2[i] );
8998         }
8999
9000         MMPLAYER_FREEIF( argv );
9001         MMPLAYER_FREEIF( argv2 );
9002         MMPLAYER_FREEIF( argc );
9003
9004         return FALSE;
9005 }
9006
9007 int
9008 __mmplayer_destroy_streaming_ext(mm_player_t* player)
9009 {
9010         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9011
9012         if (player->pd_downloader)
9013         {
9014                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
9015                 MMPLAYER_FREEIF(player->pd_downloader);
9016         }
9017
9018         if (MMPLAYER_IS_HTTP_PD(player))
9019         {
9020                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
9021                 MMPLAYER_FREEIF(player->pd_file_save_path);
9022         }
9023
9024         return MM_ERROR_NONE;
9025 }
9026
9027 int
9028 _mmplayer_destroy(MMHandleType handle) // @
9029 {
9030         mm_player_t* player = MM_PLAYER_CAST(handle);
9031
9032         MMPLAYER_FENTER();
9033
9034         /* check player handle */
9035         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9036
9037         /* destroy can called at anytime */
9038         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
9039
9040         __mmplayer_destroy_streaming_ext(player);
9041
9042         /* release repeat thread */
9043         if ( player->repeat_thread )
9044         {
9045                 player->repeat_thread_exit = TRUE;
9046                 g_cond_signal( &player->repeat_thread_cond );
9047
9048                 debug_log("waitting for repeat thread exit\n");
9049                 g_thread_join ( player->repeat_thread );
9050                 g_mutex_clear(&player->repeat_thread_mutex );
9051                 g_cond_clear (&player->repeat_thread_cond );
9052                 debug_log("repeat thread released\n");
9053         }
9054
9055         /* release next play thread */
9056         if ( player->next_play_thread )
9057         {
9058                 player->next_play_thread_exit = TRUE;
9059                 g_cond_signal( &player->next_play_thread_cond );
9060
9061                 debug_log("waitting for next play thread exit\n");
9062                 g_thread_join ( player->next_play_thread );
9063                 g_mutex_clear(&player->next_play_thread_mutex );
9064                 g_cond_clear(&player->next_play_thread_cond );
9065                 debug_log("next play thread released\n");
9066         }
9067
9068         _mmplayer_release_video_capture(player);
9069
9070         /* flush any pending asm_cb */
9071         if (player->sound_focus.cb_pending)
9072         {
9073                 /* set a flag for make sure asm_cb to be returned immediately */
9074                 debug_warning("asm cb has pending state");
9075                 player->sound_focus.exit_cb = TRUE;
9076
9077                 /* make sure to release any pending asm_cb which locked by cmd_lock */
9078                 MMPLAYER_CMD_UNLOCK(player);
9079                 sched_yield();
9080                 MMPLAYER_CMD_LOCK(player);
9081         }
9082
9083         /* withdraw asm */
9084         if ( MM_ERROR_NONE != _mmplayer_sound_unregister(&player->sound_focus) )
9085         {
9086                 debug_error("failed to deregister asm server\n");
9087         }
9088
9089 #ifdef USE_LAZY_PAUSE
9090         if (player->lazy_pause_event_id)
9091         {
9092                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->lazy_pause_event_id);
9093                 player->lazy_pause_event_id = 0;
9094         }
9095 #endif
9096
9097         if (player->resume_event_id)
9098         {
9099                 g_source_remove (player->resume_event_id);
9100                 player->resume_event_id = 0;
9101         }
9102
9103         if (player->resumable_cancel_id)
9104         {
9105                 g_source_remove (player->resumable_cancel_id);
9106                 player->resumable_cancel_id = 0;
9107         }
9108
9109         /* release pipeline */
9110         if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
9111         {
9112                 debug_error("failed to destory pipeline\n");
9113                 return MM_ERROR_PLAYER_INTERNAL;
9114         }
9115
9116         if (player->is_external_subtitle_present && player->subtitle_language_list)
9117         {
9118           g_list_free (player->subtitle_language_list);
9119           player->subtitle_language_list = NULL;
9120         }
9121
9122         __mmplayer_release_dump_list (player->dump_list);
9123
9124         /* release miscellaneous information.
9125            these info needs to be released after pipeline is destroyed. */
9126         __mmplayer_release_misc_post( player );
9127
9128         /* release attributes */
9129         _mmplayer_deconstruct_attribute( handle );
9130
9131         /* release factories */
9132         __mmplayer_release_factories( player );
9133
9134         /* release lock */
9135         g_mutex_clear(&player->fsink_lock );
9136
9137         g_mutex_clear(&player->msg_cb_lock );
9138
9139         MMPLAYER_FLEAVE();
9140
9141         return MM_ERROR_NONE;
9142 }
9143
9144 int
9145 __mmplayer_realize_streaming_ext(mm_player_t* player)
9146 {
9147         int ret = MM_ERROR_NONE;
9148
9149         MMPLAYER_FENTER();
9150         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9151
9152         if (MMPLAYER_IS_HTTP_PD(player))
9153         {
9154                 gboolean bret = FALSE;
9155
9156                 player->pd_downloader = _mmplayer_create_pd_downloader();
9157                 if ( !player->pd_downloader )
9158                 {
9159                         debug_error ("Unable to create PD Downloader...");
9160                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
9161                 }
9162
9163                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
9164
9165                 if (FALSE == bret)
9166                 {
9167                         debug_error ("Unable to create PD Downloader...");
9168                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
9169                 }
9170         }
9171
9172         MMPLAYER_FLEAVE();
9173         return ret;
9174 }
9175
9176 int
9177 _mmplayer_realize(MMHandleType hplayer) // @
9178 {
9179         mm_player_t* player =  (mm_player_t*)hplayer;
9180         char *uri =NULL;
9181         void *param = NULL;
9182         int application_pid = -1;
9183         gboolean update_registry = FALSE;
9184         MMHandleType attrs = 0;
9185         int ret = MM_ERROR_NONE;
9186
9187         MMPLAYER_FENTER();
9188
9189         /* check player handle */
9190         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
9191
9192         /* check current state */
9193         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
9194
9195         attrs = MMPLAYER_GET_ATTRS(player);
9196         if ( !attrs )
9197         {
9198                 debug_error("fail to get attributes.\n");
9199                 return MM_ERROR_PLAYER_INTERNAL;
9200         }
9201
9202         mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
9203         player->sound_focus.pid = application_pid;
9204
9205         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
9206         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
9207
9208         ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
9209
9210         if (ret != MM_ERROR_NONE)
9211         {
9212                 debug_error("failed to parse profile\n");
9213                 return ret;
9214         }
9215
9216         /* FIXIT : we can use thouse in player->profile directly */
9217         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
9218         {
9219                 player->mem_buf.buf = (char *)player->profile.mem;
9220                 player->mem_buf.len = player->profile.mem_size;
9221                 player->mem_buf.offset = 0;
9222         }
9223
9224         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF)
9225         {
9226                 if (strstr(uri, "es_buff://push_mode"))
9227                 {
9228                         player->es_player_push_mode = TRUE;
9229                 }
9230                 else
9231                 {
9232                         player->es_player_push_mode = FALSE;
9233                 }
9234         }
9235
9236         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
9237         {
9238                 debug_warning("mms protocol is not supported format.\n");
9239                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
9240         }
9241
9242         if (MMPLAYER_IS_STREAMING(player))
9243                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
9244         else
9245                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
9246
9247         player->smooth_streaming = FALSE;
9248         player->videodec_linked  = 0;
9249         player->videosink_linked = 0;
9250         player->audiodec_linked  = 0;
9251         player->audiosink_linked = 0;
9252         player->textsink_linked = 0;
9253         player->is_external_subtitle_present = FALSE;
9254         /* set the subtitle ON default */
9255         player->is_subtitle_off = FALSE;
9256
9257         /* registry should be updated for downloadable codec */
9258         mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
9259
9260         if ( update_registry )
9261         {
9262                 debug_log("updating registry...\n");
9263                 gst_update_registry();
9264
9265                 /* then we have to rebuild factories */
9266                 __mmplayer_release_factories( player );
9267                 __mmplayer_init_factories(player);
9268         }
9269
9270         /* realize pipeline */
9271         ret = __gst_realize( player );
9272         if ( ret != MM_ERROR_NONE )
9273         {
9274                 debug_error("fail to realize the player.\n");
9275         }
9276         else
9277         {
9278                 ret = __mmplayer_realize_streaming_ext(player);
9279         }
9280
9281         MMPLAYER_FLEAVE();
9282
9283         return ret;
9284 }
9285
9286 int
9287 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
9288 {
9289         MMPLAYER_FENTER();
9290         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9291
9292         /* destroy can called at anytime */
9293         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
9294         {
9295                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
9296                 MMPLAYER_FREEIF(player->pd_downloader);
9297         }
9298
9299         MMPLAYER_FLEAVE();
9300         return MM_ERROR_NONE;
9301 }
9302
9303 int
9304 _mmplayer_unrealize(MMHandleType hplayer)
9305 {
9306         mm_player_t* player = (mm_player_t*)hplayer;
9307         int ret = MM_ERROR_NONE;
9308
9309         MMPLAYER_FENTER();
9310
9311         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
9312
9313         /* check current state */
9314         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
9315
9316         __mmplayer_unrealize_streaming_ext(player);
9317
9318         /* unrealize pipeline */
9319         ret = __gst_unrealize( player );
9320
9321         /* set asm stop if success */
9322         if (MM_ERROR_NONE == ret)
9323         {
9324                 ret = _mmplayer_sound_release_focus(&player->sound_focus);
9325                 if ( ret != MM_ERROR_NONE )
9326                 {
9327                         debug_error("failed to release sound focus\n");
9328                         return ret;
9329                 }
9330         }
9331         else
9332         {
9333                 debug_error("failed and don't change asm state to stop");
9334         }
9335
9336         MMPLAYER_FLEAVE();
9337
9338         return ret;
9339 }
9340
9341 int
9342 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
9343 {
9344         mm_player_t* player = (mm_player_t*)hplayer;
9345
9346         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9347
9348         return __gst_set_message_callback(player, callback, user_param);
9349 }
9350
9351 int
9352 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
9353 {
9354         mm_player_t *player = (mm_player_t*)hplayer;
9355
9356         return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
9357
9358         *state = MMPLAYER_CURRENT_STATE(player);
9359
9360         return MM_ERROR_NONE;
9361 }
9362
9363
9364 int
9365 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
9366 {
9367         mm_player_t* player = (mm_player_t*) hplayer;
9368         GstElement* vol_element = NULL;
9369         int i = 0;
9370
9371         MMPLAYER_FENTER();
9372
9373         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9374
9375         debug_log("volume [L]=%f:[R]=%f\n",
9376                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
9377
9378         /* invalid factor range or not */
9379         for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
9380         {
9381                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
9382                         debug_error("Invalid factor! (valid factor:0~1.0)\n");
9383                         return MM_ERROR_INVALID_ARGUMENT;
9384                 }
9385         }
9386
9387         /* not support to set other value into each channel */
9388         if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
9389                 return MM_ERROR_INVALID_ARGUMENT;
9390
9391         /* Save volume to handle. Currently the first array element will be saved. */
9392         player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
9393
9394         /* check pipeline handle */
9395         if ( ! player->pipeline || ! player->pipeline->audiobin )
9396         {
9397                 debug_log("audiobin is not created yet\n");
9398                 debug_log("but, current stored volume will be set when it's created.\n");
9399
9400                 /* NOTE : stored volume will be used in create_audiobin
9401                  * returning MM_ERROR_NONE here makes application to able to
9402                  * set volume at anytime.
9403                  */
9404                 return MM_ERROR_NONE;
9405         }
9406
9407         /* setting volume to volume element */
9408         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
9409
9410         if ( vol_element )
9411         {
9412                 debug_log("volume is set [%f]\n", player->sound.volume);
9413                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
9414         }
9415
9416         MMPLAYER_FLEAVE();
9417
9418         return MM_ERROR_NONE;
9419 }
9420
9421
9422 int
9423 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
9424 {
9425         mm_player_t* player = (mm_player_t*) hplayer;
9426         int i = 0;
9427
9428         MMPLAYER_FENTER();
9429
9430         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9431         return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
9432
9433         /* returning stored volume */
9434         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
9435                 volume->level[i] = player->sound.volume;
9436
9437         MMPLAYER_FLEAVE();
9438
9439         return MM_ERROR_NONE;
9440 }
9441
9442
9443
9444 int
9445 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
9446 {
9447         mm_player_t* player = (mm_player_t*) hplayer;
9448         GstElement* vol_element = NULL;
9449
9450         MMPLAYER_FENTER();
9451
9452         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9453
9454         /* mute value shoud 0 or 1 */
9455         if ( mute != 0 && mute != 1 )
9456         {
9457                 debug_error("bad mute value\n");
9458
9459                 /* FIXIT : definitly, we need _BAD_PARAM error code */
9460                 return MM_ERROR_INVALID_ARGUMENT;
9461         }
9462
9463         player->sound.mute = mute;
9464
9465         /* just hold mute value if pipeline is not ready */
9466         if ( !player->pipeline || !player->pipeline->audiobin )
9467         {
9468                 debug_log("pipeline is not ready. holding mute value\n");
9469                 return MM_ERROR_NONE;
9470         }
9471
9472         vol_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
9473
9474         /* NOTE : volume will only created when the bt is enabled */
9475         if ( vol_element )
9476         {
9477                 debug_log("mute : %d\n", mute);
9478                 g_object_set(vol_element, "mute", mute, NULL);
9479         }
9480         else
9481         {
9482                 debug_log("volume elemnet is not created. using volume in audiosink\n");
9483         }
9484
9485         MMPLAYER_FLEAVE();
9486
9487         return MM_ERROR_NONE;
9488 }
9489
9490 int
9491 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
9492 {
9493         mm_player_t* player = (mm_player_t*) hplayer;
9494
9495         MMPLAYER_FENTER();
9496
9497         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9498         return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
9499
9500         /* just hold mute value if pipeline is not ready */
9501         if ( !player->pipeline || !player->pipeline->audiobin )
9502         {
9503                 debug_log("pipeline is not ready. returning stored value\n");
9504                 *pmute = player->sound.mute;
9505                 return MM_ERROR_NONE;
9506         }
9507
9508         *pmute = player->sound.mute;
9509
9510         MMPLAYER_FLEAVE();
9511
9512         return MM_ERROR_NONE;
9513 }
9514
9515 int
9516 _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
9517 {
9518         mm_player_t* player = (mm_player_t*) hplayer;
9519
9520         MMPLAYER_FENTER();
9521
9522         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9523
9524         player->video_stream_changed_cb = callback;
9525         player->video_stream_changed_cb_user_param = user_param;
9526         debug_log("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
9527
9528         MMPLAYER_FLEAVE();
9529
9530         return MM_ERROR_NONE;
9531 }
9532
9533 int
9534 _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
9535 {
9536         mm_player_t* player = (mm_player_t*) hplayer;
9537
9538         MMPLAYER_FENTER();
9539
9540         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9541
9542         player->audio_stream_changed_cb = callback;
9543         player->audio_stream_changed_cb_user_param = user_param;
9544         debug_log("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
9545
9546         MMPLAYER_FLEAVE();
9547
9548         return MM_ERROR_NONE;
9549 }
9550
9551 int
9552 _mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param) // @
9553 {
9554         mm_player_t* player = (mm_player_t*) hplayer;
9555
9556         MMPLAYER_FENTER();
9557
9558         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9559
9560         player->audio_stream_render_cb_ex = callback;
9561         player->audio_stream_cb_user_param = user_param;
9562         player->audio_stream_sink_sync = sync;
9563         debug_log("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);
9564
9565         MMPLAYER_FLEAVE();
9566
9567         return MM_ERROR_NONE;
9568 }
9569
9570 int
9571 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
9572 {
9573         mm_player_t* player = (mm_player_t*) hplayer;
9574
9575         MMPLAYER_FENTER();
9576
9577         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9578
9579         player->video_stream_cb = callback;
9580         player->video_stream_cb_user_param = user_param;
9581         player->use_video_stream = TRUE;
9582         debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
9583
9584         MMPLAYER_FLEAVE();
9585
9586         return MM_ERROR_NONE;
9587 }
9588
9589 int
9590 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
9591 {
9592         mm_player_t* player = (mm_player_t*) hplayer;
9593
9594         MMPLAYER_FENTER();
9595
9596         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9597
9598         player->audio_stream_cb = callback;
9599         player->audio_stream_cb_user_param = user_param;
9600         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
9601
9602         MMPLAYER_FLEAVE();
9603
9604         return MM_ERROR_NONE;
9605 }
9606
9607 // set prepare size
9608 int
9609 _mmplayer_set_prepare_buffering_time(MMHandleType hplayer, int second)
9610 {
9611         mm_player_t* player = (mm_player_t*) hplayer;
9612
9613         MMPLAYER_FENTER();
9614
9615         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9616
9617         if (MMPLAYER_CURRENT_STATE(player) !=  MM_PLAYER_STATE_NULL)
9618                 return MM_ERROR_PLAYER_INVALID_STATE;
9619
9620         debug_log("pre buffer size : %d sec\n", second);
9621
9622         if ( second <= 0 )
9623         {
9624                 debug_error("bad size value\n");
9625                 return MM_ERROR_INVALID_ARGUMENT;
9626         }
9627
9628         if (player->streamer == NULL)
9629         {
9630                 player->streamer = __mm_player_streaming_create();
9631                 __mm_player_streaming_initialize(player->streamer);
9632         }
9633
9634         player->streamer->buffering_req.initial_second = second;
9635
9636         MMPLAYER_FLEAVE();
9637
9638         return MM_ERROR_NONE;
9639 }
9640
9641 // set runtime mode
9642 int
9643 _mmplayer_set_runtime_buffering_mode(MMHandleType hplayer, MMPlayerBufferingMode mode, int second)
9644 {
9645         mm_player_t* player = (mm_player_t*) hplayer;
9646
9647         MMPLAYER_FENTER();
9648
9649         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9650
9651         debug_log("mode %d\n", mode);
9652
9653         if ((mode < 0) || (mode > MM_PLAYER_BUFFERING_MODE_MAX) ||
9654                 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) && (second <= 0)))
9655                 return MM_ERROR_INVALID_ARGUMENT;
9656
9657         if (player->streamer == NULL)
9658         {
9659                 player->streamer = __mm_player_streaming_create();
9660                 __mm_player_streaming_initialize(player->streamer);
9661         }
9662
9663         player->streamer->buffering_req.mode = mode;
9664
9665         if ((second > 0) &&
9666                 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) ||
9667                  (mode == MM_PLAYER_BUFFERING_MODE_ADAPTIVE)))
9668                 player->streamer->buffering_req.runtime_second = second;
9669
9670         MMPLAYER_FLEAVE();
9671
9672         return MM_ERROR_NONE;
9673 }
9674
9675 int
9676 _mmplayer_set_videoframe_render_error_cb(MMHandleType hplayer, mm_player_video_frame_render_error_callback callback, void *user_param) // @
9677 {
9678         mm_player_t* player = (mm_player_t*) hplayer;
9679
9680         MMPLAYER_FENTER();
9681
9682         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9683         return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
9684
9685         player->video_frame_render_error_cb = callback;
9686         player->video_frame_render_error_cb_user_param = user_param;
9687
9688         debug_log("Video frame render error cb Handle value is %p : %p\n", player, player->video_frame_render_error_cb);
9689
9690         MMPLAYER_FLEAVE();
9691
9692         return MM_ERROR_NONE;
9693 }
9694
9695 int
9696 __mmplayer_start_streaming_ext(mm_player_t *player)
9697 {
9698         gint ret = MM_ERROR_NONE;
9699
9700         MMPLAYER_FENTER();
9701         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9702
9703         if (MMPLAYER_IS_HTTP_PD(player))
9704         {
9705                 if ( !player->pd_downloader )
9706                 {
9707                         ret = __mmplayer_realize_streaming_ext(player);
9708
9709                         if ( ret != MM_ERROR_NONE)
9710                         {
9711                                 debug_error ("failed to realize streaming ext\n");
9712                                 return ret;
9713                         }
9714                 }
9715
9716                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
9717                 {
9718                         ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
9719                         if ( !ret )
9720                         {
9721                                 debug_error ("ERROR while starting PD...\n");
9722                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
9723                         }
9724                         ret = MM_ERROR_NONE;
9725                 }
9726         }
9727
9728         MMPLAYER_FLEAVE();
9729         return ret;
9730 }
9731
9732 int
9733 _mmplayer_start(MMHandleType hplayer) // @
9734 {
9735         mm_player_t* player = (mm_player_t*) hplayer;
9736         gint ret = MM_ERROR_NONE;
9737
9738         MMPLAYER_FENTER();
9739
9740         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9741
9742         /* check current state */
9743         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
9744
9745         ret = _mmplayer_sound_acquire_focus(&player->sound_focus);
9746         if ( ret != MM_ERROR_NONE )
9747         {
9748                 debug_error("failed to acquire sound focus.\n");
9749                 return ret;
9750         }
9751
9752         /* NOTE : we should check and create pipeline again if not created as we destroy
9753          * whole pipeline when stopping in streamming playback
9754          */
9755         if ( ! player->pipeline )
9756         {
9757                 ret = __gst_realize( player );
9758                 if ( MM_ERROR_NONE != ret )
9759                 {
9760                         debug_error("failed to realize before starting. only in streamming\n");
9761                         /* unlock */
9762                         return ret;
9763                 }
9764         }
9765
9766         ret = __mmplayer_start_streaming_ext(player);
9767         if ( ret != MM_ERROR_NONE )
9768         {
9769                 debug_error("failed to start streaming ext \n");
9770         }
9771
9772         /* start pipeline */
9773         ret = __gst_start( player );
9774         if ( ret != MM_ERROR_NONE )
9775         {
9776                 debug_error("failed to start player.\n");
9777         }
9778
9779         MMPLAYER_FLEAVE();
9780
9781         return ret;
9782 }
9783
9784 /* NOTE: post "not supported codec message" to application
9785  * when one codec is not found during AUTOPLUGGING in MSL.
9786  * So, it's separated with error of __mmplayer_gst_callback().
9787  * And, if any codec is not found, don't send message here.
9788  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
9789  */
9790 int
9791 __mmplayer_handle_missed_plugin(mm_player_t* player)
9792 {
9793         MMMessageParamType msg_param;
9794         memset (&msg_param, 0, sizeof(MMMessageParamType));
9795         gboolean post_msg_direct = FALSE;
9796
9797         MMPLAYER_FENTER();
9798
9799         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9800
9801         debug_log("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
9802                         player->not_supported_codec, player->can_support_codec);
9803
9804         if( player->not_found_demuxer )
9805         {
9806                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9807                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
9808
9809                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
9810                 MMPLAYER_FREEIF(msg_param.data);
9811
9812                 return MM_ERROR_NONE;
9813         }
9814
9815         if (player->not_supported_codec)
9816         {
9817                 if ( player->can_support_codec ) // There is one codec to play
9818                 {
9819                         post_msg_direct = TRUE;
9820                 }
9821                 else
9822                 {
9823                         if ( player->pipeline->audiobin ) // Some content has only PCM data in container.
9824                                 post_msg_direct = TRUE;
9825                 }
9826
9827                 if ( post_msg_direct )
9828                 {
9829                         MMMessageParamType msg_param;
9830                         memset (&msg_param, 0, sizeof(MMMessageParamType));
9831
9832                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
9833                         {
9834                                 debug_warning("not found AUDIO codec, posting error code to application.\n");
9835
9836                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9837                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9838                         }
9839                         else if ( player->not_supported_codec ==  MISSING_PLUGIN_VIDEO )
9840                         {
9841                                 debug_warning("not found VIDEO codec, posting error code to application.\n");
9842
9843                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9844                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
9845                         }
9846
9847                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
9848
9849                         MMPLAYER_FREEIF(msg_param.data);
9850
9851                         return MM_ERROR_NONE;
9852                 }
9853                 else // no any supported codec case
9854                 {
9855                         debug_warning("not found any codec, posting error code to application.\n");
9856
9857                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
9858                         {
9859                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9860                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9861                         }
9862                         else
9863                         {
9864                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9865                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
9866                         }
9867
9868                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
9869
9870                         MMPLAYER_FREEIF(msg_param.data);
9871                 }
9872         }
9873
9874         MMPLAYER_FLEAVE();
9875
9876         return MM_ERROR_NONE;
9877 }
9878
9879 static void __mmplayer_check_pipeline(mm_player_t* player)
9880 {
9881         GstState element_state = GST_STATE_VOID_PENDING;
9882         GstState element_pending_state = GST_STATE_VOID_PENDING;
9883         gint timeout = 0;
9884         int ret = MM_ERROR_NONE;
9885
9886         if (player->gapless.reconfigure)
9887         {
9888                 debug_warning("pipeline is under construction.\n");
9889
9890                 MMPLAYER_PLAYBACK_LOCK(player);
9891                 MMPLAYER_PLAYBACK_UNLOCK(player);
9892
9893                 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
9894
9895                 /* wait for state transition */
9896                 ret = gst_element_get_state( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND );
9897
9898                 if ( ret == GST_STATE_CHANGE_FAILURE )
9899                 {
9900                         debug_error("failed to change pipeline state within %d sec\n", timeout );
9901                 }
9902         }
9903 }
9904
9905 /* NOTE : it should be able to call 'stop' anytime*/
9906 int
9907 _mmplayer_stop(MMHandleType hplayer) // @
9908 {
9909         mm_player_t* player = (mm_player_t*)hplayer;
9910         int ret = MM_ERROR_NONE;
9911
9912         MMPLAYER_FENTER();
9913
9914         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9915
9916         /* check current state */
9917         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
9918
9919         /* check pipline building state */
9920         __mmplayer_check_pipeline(player);
9921         player->gapless.start_time = 0;
9922
9923         /* NOTE : application should not wait for EOS after calling STOP */
9924         __mmplayer_cancel_eos_timer( player );
9925
9926         __mmplayer_unrealize_streaming_ext(player);
9927
9928         /* reset */
9929         player->doing_seek = FALSE;
9930
9931         /* stop pipeline */
9932         ret = __gst_stop( player );
9933
9934         if ( ret != MM_ERROR_NONE )
9935         {
9936                 debug_error("failed to stop player.\n");
9937         }
9938
9939         MMPLAYER_FLEAVE();
9940
9941         return ret;
9942 }
9943
9944 int
9945 _mmplayer_pause(MMHandleType hplayer) // @
9946 {
9947         mm_player_t* player = (mm_player_t*)hplayer;
9948         gint64 pos_msec = 0;
9949         gboolean async = FALSE;
9950         gint ret = MM_ERROR_NONE;
9951
9952         MMPLAYER_FENTER();
9953
9954         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9955
9956         /* check current state */
9957         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
9958
9959         /* check pipline building state */
9960         __mmplayer_check_pipeline(player);
9961
9962         switch (MMPLAYER_CURRENT_STATE(player))
9963         {
9964                 case MM_PLAYER_STATE_READY:
9965                 {
9966                         /* check prepare async or not.
9967                          * In the case of streaming playback, it's recommned to avoid blocking wait.
9968                          */
9969                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
9970                         debug_log("prepare working mode : %s", (async ? "async" : "sync"));
9971                 }
9972                 break;
9973
9974                 case MM_PLAYER_STATE_PLAYING:
9975                 {
9976                         /* NOTE : store current point to overcome some bad operation
9977                         * ( returning zero when getting current position in paused state) of some
9978                         * elements
9979                         */
9980                         if ( !gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec))
9981                                 debug_warning("getting current position failed in paused\n");
9982
9983                         player->last_position = pos_msec;
9984                 }
9985                 break;
9986         }
9987
9988         /* pause pipeline */
9989         ret = __gst_pause( player, async );
9990
9991         if ( ret != MM_ERROR_NONE )
9992         {
9993                 debug_error("failed to pause player. ret : 0x%x\n", ret);
9994         }
9995
9996         MMPLAYER_FLEAVE();
9997
9998         return ret;
9999 }
10000
10001 int
10002 _mmplayer_resume(MMHandleType hplayer)
10003 {
10004         mm_player_t* player = (mm_player_t*)hplayer;
10005         int ret = MM_ERROR_NONE;
10006         gboolean async = FALSE;
10007
10008         MMPLAYER_FENTER();
10009
10010         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10011
10012         ret = _mmplayer_sound_acquire_focus(&player->sound_focus);
10013         if ( ret != MM_ERROR_NONE )
10014         {
10015                 debug_error("failed to acquire sound focus.\n");
10016                 return ret;
10017         }
10018
10019         /* check current state */
10020         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
10021
10022         ret = __gst_resume( player, async );
10023
10024         if ( ret != MM_ERROR_NONE )
10025         {
10026                 debug_error("failed to resume player.\n");
10027         }
10028
10029         MMPLAYER_FLEAVE();
10030
10031         return ret;
10032 }
10033
10034 int
10035 __mmplayer_set_play_count(mm_player_t* player, gint count)
10036 {
10037         MMHandleType attrs = 0;
10038
10039         MMPLAYER_FENTER();
10040
10041         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10042
10043         attrs =  MMPLAYER_GET_ATTRS(player);
10044         if ( !attrs )
10045         {
10046                 debug_error("fail to get attributes.\n");
10047                 return MM_ERROR_PLAYER_INTERNAL;
10048         }
10049
10050         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
10051         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
10052                 debug_error("failed to commit\n");
10053
10054         MMPLAYER_FLEAVE();
10055
10056         return  MM_ERROR_NONE;
10057 }
10058
10059 int
10060 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
10061 {
10062         mm_player_t* player = (mm_player_t*)hplayer;
10063         gint64 start_pos = 0;
10064         gint64 end_pos = 0;
10065         gint infinity = -1;
10066
10067         MMPLAYER_FENTER();
10068
10069         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10070         return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
10071
10072         player->section_repeat = TRUE;
10073         player->section_repeat_start = start;
10074         player->section_repeat_end = end;
10075
10076         start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
10077         end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
10078
10079         __mmplayer_set_play_count( player, infinity );
10080
10081         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10082                                         player->playback_rate,
10083                                         GST_FORMAT_TIME,
10084                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10085                                         GST_SEEK_TYPE_SET, start_pos,
10086                                         GST_SEEK_TYPE_SET, end_pos)))
10087         {
10088                 debug_error("failed to activate section repeat\n");
10089
10090                 return MM_ERROR_PLAYER_SEEK;
10091         }
10092
10093         debug_log("succeeded to set section repeat from %d to %d\n",
10094                 player->section_repeat_start, player->section_repeat_end);
10095
10096         MMPLAYER_FLEAVE();
10097
10098         return  MM_ERROR_NONE;
10099 }
10100
10101 static int
10102 __mmplayer_set_pcm_extraction(mm_player_t* player)
10103 {
10104         gint64 start_nsec = 0;
10105         gint64 end_nsec = 0;
10106         gint64 dur_nsec = 0;
10107         gint64 dur_msec = 0;
10108         int required_start = 0;
10109         int required_end = 0;
10110         int ret = 0;
10111
10112         MMPLAYER_FENTER();
10113
10114         return_val_if_fail( player, FALSE );
10115
10116         mm_attrs_multiple_get(player->attrs,
10117                 NULL,
10118                 "pcm_extraction_start_msec", &required_start,
10119                 "pcm_extraction_end_msec", &required_end,
10120                 NULL);
10121
10122         debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
10123
10124         if (required_start == 0 && required_end == 0)
10125         {
10126                 debug_log("extracting entire stream");
10127                 return MM_ERROR_NONE;
10128         }
10129         else if (required_start < 0 || required_start > required_end || required_end < 0 )
10130         {
10131                 debug_log("invalid range for pcm extraction");
10132                 return MM_ERROR_INVALID_ARGUMENT;
10133         }
10134
10135         /* get duration */
10136         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
10137         if ( !ret )
10138         {
10139                 debug_error("failed to get duration");
10140                 return MM_ERROR_PLAYER_INTERNAL;
10141         }
10142         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
10143
10144         if (dur_msec < required_end) // FIXME
10145         {
10146                 debug_log("invalid end pos for pcm extraction");
10147                 return MM_ERROR_INVALID_ARGUMENT;
10148         }
10149
10150         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
10151         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
10152
10153         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10154                                         1.0,
10155                                         GST_FORMAT_TIME,
10156                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10157                                         GST_SEEK_TYPE_SET, start_nsec,
10158                                         GST_SEEK_TYPE_SET, end_nsec)))
10159         {
10160                 debug_error("failed to seek for pcm extraction\n");
10161
10162                 return MM_ERROR_PLAYER_SEEK;
10163         }
10164
10165         debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
10166
10167         MMPLAYER_FLEAVE();
10168
10169         return MM_ERROR_NONE;
10170 }
10171
10172 int
10173 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
10174 {
10175         mm_player_t* player = (mm_player_t*)hplayer;
10176         gint64 cur_pos = 0;
10177         gint onetime = 1;
10178
10179         MMPLAYER_FENTER();
10180
10181         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10182
10183         player->section_repeat = FALSE;
10184
10185         __mmplayer_set_play_count( player, onetime );
10186
10187         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_pos);
10188
10189         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10190                                         1.0,
10191                                         GST_FORMAT_TIME,
10192                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10193                                         GST_SEEK_TYPE_SET, cur_pos,
10194                                         GST_SEEK_TYPE_SET, player->duration )))
10195         {
10196                 debug_error("failed to deactivate section repeat\n");
10197
10198                 return MM_ERROR_PLAYER_SEEK;
10199         }
10200
10201         MMPLAYER_FENTER();
10202
10203         return MM_ERROR_NONE;
10204 }
10205
10206 int
10207 _mmplayer_set_playspeed(MMHandleType hplayer, float rate)
10208 {
10209         mm_player_t* player = (mm_player_t*)hplayer;
10210         gint64 pos_msec = 0;
10211         int ret = MM_ERROR_NONE;
10212         int mute = FALSE;
10213         signed long long start = 0, stop = 0;
10214         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
10215         MMPLAYER_FENTER();
10216
10217         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
10218         return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
10219
10220         /* The sound of video is not supported under 0.0 and over 2.0. */
10221         if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
10222         {
10223                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
10224                         mute = TRUE;
10225         }
10226         _mmplayer_set_mute(hplayer, mute);
10227
10228         if (player->playback_rate == rate)
10229                 return MM_ERROR_NONE;
10230
10231         /* If the position is reached at start potion during fast backward, EOS is posted.
10232          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
10233          * */
10234         player->playback_rate = rate;
10235
10236         current_state = MMPLAYER_CURRENT_STATE(player);
10237
10238         if ( current_state != MM_PLAYER_STATE_PAUSED )
10239                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
10240
10241         debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
10242
10243         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
10244                 || ( ! ret ))
10245                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
10246         {
10247                 debug_warning("returning last point : %lld\n", player->last_position );
10248                 pos_msec = player->last_position;
10249         }
10250
10251
10252         if(rate >= 0)
10253         {
10254                 start = pos_msec;
10255                 stop = GST_CLOCK_TIME_NONE;
10256         }
10257         else
10258         {
10259                 start = GST_CLOCK_TIME_NONE;
10260                 stop = pos_msec;
10261         }
10262         if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10263                                 rate,
10264                                 GST_FORMAT_TIME,
10265                                 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10266                                 GST_SEEK_TYPE_SET, start,
10267                                 GST_SEEK_TYPE_SET, stop)))
10268         {
10269                 debug_error("failed to set speed playback\n");
10270                 return MM_ERROR_PLAYER_SEEK;
10271         }
10272
10273         debug_log("succeeded to set speed playback as %0.1f\n", rate);
10274
10275         MMPLAYER_FLEAVE();
10276
10277         return MM_ERROR_NONE;;
10278 }
10279
10280 int
10281 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
10282 {
10283         mm_player_t* player = (mm_player_t*)hplayer;
10284         int ret = MM_ERROR_NONE;
10285
10286         MMPLAYER_FENTER();
10287
10288         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10289
10290         ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
10291
10292         MMPLAYER_FLEAVE();
10293
10294         return ret;
10295 }
10296
10297 int
10298 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
10299 {
10300         mm_player_t* player = (mm_player_t*)hplayer;
10301         int ret = MM_ERROR_NONE;
10302
10303         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10304
10305         ret = __gst_get_position ( player, format, position );
10306
10307         return ret;
10308 }
10309
10310 int
10311 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
10312 {
10313         mm_player_t* player = (mm_player_t*)hplayer;
10314         int ret = MM_ERROR_NONE;
10315
10316         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10317
10318         ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
10319
10320         return ret;
10321 }
10322
10323 int
10324 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
10325 {
10326         mm_player_t* player = (mm_player_t*)hplayer;
10327         int ret = MM_ERROR_NONE;
10328
10329         MMPLAYER_FENTER();
10330
10331         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10332
10333         ret = __gst_adjust_subtitle_position(player, format, position);
10334
10335         MMPLAYER_FLEAVE();
10336
10337         return ret;
10338 }
10339 int
10340 _mmplayer_adjust_video_postion(MMHandleType hplayer, int offset) // @
10341 {
10342         mm_player_t* player = (mm_player_t*)hplayer;
10343         int ret = MM_ERROR_NONE;
10344
10345         MMPLAYER_FENTER();
10346
10347         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10348
10349         ret = __gst_adjust_video_position(player, offset);
10350
10351         MMPLAYER_FLEAVE();
10352
10353         return ret;
10354 }
10355
10356 static gboolean
10357 __mmplayer_is_midi_type( gchar* str_caps)
10358 {
10359         if ( ( g_strrstr(str_caps, "audio/midi") ) ||
10360                 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
10361                 ( g_strrstr(str_caps, "application/x-smaf") ) ||
10362                 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
10363                 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
10364                 ( g_strrstr(str_caps, "audio/xmf") ) ||
10365                 ( g_strrstr(str_caps, "audio/mxmf") ) )
10366         {
10367                 debug_log("midi\n");
10368
10369                 return TRUE;
10370         }
10371
10372         return FALSE;
10373 }
10374
10375 static gboolean
10376 __mmplayer_is_only_mp3_type (gchar *str_caps)
10377 {
10378         if (g_strrstr(str_caps, "application/x-id3") ||
10379                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
10380         {
10381                 return TRUE;
10382         }
10383         return FALSE;
10384 }
10385
10386 static void
10387 __mmplayer_set_audio_attrs (mm_player_t* player, GstCaps* caps)
10388 {
10389         GstStructure* caps_structure = NULL;
10390         gint samplerate = 0;
10391         gint channels = 0;
10392
10393         MMPLAYER_FENTER();
10394         return_if_fail (player && caps);
10395
10396         caps_structure = gst_caps_get_structure(caps, 0);
10397
10398         /* set stream information */
10399         gst_structure_get_int (caps_structure, "rate", &samplerate);
10400         mm_attrs_set_int_by_name (player->attrs, "content_audio_samplerate", samplerate);
10401
10402         gst_structure_get_int (caps_structure, "channels", &channels);
10403         mm_attrs_set_int_by_name (player->attrs, "content_audio_channels", channels);
10404
10405         debug_log ("audio samplerate : %d       channels : %d\n", samplerate, channels);
10406 }
10407
10408 static void
10409 __mmplayer_update_content_type_info(mm_player_t* player)
10410 {
10411         MMPLAYER_FENTER();
10412         return_if_fail( player && player->type);
10413
10414         if (__mmplayer_is_midi_type(player->type))
10415         {
10416                 player->bypass_audio_effect = TRUE;
10417         }
10418         else if (g_strrstr(player->type, "application/x-hls"))
10419         {
10420                 /* If it can't know exact type when it parses uri because of redirection case,
10421                  * it will be fixed by typefinder or when doing autoplugging.
10422                  */
10423                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
10424                 if (player->streamer)
10425                 {
10426                         player->streamer->is_adaptive_streaming = TRUE;
10427                         player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
10428                         player->streamer->buffering_req.runtime_second = 5;
10429                 }
10430         }
10431         else if (g_strrstr(player->type, "application/dash+xml"))
10432         {
10433                 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
10434         }
10435
10436         MMPLAYER_FLEAVE();
10437 }
10438
10439 static void
10440 __mmplayer_typefind_have_type(  GstElement *tf, guint probability,  // @
10441 GstCaps *caps, gpointer data)
10442 {
10443         mm_player_t* player = (mm_player_t*)data;
10444         GstPad* pad = NULL;
10445
10446         MMPLAYER_FENTER();
10447
10448         return_if_fail( player && tf && caps );
10449
10450         /* store type string */
10451         MMPLAYER_FREEIF(player->type);
10452         player->type = gst_caps_to_string(caps);
10453         if (player->type)
10454                 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
10455
10456         if ( (!MMPLAYER_IS_WFD_STREAMING( player )) &&
10457                  (!MMPLAYER_IS_RTSP_STREAMING( player )) &&
10458                  (g_strrstr(player->type, "audio/x-raw-int")))
10459         {
10460                 debug_error("not support media format\n");
10461
10462                 if (player->msg_posted == FALSE)
10463                 {
10464                         MMMessageParamType msg_param;
10465                         memset (&msg_param, 0, sizeof(MMMessageParamType));
10466
10467                         msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
10468                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10469
10470                         /* don't post more if one was sent already */
10471                         player->msg_posted = TRUE;
10472                 }
10473                 return;
10474         }
10475
10476         __mmplayer_update_content_type_info(player);
10477
10478         pad = gst_element_get_static_pad(tf, "src");
10479         if ( !pad )
10480         {
10481                 debug_error("fail to get typefind src pad.\n");
10482                 return;
10483         }
10484
10485         if (player->use_decodebin)
10486         {
10487                 if(!__mmplayer_try_to_plug_decodebin( player, pad, caps ))
10488                 {
10489                         gboolean async = FALSE;
10490                         debug_error("failed to autoplug %s\n", player->type);
10491
10492                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10493
10494                         if ( async && player->msg_posted == FALSE )
10495                         {
10496                                 __mmplayer_handle_missed_plugin( player );
10497                         }
10498
10499                         goto DONE;
10500                 }
10501         }
10502         else
10503         {
10504                 /* try to plug */
10505                 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
10506                 {
10507                         gboolean async = FALSE;
10508                         debug_error("failed to autoplug %s\n", player->type);
10509
10510                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10511
10512                         if ( async && player->msg_posted == FALSE )
10513                         {
10514                                 __mmplayer_handle_missed_plugin( player );
10515                         }
10516
10517                         goto DONE;
10518                 }
10519
10520                 /* finish autopluging if no dynamic pad waiting */
10521                 if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
10522                 {
10523                         if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
10524                         {
10525                                 __mmplayer_pipeline_complete( NULL, (gpointer)player );
10526                         }
10527                 }
10528         }
10529
10530 DONE:
10531         gst_object_unref( GST_OBJECT(pad) );
10532
10533         MMPLAYER_FLEAVE();
10534
10535         return;
10536 }
10537
10538 #ifdef _MM_PLAYER_ALP_PARSER
10539 void check_name (void *data, void *user_data)
10540 {
10541         mm_player_t* player = user_data;
10542
10543         if (g_strrstr((gchar*)data, "mpegaudioparse"))
10544         {
10545                 debug_log("mpegaudioparse - set alp-mp3dec\n");
10546                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "alp-mp3dec", TRUE, NULL);
10547         }
10548 }
10549 #endif
10550
10551 static GstElement *
10552 __mmplayer_create_decodebin (mm_player_t* player)
10553 {
10554         GstElement *decodebin = NULL;
10555
10556         MMPLAYER_FENTER();
10557
10558         /* create decodebin */
10559         decodebin = gst_element_factory_make("decodebin", NULL);
10560
10561         if (!decodebin)
10562         {
10563                 debug_error("fail to create decodebin\n");
10564                 goto ERROR;
10565         }
10566
10567         /* raw pad handling signal */
10568         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
10569                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
10570
10571         /* no-more-pad pad handling signal */
10572         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
10573                                                 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
10574
10575         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
10576                                                 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
10577
10578         /* This signal is emitted when a pad for which there is no further possible
10579            decoding is added to the decodebin.*/
10580         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
10581                                                 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player );
10582
10583         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
10584            before looking for any elements that can handle that stream.*/
10585         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
10586                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
10587
10588         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
10589            before looking for any elements that can handle that stream.*/
10590         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
10591                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
10592
10593         /* This signal is emitted once decodebin has finished decoding all the data.*/
10594         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
10595                                                 G_CALLBACK(__mmplayer_gst_decode_drained), player);
10596
10597         /* This signal is emitted when a element is added to the bin.*/
10598         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
10599                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
10600
10601 ERROR:
10602         return decodebin;
10603 }
10604
10605 static gboolean
10606 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
10607 {
10608         MMPlayerGstElement* mainbin = NULL;
10609         GstElement* decodebin = NULL;
10610         GstElement* queue2 = NULL;
10611         GstPad* sinkpad = NULL;
10612         GstPad* qsrcpad= NULL;
10613         gchar *caps_str = NULL;
10614         gint64 dur_bytes = 0L;
10615         gchar* file_buffering_path = NULL;
10616         gboolean use_file_buffer = FALSE;
10617
10618         guint max_buffer_size_bytes = 0;
10619         gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
10620
10621         MMPLAYER_FENTER();
10622         return_val_if_fail (player && player->pipeline && player->pipeline->mainbin, FALSE);
10623
10624         mainbin = player->pipeline->mainbin;
10625
10626         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
10627                 (MMPLAYER_IS_HTTP_STREAMING(player)))
10628         {
10629                 debug_log ("creating http streaming buffering queue (queue2)\n");
10630
10631                 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
10632                 {
10633                         debug_error ("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
10634                 }
10635                 else
10636             {
10637                         queue2 = gst_element_factory_make ("queue2", "queue2");
10638                         if (!queue2)
10639                         {
10640                                 debug_error ("failed to create buffering queue element\n");
10641                                 goto ERROR;
10642                         }
10643
10644                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2))
10645                         {
10646                                 debug_error("failed to add buffering queue\n");
10647                                 goto ERROR;
10648                         }
10649
10650                         sinkpad = gst_element_get_static_pad(queue2, "sink");
10651                         qsrcpad = gst_element_get_static_pad(queue2, "src");
10652
10653                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
10654                         {
10655                                 debug_error("failed to link buffering queue\n");
10656                                 goto ERROR;
10657                         }
10658
10659                         // if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
10660                         {
10661                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
10662                                         debug_error("fail to get duration.\n");
10663
10664                                 debug_log("dur_bytes = %lld\n", dur_bytes);
10665
10666                                 if (dur_bytes > 0)
10667                                 {
10668                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
10669                                         file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
10670                                 }
10671                                 else
10672                                 {
10673                                         dur_bytes = 0;
10674                                 }
10675                         }
10676
10677                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
10678                         // if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
10679                         if(!g_strrstr(player->type, "video/mpegts"))
10680                         {
10681                                 max_buffer_size_bytes = (use_file_buffer)?(player->ini.http_max_size_bytes):(5*1024*1024);
10682                                 debug_log("max_buffer_size_bytes = %d\n", max_buffer_size_bytes);
10683
10684                                 __mm_player_streaming_set_queue2(player->streamer,
10685                                                                                                 queue2,
10686                                                                                                 FALSE,
10687                                                                                                 max_buffer_size_bytes,
10688                                                                                                 player->ini.http_buffering_time,
10689                                                                                                 1.0,                                                            // no meaning
10690                                                                                                 player->ini.http_buffering_limit,       // no meaning
10691                                                                                                 use_file_buffer,
10692                                                                                                 file_buffering_path,
10693                                                                                                 (guint64)dur_bytes);
10694                         }
10695
10696                         MMPLAYER_FREEIF(file_buffering_path);
10697                         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (queue2))
10698                         {
10699                                 debug_error("failed to sync queue2 state with parent\n");
10700                                 goto ERROR;
10701                         }
10702
10703                         srcpad = qsrcpad;
10704
10705                         gst_object_unref(GST_OBJECT(sinkpad));
10706
10707                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
10708                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
10709                 }
10710         }
10711
10712         /* create decodebin */
10713         decodebin = __mmplayer_create_decodebin(player);
10714
10715         if (!decodebin)
10716         {
10717                 debug_error("can not create autoplug element\n");
10718                 goto ERROR;
10719         }
10720
10721         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin))
10722         {
10723                 debug_error("failed to add decodebin\n");
10724                 goto ERROR;
10725         }
10726
10727         /* to force caps on the decodebin element and avoid reparsing stuff by
10728         * typefind. It also avoids a deadlock in the way typefind activates pads in
10729         * the state change */
10730         g_object_set (decodebin, "sink-caps", caps, NULL);
10731
10732         sinkpad = gst_element_get_static_pad(decodebin, "sink");
10733
10734         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
10735         {
10736                 debug_error("failed to link decodebin\n");
10737                 goto ERROR;
10738         }
10739
10740         gst_object_unref(GST_OBJECT(sinkpad));
10741
10742         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
10743         mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin;
10744
10745         /* set decodebin property about buffer in streaming playback. *
10746          * in case of hls, it does not need to have big buffer        *
10747          * because it is kind of adaptive streaming.                  */
10748         if ( ((!MMPLAYER_IS_HTTP_PD(player)) &&
10749             (MMPLAYER_IS_HTTP_STREAMING(player))) || MMPLAYER_IS_DASH_STREAMING (player))
10750         {
10751                 guint max_size_bytes = MAX_DECODEBIN_BUFFER_BYTES;
10752                 guint64 max_size_time = MAX_DECODEBIN_BUFFER_TIME;
10753                 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
10754
10755                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {
10756                         max_size_bytes = MAX_DECODEBIN_ADAPTIVE_BUFFER_BYTES;
10757                         max_size_time = MAX_DECODEBIN_ADAPTIVE_BUFFER_TIME;
10758                 }
10759
10760                 g_object_set (G_OBJECT(decodebin), "use-buffering", TRUE,
10761                                                                                         "high-percent", (gint)player->ini.http_buffering_limit,
10762                                                                                         "low-percent", 1,   // 1%
10763                                                                                         "max-size-bytes", max_size_bytes,
10764                                                                                         "max-size-time", (guint64)(max_size_time * GST_SECOND),
10765                                                                                         "max-size-buffers", 0, NULL);  // disable or automatic
10766         }
10767
10768         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin))
10769         {
10770                 debug_error("failed to sync decodebin state with parent\n");
10771                 goto ERROR;
10772         }
10773
10774         MMPLAYER_FLEAVE();
10775
10776         return TRUE;
10777
10778 ERROR:
10779
10780         MMPLAYER_FREEIF( caps_str );
10781
10782         if (sinkpad)
10783                 gst_object_unref(GST_OBJECT(sinkpad));
10784
10785         if (queue2)
10786         {
10787                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
10788                  * You need to explicitly set elements to the NULL state before
10789                  * dropping the final reference, to allow them to clean up.
10790                  */
10791                 gst_element_set_state(queue2, GST_STATE_NULL);
10792
10793                 /* And, it still has a parent "player".
10794                  * You need to let the parent manage the object instead of unreffing the object directly.
10795                  */
10796                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
10797                 gst_object_unref (queue2);
10798                 queue2 = NULL;
10799         }
10800
10801         if (decodebin)
10802         {
10803                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
10804                  * You need to explicitly set elements to the NULL state before
10805                  * dropping the final reference, to allow them to clean up.
10806                  */
10807                 gst_element_set_state(decodebin, GST_STATE_NULL);
10808
10809                 /* And, it still has a parent "player".
10810                  * You need to let the parent manage the object instead of unreffing the object directly.
10811                  */
10812
10813                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
10814                 gst_object_unref (decodebin);
10815                 decodebin = NULL;
10816         }
10817
10818         return FALSE;
10819 }
10820
10821 /* it will return first created element */
10822 static gboolean
10823 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
10824 {
10825         MMPlayerGstElement* mainbin = NULL;
10826         const char* mime = NULL;
10827         const GList* item = NULL;
10828         const gchar* klass = NULL;
10829         GstCaps* res = NULL;
10830         gboolean skip = FALSE;
10831         GstPad* queue_pad = NULL;
10832         GstElement* queue = NULL;
10833         GstElement *element = NULL;
10834
10835         MMPLAYER_FENTER();
10836
10837         return_val_if_fail( player && player->pipeline && player->pipeline->mainbin, FALSE );
10838
10839         mainbin = player->pipeline->mainbin;
10840
10841         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
10842
10843         /* return if we got raw output */
10844         if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
10845                 || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup"))
10846         {
10847
10848                 element = (GstElement*)gst_pad_get_parent(pad);
10849 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
10850  * No queue will be added. I think it can caused breaking sound when playing raw audio
10851  * frames but there's no different. Decodebin also doesn't add with those wav fils.
10852  * Anyway, currentely raw-queue seems not necessary.
10853  */
10854 #if 1
10855                 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
10856                  * has linked. if so, we need to add queue for quality of output. note that
10857                  * decodebin also has same problem.
10858                  */
10859                 klass = gst_element_factory_get_metadata (gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
10860
10861                 /* add queue if needed */
10862                 if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
10863                         || g_strrstr(klass, "Parse")) &&  !g_str_has_prefix(mime, "text"))
10864                 {
10865                         debug_log("adding raw queue\n");
10866
10867                         queue = gst_element_factory_make("queue", NULL);
10868                         if ( ! queue )
10869                         {
10870                                 debug_warning("failed to create queue\n");
10871                                 goto ERROR;
10872                         }
10873
10874                         /* warmup */
10875                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
10876                         {
10877                                 debug_warning("failed to set state READY to queue\n");
10878                                 goto ERROR;
10879                         }
10880
10881                         /* add to pipeline */
10882                         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
10883                         {
10884                                 debug_warning("failed to add queue\n");
10885                                 goto ERROR;
10886                         }
10887
10888                         /* link queue */
10889                         queue_pad = gst_element_get_static_pad(queue, "sink");
10890
10891                         if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
10892                         {
10893                                 debug_warning("failed to link queue\n");
10894                                 goto ERROR;
10895                         }
10896                         gst_object_unref ( GST_OBJECT(queue_pad) );
10897                         queue_pad = NULL;
10898
10899                         /* running */
10900                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
10901                         {
10902                                 debug_warning("failed to set state PAUSED to queue\n");
10903                                 goto ERROR;
10904                         }
10905
10906                         /* replace given pad to queue:src */
10907                         pad = gst_element_get_static_pad(queue, "src");
10908                         if ( ! pad )
10909                         {
10910                                 debug_warning("failed to get pad from queue\n");
10911                                 goto ERROR;
10912                         }
10913                 }
10914 #endif
10915                 /* check if player can do start continually */
10916                 MMPLAYER_CHECK_CMD_IF_EXIT(player);
10917
10918                 if(__mmplayer_link_sink(player,pad))
10919                         __mmplayer_gst_decode_callback(element, pad, player);
10920
10921                 gst_object_unref( GST_OBJECT(element));
10922                 element = NULL;
10923
10924                 return TRUE;
10925         }
10926
10927         item = player->factories;
10928         for(; item != NULL ; item = item->next)
10929         {
10930                 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
10931                 const GList *pads;
10932                 gint idx = 0;
10933
10934                 skip = FALSE;
10935
10936                 /* filtering exclude keyword */
10937                 for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
10938                 {
10939                         if ( g_strrstr(GST_OBJECT_NAME (factory),
10940                                         player->ini.exclude_element_keyword[idx] ) )
10941                         {
10942                                 debug_warning("skipping [%s] by exculde keyword [%s]\n",
10943                                         GST_OBJECT_NAME (factory),
10944                                         player->ini.exclude_element_keyword[idx] );
10945
10946                                 skip = TRUE;
10947                                 break;
10948                         }
10949                 }
10950
10951                 if ( MMPLAYER_IS_RTSP_STREAMING(player) && g_strrstr(GST_OBJECT_NAME (factory), "omx_mpeg4dec"))
10952                 {
10953                         // omx decoder can not support mpeg4video data partitioned
10954                         // rtsp streaming didn't know mpeg4video data partitioned format
10955                         // so, if rtsp playback, player will skip omx_mpeg4dec.
10956                         debug_warning("skipping [%s] when rtsp streaming \n",
10957                                         GST_OBJECT_NAME (factory));
10958
10959                         skip = TRUE;
10960                 }
10961
10962                 if ( skip ) continue;
10963
10964                 /* check factory class for filtering */
10965                 klass = gst_element_factory_get_metadata (GST_ELEMENT_FACTORY(factory), GST_ELEMENT_METADATA_KLASS);
10966
10967                 /*parsers are not required in case of external feeder*/
10968                 if (g_strrstr(klass, "Codec/Parser") && MMPLAYER_IS_ES_BUFF_SRC(player))
10969                         continue;
10970
10971                 /* NOTE : msl don't need to use image plugins.
10972                  * So, those plugins should be skipped for error handling.
10973                  */
10974                 if ( g_strrstr(klass, "Codec/Decoder/Image") )
10975                 {
10976                         debug_log("skipping [%s] by not required\n", GST_OBJECT_NAME (factory));
10977                         continue;
10978                 }
10979
10980                 /* check pad compatability */
10981                 for(pads = gst_element_factory_get_static_pad_templates(factory);
10982                                         pads != NULL; pads=pads->next)
10983                 {
10984                         GstStaticPadTemplate *temp1 = pads->data;
10985                         GstCaps* static_caps = NULL;
10986
10987                         if( temp1->direction != GST_PAD_SINK
10988                                 || temp1->presence != GST_PAD_ALWAYS)
10989                                 continue;
10990
10991                         if ( GST_IS_CAPS( &temp1->static_caps.caps) )
10992                         {
10993                                 /* using existing caps */
10994                                 static_caps = gst_caps_ref(temp1->static_caps.caps );
10995                         }
10996                         else
10997                         {
10998                                 /* create one */
10999                                 static_caps = gst_caps_from_string ( temp1->static_caps.string );
11000                         }
11001
11002                         res = gst_caps_intersect((GstCaps*)caps, static_caps);
11003                         gst_caps_unref( static_caps );
11004                         static_caps = NULL;
11005
11006                         if( res && !gst_caps_is_empty(res) )
11007                         {
11008                                 GstElement *new_element;
11009                                 GList *elements = player->parsers;
11010                                 char *name_template = g_strdup(temp1->name_template);
11011                                 gchar *name_to_plug = GST_OBJECT_NAME(factory);
11012                                 gst_caps_unref(res);
11013
11014                                 /* check ALP Codec can be used or not */
11015                                 if ((g_strrstr(klass, "Codec/Decoder/Audio")))
11016                                 {
11017                                         /* consider mp3 audio only */
11018                                         if ( !MMPLAYER_IS_STREAMING(player) && __mmplayer_is_only_mp3_type(player->type) )
11019                                         {
11020                                                 /* try to use ALP decoder first instead of selected decoder */
11021                                                 GstElement *element = NULL;
11022                                                 GstElementFactory * element_facory;
11023                                                 gchar *path = NULL;
11024                                                 guint64 data_size = 0;
11025                                                 #define MIN_THRESHOLD_SIZE  320 * 1024 // 320K
11026                                                 struct stat sb;
11027
11028                                                 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
11029
11030                                                 if (stat(path, &sb) == 0)
11031                                                 {
11032                                                         data_size = (guint64)sb.st_size;
11033                                                 }
11034                                                 debug_log("file size : %u", data_size);
11035
11036                                                 if (data_size > MIN_THRESHOLD_SIZE)
11037                                                 {
11038                                                         debug_log("checking if ALP can be used or not");
11039                                                         element = gst_element_factory_make("omx_mp3dec", "omx mp3 decoder");
11040                                                         if ( element )
11041                                                         {
11042                                                                 /* check availability because multi-instance is not supported */
11043                                                                 GstStateChangeReturn ret = gst_element_set_state(element, GST_STATE_READY);
11044
11045                                                                 if (ret != GST_STATE_CHANGE_SUCCESS) // use just selected decoder
11046                                                                 {
11047                                                                         gst_object_unref (element);
11048                                                                 }
11049                                                                 else if (ret == GST_STATE_CHANGE_SUCCESS) // replace facotry to use omx
11050                                                                 {
11051                                                                         /* clean  */
11052                                                                         gst_element_set_state(element, GST_STATE_NULL);
11053                                                                         gst_object_unref (element);
11054
11055                                                                         element_facory = gst_element_factory_find("omx_mp3dec");
11056                                                                         /* replace, otherwise use selected thing instead */
11057                                                                         if (element_facory)
11058                                                                         {
11059                                                                                 factory = element_facory;
11060                                                                                 name_to_plug = GST_OBJECT_NAME(factory);
11061                                                                         }
11062
11063                                                                         /* make parser alp mode */
11064                                                                         #ifdef _MM_PLAYER_ALP_PARSER
11065                                                                         g_list_foreach (player->parsers, check_name, player);
11066                                                                         #endif
11067                                                                 }
11068                                                         }
11069                                                 }
11070                                         }
11071                                 }
11072                                 else if ((g_strrstr(klass, "Codec/Decoder/Video")))
11073                                 {
11074                                         if ( g_strrstr(GST_OBJECT_NAME(factory), "omx_") )
11075                                         {
11076                                                 char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
11077                                                 if (env != NULL)
11078                                                 {
11079                                                         if (strncasecmp(env, "yes", 3) == 0)
11080                                                         {
11081                                                                 debug_log("skipping [%s] by disabled\n", name_to_plug);
11082                                                                 MMPLAYER_FREEIF(name_template);
11083                                                                 continue;
11084                                                         }
11085                                                 }
11086                                         }
11087                                 }
11088
11089                                 debug_log("found %s to plug\n", name_to_plug);
11090
11091                                 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
11092                                 if ( ! new_element )
11093                                 {
11094                                         debug_error("failed to create element [%s]. continue with next.\n",
11095                                                 GST_OBJECT_NAME (factory));
11096
11097                                         MMPLAYER_FREEIF(name_template);
11098
11099                                         continue;
11100                                 }
11101
11102                                 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
11103                                  * because parser can accept its own output as input.
11104                                  */
11105                                 if (g_strrstr(klass, "Parser"))
11106                                 {
11107                                         gchar *selected = NULL;
11108
11109                                         for ( ; elements; elements = g_list_next(elements))
11110                                         {
11111                                                 gchar *element_name = elements->data;
11112
11113                                                 if (g_strrstr(element_name, name_to_plug))
11114                                                 {
11115                                                         debug_log("but, %s already linked, so skipping it\n", name_to_plug);
11116                                                         skip = TRUE;
11117                                                 }
11118                                         }
11119
11120                                         if (skip)
11121                                         {
11122                                                 MMPLAYER_FREEIF(name_template);
11123                                                 continue;
11124                                         }
11125
11126                                         selected = g_strdup(name_to_plug);
11127                                         player->parsers = g_list_append(player->parsers, selected);
11128                                 }
11129
11130                                 /* store specific handles for futher control */
11131                                 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
11132                                 {
11133                                         /* FIXIT : first value will be overwritten if there's more
11134                                          * than 1 demuxer/parser
11135                                          */
11136                                         debug_log("plugged element is demuxer. take it\n");
11137                                         mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
11138                                         mainbin[MMPLAYER_M_DEMUX].gst = new_element;
11139
11140                                         /*Added for multi audio support */
11141                                         if(g_strrstr(klass, "Demux"))
11142                                         {
11143                                                 mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
11144                                                 mainbin[MMPLAYER_M_DEMUX_EX].gst = new_element;
11145
11146                                                 /* NOTE : workaround for bug in mpegtsdemux since doesn't emit
11147                                                 no-more-pad signal. this may cause wrong content attributes at PAUSED state
11148                                                 this code should be removed after mpegtsdemux is fixed */
11149                                                 if ( g_strrstr(GST_OBJECT_NAME(factory), "mpegtsdemux") )
11150                                                 {
11151                                                         debug_warning("force no-more-pad to TRUE since mpegtsdemux os not giving no-more-pad signal. content attributes may wrong");
11152                                                         player->no_more_pad = TRUE;
11153                                                 }
11154                                         }
11155                                         if (g_strrstr(name_to_plug, "asfdemux")) // to support trust-zone only
11156                                         {
11157                                                 g_object_set(mainbin[MMPLAYER_M_DEMUX_EX].gst, "file-location", player->profile.uri,NULL);
11158                                         }
11159                                 }
11160                                 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
11161                                 {
11162                                         if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
11163                                         {
11164                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
11165                                                 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
11166                                                 mainbin[MMPLAYER_M_DEC1].gst = new_element;
11167                                         }
11168                                         else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
11169                                         {
11170                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
11171                                                 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
11172                                                 mainbin[MMPLAYER_M_DEC2].gst = new_element;
11173                                         }
11174                                         /* NOTE : IF one codec is found, add it to supported_codec and remove from
11175                                          * missing plugin. Both of them are used to check what's supported codec
11176                                          * before returning result of play start. And, missing plugin should be
11177                                          * updated here for multi track files.
11178                                          */
11179                                         if(g_str_has_prefix(mime, "video"))
11180                                         {
11181                                                 GstPad *src_pad = NULL;
11182                                                 GstPadTemplate *pad_templ = NULL;
11183                                                 GstCaps *caps = NULL;
11184                                                 gchar *caps_str = NULL;
11185
11186                                                 debug_log("found VIDEO decoder\n");
11187                                                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
11188                                                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
11189
11190                                                 src_pad = gst_element_get_static_pad (new_element, "src");
11191                                                 pad_templ = gst_pad_get_pad_template (src_pad);
11192                                                 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
11193
11194                                                 caps_str = gst_caps_to_string(caps);
11195
11196                                                 /* clean */
11197                                                 MMPLAYER_FREEIF( caps_str );
11198                                                 gst_object_unref (src_pad);
11199                                         }
11200                                         else if (g_str_has_prefix(mime, "audio"))
11201                                         {
11202                                                 debug_log("found AUDIO decoder\n");
11203                                                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
11204                                                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
11205                                         }
11206                                 }
11207
11208                                 if ( ! __mmplayer_close_link(player, pad, new_element,
11209                                                         name_template,gst_element_factory_get_static_pad_templates(factory)) )
11210                                 {
11211                                         MMPLAYER_FREEIF(name_template);
11212                                         if (player->keep_detecting_vcodec)
11213                                         continue;
11214
11215                                         /* Link is failed even though a supportable codec is found. */
11216                                         __mmplayer_check_not_supported_codec(player, klass, mime);
11217
11218                                         debug_error("failed to call _close_link\n");
11219                                         return FALSE;
11220                                 }
11221
11222                                 MMPLAYER_FREEIF(name_template);
11223                                 return TRUE;
11224                         }
11225
11226                         gst_caps_unref(res);
11227                         break;
11228                 }
11229         }
11230
11231         /* There is no available codec. */
11232         __mmplayer_check_not_supported_codec(player, klass, mime);
11233
11234         MMPLAYER_FLEAVE();
11235         return FALSE;
11236
11237 ERROR:
11238         /* release */
11239         if ( queue )
11240                 gst_object_unref( queue );
11241
11242         if ( queue_pad )
11243                 gst_object_unref( queue_pad );
11244
11245         if ( element )
11246                 gst_object_unref ( element );
11247
11248         return FALSE;
11249 }
11250
11251
11252 static int
11253 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
11254 {
11255         MMPLAYER_FENTER();
11256
11257         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
11258         return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
11259
11260         debug_log("class : %s, mime : %s \n", factory_class, mime );
11261
11262         /* add missing plugin */
11263         /* NOTE : msl should check missing plugin for image mime type.
11264          * Some motion jpeg clips can have playable audio track.
11265          * So, msl have to play audio after displaying popup written video format not supported.
11266          */
11267         if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
11268         {
11269                 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
11270                 {
11271                         debug_log("not found demuxer\n");
11272                         player->not_found_demuxer = TRUE;
11273                         player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
11274
11275                         goto DONE;
11276                 }
11277         }
11278
11279         if( !g_strrstr(factory_class, "Demuxer"))
11280         {
11281                 if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
11282                 {
11283                         debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
11284                                 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
11285
11286                         /* check that clip have multi tracks or not */
11287                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
11288                         {
11289                                 debug_log("video plugin is already linked\n");
11290                         }
11291                         else
11292                         {
11293                                 debug_warning("add VIDEO to missing plugin\n");
11294                                 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
11295                         }
11296                 }
11297                 else if ( g_str_has_prefix(mime, "audio") )
11298                 {
11299                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
11300                         {
11301                                 debug_log("audio plugin is already linked\n");
11302                         }
11303                         else
11304                         {
11305                                 debug_warning("add AUDIO to missing plugin\n");
11306                                 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
11307                         }
11308                 }
11309         }
11310
11311 DONE:
11312         MMPLAYER_FLEAVE();
11313
11314         return MM_ERROR_NONE;
11315 }
11316
11317
11318 static void
11319 __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
11320 {
11321     mm_player_t* player = (mm_player_t*)data;
11322
11323         MMPLAYER_FENTER();
11324
11325         return_if_fail( player );
11326
11327         /* remove fakesink. */
11328         if ( !__mmplayer_gst_remove_fakesink( player,
11329                                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
11330         {
11331                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
11332                  * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
11333                  * source element are not same. To overcome this situation, this function will called
11334                  * several places and several times. Therefore, this is not an error case.
11335                  */
11336                 return;
11337         }
11338
11339         debug_log("pipeline has completely constructed\n");
11340
11341         if (( player->ini.async_start ) &&
11342                 ( player->msg_posted == FALSE ) &&
11343                 ( player->cmd >= MMPLAYER_COMMAND_START ))
11344         {
11345                 __mmplayer_handle_missed_plugin( player );
11346         }
11347
11348         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complete" );
11349 }
11350
11351 static gboolean
11352 __mmplayer_verify_next_play_path(mm_player_t *player)
11353 {
11354         MMHandleType attrs = 0;
11355         MMPlayerParseProfile profile;
11356         gint uri_idx = 0, check_cnt = 0;
11357         char *uri = NULL;
11358         gint mode = MM_PLAYER_PD_MODE_NONE;
11359         gint count = 0;
11360         guint num_of_list = 0;
11361
11362         MMPLAYER_FENTER();
11363
11364         debug_log("checking for gapless play");
11365
11366         if (player->pipeline->textbin)
11367         {
11368                 debug_error("subtitle path is enabled. gapless play is not supported.\n");
11369                 goto ERROR;
11370         }
11371
11372         attrs = MMPLAYER_GET_ATTRS(player);
11373         if ( !attrs )
11374         {
11375                 debug_error("fail to get attributes.\n");
11376                 goto ERROR;
11377         }
11378
11379         /* seamless playback is supported in case of audio only */
11380         mm_attrs_get_int_by_name(attrs, "content_video_found", &mode);
11381         if (mode)
11382         {
11383                 debug_log("video found");
11384                 goto ERROR;
11385         }
11386
11387         if (mm_attrs_get_int_by_name (attrs, "pd_mode", &mode) == MM_ERROR_NONE)
11388         {
11389                 if (mode == TRUE)
11390                 {
11391                         debug_warning("pd mode\n");
11392                         goto ERROR;
11393                 }
11394         }
11395
11396         if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
11397         {
11398                 debug_error("can not get play count\n");
11399         }
11400
11401         num_of_list = g_list_length(player->uri_info.uri_list);
11402
11403         debug_log("repeat count = %d, num_of_list = %d\n", count, num_of_list);
11404
11405         if ( num_of_list == 0 )
11406         {
11407                 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE)
11408                 {
11409                         debug_error("can not get profile_uri\n");
11410                         goto ERROR;
11411                 }
11412
11413                 if (!uri)
11414                 {
11415                         debug_error("uri list is empty.\n");
11416                         goto ERROR;
11417                 }
11418
11419                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
11420                 debug_log("add original path : %s ", uri);
11421
11422                 num_of_list = 1;
11423                 uri= NULL;
11424         }
11425
11426         uri_idx = player->uri_info.uri_idx;
11427
11428         while(TRUE)
11429         {
11430                 check_cnt++;
11431
11432                 if (check_cnt > num_of_list)
11433                 {
11434                         debug_error("there is no valid uri.");
11435                         goto ERROR;
11436                 }
11437
11438                 debug_log("uri idx : %d / %d\n", uri_idx, num_of_list);
11439
11440                 if ( uri_idx < num_of_list-1 )
11441                 {
11442                         uri_idx++;
11443                 }
11444                 else
11445                 {
11446                         if ((count <= 1) && (count != -1))
11447                         {
11448                                 debug_log("no repeat.");
11449                                 goto ERROR;
11450                         }
11451                         else if ( count > 1 )   /* decrease play count */
11452                         {
11453                                 /* we successeded to rewind. update play count and then wait for next EOS */
11454                                 count--;
11455
11456                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
11457
11458                                 /* commit attribute */
11459                                 if ( mmf_attrs_commit ( attrs ) )
11460                                 {
11461                                         debug_error("failed to commit attribute\n");
11462                                 }
11463                         }
11464
11465                         /* count < 0 : repeat continually */
11466                         uri_idx = 0;
11467                 }
11468
11469                 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
11470                 debug_log("uri idx : %d, uri = %s\n", uri_idx, uri);
11471
11472                 if (uri == NULL)
11473                 {
11474                         debug_warning("next uri does not exist\n");
11475                         continue;
11476                 }
11477
11478                 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE)
11479                 {
11480                         debug_error("failed to parse profile\n");
11481                         continue;
11482                 }
11483
11484                 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
11485                         (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP))
11486                 {
11487                         debug_warning("uri type is not supported (%d).", profile.uri_type);
11488                         continue;
11489                 }
11490
11491                 break;
11492         }
11493
11494         player->uri_info.uri_idx = uri_idx;
11495         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
11496
11497
11498         if (mmf_attrs_commit(player->attrs))
11499         {
11500                 debug_error("failed to commit.\n");
11501                 goto ERROR;
11502         }
11503
11504         debug_log("next uri %s (%d)\n", uri, uri_idx);
11505
11506         return TRUE;
11507
11508 ERROR:
11509
11510         debug_error("unable to play next path. EOS will be posted soon.\n");
11511         return FALSE;
11512 }
11513
11514 static void
11515 __mmplayer_initialize_next_play(mm_player_t *player)
11516 {
11517         int i;
11518
11519         MMPLAYER_FENTER();
11520
11521         player->smooth_streaming = FALSE;
11522         player->videodec_linked = 0;
11523         player->audiodec_linked = 0;
11524         player->videosink_linked = 0;
11525         player->audiosink_linked = 0;
11526         player->textsink_linked = 0;
11527         player->is_external_subtitle_present = FALSE;
11528         player->not_supported_codec = MISSING_PLUGIN_NONE;
11529         player->can_support_codec = FOUND_PLUGIN_NONE;
11530         player->pending_seek.is_pending = FALSE;
11531         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
11532         player->pending_seek.pos = 0;
11533         player->msg_posted = FALSE;
11534         player->has_many_types = FALSE;
11535         player->no_more_pad = FALSE;
11536         player->is_drm_file = FALSE;
11537         player->not_found_demuxer = 0;
11538         player->doing_seek = FALSE;
11539         player->max_audio_channels = 0;
11540         player->is_subtitle_force_drop = FALSE;
11541         player->play_subtitle = FALSE;
11542         player->use_textoverlay = FALSE;
11543         player->adjust_subtitle_pos = 0;
11544
11545         player->updated_bitrate_count = 0;
11546         player->total_bitrate = 0;
11547         player->updated_maximum_bitrate_count = 0;
11548         player->total_maximum_bitrate = 0;
11549
11550         _mmplayer_track_initialize(player);
11551
11552         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
11553         {
11554                 player->bitrate[i] = 0;
11555                 player->maximum_bitrate[i] = 0;
11556         }
11557
11558         if (player->v_stream_caps)
11559         {
11560                 gst_caps_unref(player->v_stream_caps);
11561                 player->v_stream_caps = NULL;
11562         }
11563
11564         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
11565         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
11566
11567         /* clean found parsers */
11568         if (player->parsers)
11569         {
11570                 GList *parsers = player->parsers;
11571                 for ( ;parsers ; parsers = g_list_next(parsers))
11572                 {
11573                         gchar *name = parsers->data;
11574                         MMPLAYER_FREEIF(name);
11575                 }
11576                 g_list_free(player->parsers);
11577                 player->parsers = NULL;
11578         }
11579
11580         /* clean found audio decoders */
11581         if (player->audio_decoders)
11582         {
11583                 GList *a_dec = player->audio_decoders;
11584                 for ( ;a_dec ; a_dec = g_list_next(a_dec))
11585                 {
11586                         gchar *name = a_dec->data;
11587                         MMPLAYER_FREEIF(name);
11588                 }
11589                 g_list_free(player->audio_decoders);
11590                 player->audio_decoders = NULL;
11591         }
11592
11593         MMPLAYER_FLEAVE();
11594 }
11595
11596 static void
11597 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
11598 {
11599         MMPlayerGstElement *mainbin = NULL;
11600         MMMessageParamType msg_param = {0,};
11601         GstElement *element = NULL;
11602         MMHandleType attrs = 0;
11603         char *uri = NULL;
11604         enum MainElementID elemId = MMPLAYER_M_NUM;
11605
11606         MMPLAYER_FENTER();
11607
11608         if ((player == NULL) ||
11609                 (player->pipeline == NULL) ||
11610                 (player->pipeline->mainbin == NULL))
11611         {
11612                 debug_error("player is null.\n");
11613                 goto ERROR;
11614         }
11615
11616         mainbin = player->pipeline->mainbin;
11617         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
11618
11619         attrs = MMPLAYER_GET_ATTRS(player);
11620         if ( !attrs )
11621         {
11622                 debug_error("fail to get attributes.\n");
11623                 goto ERROR;
11624         }
11625
11626         /* Initialize Player values */
11627         __mmplayer_initialize_next_play(player);
11628
11629         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
11630
11631         if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE)
11632         {
11633                 debug_error("failed to parse profile\n");
11634                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
11635                 goto ERROR;
11636         }
11637
11638         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
11639                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player)))
11640         {
11641                 debug_error("it's dash or hls. not support.");
11642                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
11643                 goto ERROR;
11644         }
11645
11646         /* setup source */
11647         switch ( player->profile.uri_type )
11648         {
11649                 /* file source */
11650                 case MM_PLAYER_URI_TYPE_FILE:
11651                 {
11652                         debug_log("using filesrc for 'file://' handler.\n");
11653
11654                         element = gst_element_factory_make("filesrc", "source");
11655
11656                         if ( !element )
11657                         {
11658                                 debug_error("failed to create filesrc\n");
11659                                 break;
11660                         }
11661
11662                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
11663                         break;
11664                 }
11665                 case MM_PLAYER_URI_TYPE_URL_HTTP:
11666                 {
11667                         gchar *user_agent, *proxy, *cookies, **cookie_list;
11668                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
11669                         user_agent = proxy = cookies = NULL;
11670                         cookie_list = NULL;
11671
11672                         element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
11673                         if ( !element )
11674                         {
11675                                 debug_error("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
11676                                 break;
11677                         }
11678                         debug_log("using http streamming source [%s].\n", player->ini.httpsrc_element);
11679
11680                         /* get attribute */
11681                         mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
11682                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
11683                         mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
11684                         mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
11685
11686                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
11687                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
11688                         {
11689                                 debug_log("get timeout from ini\n");
11690                                 http_timeout = player->ini.http_timeout;
11691                         }
11692
11693                         /* get attribute */
11694                         secure_debug_log("location : %s\n", player->profile.uri);
11695                         secure_debug_log("cookies : %s\n", cookies);
11696                         secure_debug_log("proxy : %s\n", proxy);
11697                         secure_debug_log("user_agent :  %s\n", user_agent);
11698                         debug_log("timeout : %d\n", http_timeout);
11699
11700                         /* setting property to streaming source */
11701                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
11702                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
11703                         g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
11704
11705                         /* check if prosy is vailid or not */
11706                         if ( util_check_valid_url ( proxy ) )
11707                                 g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
11708                         /* parsing cookies */
11709                         if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
11710                                 g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
11711                         if ( user_agent )
11712                                 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
11713                         break;
11714                 }
11715                 default:
11716                         debug_error("not support uri type %d\n", player->profile.uri_type);
11717                         break;
11718         }
11719
11720         if ( !element )
11721         {
11722                 debug_error("no source element was created.\n");
11723                 goto ERROR;
11724         }
11725
11726         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
11727         {
11728                 debug_error("failed to add source element to pipeline\n");
11729                 gst_object_unref(GST_OBJECT(element));
11730                 element = NULL;
11731                 goto ERROR;
11732         }
11733
11734         /* take source element */
11735         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
11736         mainbin[MMPLAYER_M_SRC].gst = element;
11737
11738         element = NULL;
11739
11740         if (MMPLAYER_IS_HTTP_STREAMING(player))
11741         {
11742                 if (player->streamer == NULL)
11743                 {
11744                         player->streamer = __mm_player_streaming_create();
11745                         __mm_player_streaming_initialize(player->streamer);
11746                 }
11747
11748                 elemId = MMPLAYER_M_TYPEFIND;
11749                 element = gst_element_factory_make("typefind", "typefinder");
11750                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
11751                         G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
11752         }
11753         else
11754         {
11755                 elemId = MMPLAYER_M_AUTOPLUG;
11756                 element = __mmplayer_create_decodebin(player);
11757         }
11758
11759         /* check autoplug element is OK */
11760         if ( ! element )
11761         {
11762                 debug_error("can not create element (%d)\n", elemId);
11763                 goto ERROR;
11764         }
11765
11766         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
11767         {
11768                 debug_error("failed to add sinkbin to pipeline\n");
11769                 gst_object_unref(GST_OBJECT(element));
11770                 element = NULL;
11771                 goto ERROR;
11772         }
11773
11774         mainbin[elemId].id = elemId;
11775         mainbin[elemId].gst = element;
11776
11777         if ( gst_element_link (mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE )
11778         {
11779                 debug_error("Failed to link src - autoplug (or typefind)\n");
11780                 goto ERROR;
11781         }
11782
11783         if (gst_element_set_state (mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE)
11784         {
11785                 debug_error("Failed to change state of src element\n");
11786                 goto ERROR;
11787         }
11788
11789         if (!MMPLAYER_IS_HTTP_STREAMING(player))
11790         {
11791                 if (gst_element_set_state (mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE)
11792                 {
11793                         debug_error("Failed to change state of decodebin\n");
11794                         goto ERROR;
11795                 }
11796         }
11797         else
11798         {
11799                 if (gst_element_set_state (mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE)
11800                 {
11801                         debug_error("Failed to change state of src element\n");
11802                         goto ERROR;
11803                 }
11804         }
11805
11806         player->gapless.stream_changed = TRUE;
11807         player->gapless.running = TRUE;
11808         MMPLAYER_FLEAVE();
11809         return;
11810
11811 ERROR:
11812         MMPLAYER_PLAYBACK_UNLOCK(player);
11813
11814         if (!player->msg_posted)
11815         {
11816                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
11817                 player->msg_posted = TRUE;
11818         }
11819         return;
11820 }
11821
11822 static gboolean
11823 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
11824 {
11825         mm_player_selector_t *selector = &player->selector[type];
11826         MMPlayerGstElement *sinkbin = NULL;
11827         enum MainElementID selectorId = MMPLAYER_M_NUM;
11828         enum MainElementID sinkId = MMPLAYER_M_NUM;
11829         GstPad *srcpad = NULL;
11830         GstPad *sinkpad = NULL;
11831
11832         MMPLAYER_FENTER();
11833         return_val_if_fail (player, FALSE);
11834
11835         debug_log("type %d", type);
11836
11837         switch (type)
11838         {
11839                 case MM_PLAYER_TRACK_TYPE_AUDIO:
11840                         selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
11841                         sinkId = MMPLAYER_A_BIN;
11842                         sinkbin = player->pipeline->audiobin;
11843                 break;
11844                 case MM_PLAYER_TRACK_TYPE_TEXT:
11845                         selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
11846                         sinkId = MMPLAYER_T_BIN;
11847                         sinkbin = player->pipeline->textbin;
11848                 break;
11849                 default:
11850                         debug_error("requested type is not supportable");
11851                         return FALSE;
11852                 break;
11853         }
11854
11855         if (player->pipeline->mainbin[selectorId].gst)
11856         {
11857                 gint n;
11858
11859                 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
11860
11861                 if (selector->event_probe_id != 0)
11862                         gst_pad_remove_probe (srcpad, selector->event_probe_id);
11863                 selector->event_probe_id = 0;
11864
11865                 if ((sinkbin) && (sinkbin[sinkId].gst))
11866                 {
11867                         sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
11868
11869                         if (srcpad && sinkpad)
11870                         {
11871                                 /* after getting drained signal there is no data flows, so no need to do pad_block */
11872                                 debug_log("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
11873                                 gst_pad_unlink (srcpad, sinkpad);
11874                         }
11875
11876                         gst_object_unref (sinkpad);
11877                         sinkpad = NULL;
11878                 }
11879                 gst_object_unref (srcpad);
11880                 srcpad = NULL;
11881
11882                 debug_log("selector release");
11883
11884                 /* release and unref requests pad from the selector */
11885                 for (n = 0; n < selector->channels->len; n++)
11886                 {
11887                         GstPad *sinkpad = g_ptr_array_index (selector->channels, n);
11888                         gst_element_release_request_pad ((player->pipeline->mainbin[selectorId].gst), sinkpad);
11889                 }
11890                 g_ptr_array_set_size (selector->channels, 0);
11891
11892                 gst_element_set_state (player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
11893                 gst_bin_remove (GST_BIN_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
11894
11895                 player->pipeline->mainbin[selectorId].gst = NULL;
11896                 selector = NULL;
11897         }
11898
11899         return TRUE;
11900 }
11901
11902 static void
11903 __mmplayer_deactivate_old_path(mm_player_t *player)
11904 {
11905         MMPLAYER_FENTER();
11906         return_if_fail ( player );
11907
11908         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
11909                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT)))
11910         {
11911                 debug_error("deactivate selector error");
11912                 goto ERROR;
11913         }
11914
11915         _mmplayer_track_destroy(player);
11916         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG );
11917
11918         if (player->streamer)
11919         {
11920                 __mm_player_streaming_deinitialize (player->streamer);
11921                 __mm_player_streaming_destroy(player->streamer);
11922                 player->streamer = NULL;
11923         }
11924
11925         MMPLAYER_PLAYBACK_LOCK(player);
11926         g_cond_signal( &player->next_play_thread_cond );
11927
11928         MMPLAYER_FLEAVE();
11929         return;
11930
11931 ERROR:
11932
11933         if (!player->msg_posted)
11934         {
11935                 MMMessageParamType msg = {0,};
11936
11937                 /*post error*/
11938                 msg.code = MM_ERROR_PLAYER_INTERNAL;
11939                 debug_error("next_uri_play> deactivate error");
11940
11941                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
11942                 player->msg_posted = TRUE;
11943         }
11944         return;
11945 }
11946
11947 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
11948 {
11949         int result = MM_ERROR_NONE;
11950         mm_player_t* player = (mm_player_t*) hplayer;
11951         MMPLAYER_FENTER();
11952
11953         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
11954
11955         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
11956         if (mmf_attrs_commit(player->attrs))
11957         {
11958                 debug_error("failed to commit the original uri.\n");
11959                 result = MM_ERROR_PLAYER_INTERNAL;
11960         }
11961         else
11962         {
11963                 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
11964                 {
11965                         debug_error("failed to add the original uri in the uri list.\n");
11966                 }
11967         }
11968
11969         MMPLAYER_FLEAVE();
11970         return result;
11971 }
11972
11973 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
11974 {
11975         mm_player_t* player = (mm_player_t*) hplayer;
11976         guint num_of_list = 0;
11977
11978         MMPLAYER_FENTER();
11979
11980         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
11981         return_val_if_fail (uri, MM_ERROR_INVALID_ARGUMENT);
11982
11983         if (player->pipeline && player->pipeline->textbin)
11984         {
11985                 debug_error("subtitle path is enabled.\n");
11986                 return MM_ERROR_PLAYER_INVALID_STATE;
11987         }
11988
11989         num_of_list = g_list_length(player->uri_info.uri_list);
11990
11991         if (is_first_path == TRUE)
11992         {
11993                 if (num_of_list == 0)
11994                 {
11995                         player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
11996                         debug_log("add original path : %s", uri);
11997                 }
11998                 else
11999                 {
12000                         player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
12001                         player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
12002
12003                         debug_log("change original path : %s", uri);
12004                 }
12005         }
12006         else
12007         {
12008                 if (num_of_list == 0)
12009                 {
12010                         MMHandleType attrs = 0;
12011                         char *original_uri = NULL;
12012
12013                         attrs = MMPLAYER_GET_ATTRS(player);
12014                         if ( attrs )
12015                         {
12016                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
12017
12018                                 if (!original_uri)
12019                                 {
12020                                         debug_error("there is no original uri.");
12021                                         return MM_ERROR_PLAYER_INVALID_STATE;
12022                                 }
12023
12024                                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
12025                                 player->uri_info.uri_idx = 0;
12026
12027                                 debug_log("add original path at first : %s (%d)", original_uri);
12028                         }
12029                 }
12030
12031                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12032                 debug_log("add new path : %s (total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
12033         }
12034
12035         MMPLAYER_FLEAVE();
12036         return MM_ERROR_NONE;
12037 }
12038
12039 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
12040 {
12041         mm_player_t* player = (mm_player_t*) hplayer;
12042         char *next_uri = NULL;
12043         guint num_of_list = 0;
12044
12045         MMPLAYER_FENTER();
12046         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12047
12048         num_of_list = g_list_length(player->uri_info.uri_list);
12049
12050         if (num_of_list > 0)
12051         {
12052                 gint uri_idx = player->uri_info.uri_idx;
12053
12054                 if ( uri_idx < num_of_list-1 )
12055                         uri_idx++;
12056                 else
12057                         uri_idx = 0;
12058
12059                 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12060                 debug_error("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
12061
12062                 *uri = g_strdup(next_uri);
12063         }
12064
12065         MMPLAYER_FLEAVE();
12066         return MM_ERROR_NONE;
12067 }
12068
12069 static void
12070 __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad,
12071 GstCaps *caps, gpointer data)
12072 {
12073         mm_player_t* player = (mm_player_t*)data;
12074         const gchar* klass = NULL;
12075         const gchar* mime = NULL;
12076         gchar* caps_str = NULL;
12077
12078         klass = gst_element_factory_get_metadata (gst_element_get_factory(elem), GST_ELEMENT_METADATA_KLASS);
12079         mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12080         caps_str = gst_caps_to_string(caps);
12081
12082         debug_warning("unknown type of caps : %s from %s",
12083                                         caps_str, GST_ELEMENT_NAME (elem));
12084
12085         MMPLAYER_FREEIF(caps_str);
12086
12087         /* There is no available codec. */
12088         __mmplayer_check_not_supported_codec (player, klass, mime);
12089 }
12090
12091 static gboolean
12092 __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad,
12093 GstCaps * caps,  gpointer data)
12094 {
12095         mm_player_t* player = (mm_player_t*)data;
12096         const char* mime = NULL;
12097         gboolean ret = TRUE;
12098
12099         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
12100         mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12101
12102         if (g_str_has_prefix(mime, "audio")) {
12103                 GstStructure* caps_structure = NULL;
12104                 gint samplerate = 0;
12105                 gint channels = 0;
12106                 gchar *caps_str = NULL;
12107
12108                 caps_structure = gst_caps_get_structure(caps, 0);
12109                 gst_structure_get_int (caps_structure, "rate", &samplerate);
12110                 gst_structure_get_int (caps_structure, "channels", &channels);
12111
12112                 if ( (channels > 0 && samplerate == 0)) {
12113                         debug_log("exclude audio...");
12114                         ret = FALSE;
12115                 }
12116
12117                 caps_str = gst_caps_to_string(caps);
12118                 /* set it directly because not sent by TAG */
12119                 if (g_strrstr(caps_str, "mobile-xmf")) {
12120                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
12121                 }
12122                 MMPLAYER_FREEIF (caps_str);
12123         } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
12124                 debug_log("already video linked");
12125                 ret = FALSE;
12126         } else {
12127                 debug_log("found new stream");
12128         }
12129
12130         return ret;
12131 }
12132
12133 static gint
12134 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad,
12135 GstCaps* caps, GstElementFactory* factory, gpointer data)
12136 {
12137         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
12138          We are defining our own and will be removed when it actually exposed */
12139         typedef enum {
12140                 GST_AUTOPLUG_SELECT_TRY,
12141                 GST_AUTOPLUG_SELECT_EXPOSE,
12142                 GST_AUTOPLUG_SELECT_SKIP
12143         } GstAutoplugSelectResult;
12144
12145         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
12146         mm_player_t* player = (mm_player_t*)data;
12147
12148         gchar* factory_name = NULL;
12149         gchar* caps_str = NULL;
12150         const gchar* klass = NULL;
12151         gint idx = 0;
12152
12153         factory_name = GST_OBJECT_NAME (factory);
12154         klass = gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
12155         caps_str = gst_caps_to_string(caps);
12156
12157 //      debug_log("found new element [%s] to link for caps [%s]", factory_name, caps_str);
12158         debug_log("found new element [%s] to link", factory_name);
12159
12160         /* store type string */
12161         if (player->type == NULL)
12162         {
12163                 player->type = gst_caps_to_string(caps);
12164                 __mmplayer_update_content_type_info(player);
12165         }
12166
12167         /* To support evasimagesink, omx is excluded temporarily*/
12168         int surface_type = 0;
12169         mm_attrs_get_int_by_name(player->attrs, "display_surface_client_type", &surface_type);
12170         if (surface_type == MM_DISPLAY_SURFACE_NULL)
12171                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
12172         debug_log("check display surface type attribute: %d", surface_type);
12173         if (surface_type == MM_DISPLAY_SURFACE_EVAS && strstr(factory_name, "omx"))
12174         {
12175                 debug_warning("skipping [%s] for supporting evasimagesink temporarily.\n", factory_name);
12176                 result = GST_AUTOPLUG_SELECT_SKIP;
12177                 goto DONE;
12178         }
12179
12180         /* filtering exclude keyword */
12181         for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
12182         {
12183                 if ( strstr(factory_name, player->ini.exclude_element_keyword[idx] ) )
12184                 {
12185                         debug_warning("skipping [%s] by exculde keyword [%s]\n",
12186                         factory_name, player->ini.exclude_element_keyword[idx] );
12187
12188                         // NOTE : does we need to check n_value against the number of item selected?
12189                         result = GST_AUTOPLUG_SELECT_SKIP;
12190                         goto DONE;
12191                 }
12192         }
12193
12194         /* check factory class for filtering */
12195         /* NOTE : msl don't need to use image plugins.
12196          * So, those plugins should be skipped for error handling.
12197          */
12198         if (g_strrstr(klass, "Codec/Decoder/Image"))
12199         {
12200                 debug_log("skipping [%s] by not required\n", factory_name);
12201                 result = GST_AUTOPLUG_SELECT_SKIP;
12202                 goto DONE;
12203         }
12204
12205         if ((MMPLAYER_IS_ES_BUFF_SRC(player)) &&
12206                 (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser"))))
12207         {
12208                 // TO CHECK : subtitle if needed, add subparse exception.
12209                 debug_log("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
12210                 result = GST_AUTOPLUG_SELECT_SKIP;
12211                 goto DONE;
12212         }
12213
12214         if (g_strrstr(factory_name, "mpegpsdemux"))
12215         {
12216                 debug_log("skipping PS container - not support\n");
12217                 result = GST_AUTOPLUG_SELECT_SKIP;
12218                 goto DONE;
12219         }
12220
12221         if (g_strrstr(factory_name, "mssdemux"))
12222                 player->smooth_streaming = TRUE;
12223
12224         /* check ALP Codec can be used or not */
12225         if ((g_strrstr(klass, "Codec/Decoder/Audio")))
12226         {
12227                 GstStructure* str = NULL;
12228                 gint channels = 0;
12229
12230                 str = gst_caps_get_structure( caps, 0 );
12231                 if ( str )
12232                 {
12233                         gst_structure_get_int (str, "channels", &channels);
12234
12235                         debug_log ("check audio ch : %d %d\n", player->max_audio_channels, channels);
12236                         if (player->max_audio_channels < channels)
12237                         {
12238                                 player->max_audio_channels = channels;
12239                         }
12240                 }
12241
12242                 if (!player->audiodec_linked)
12243                 {
12244                         /* set stream information */
12245                         __mmplayer_set_audio_attrs (player, caps);
12246                 }
12247         }
12248         else if ((g_strrstr(klass, "Codec/Decoder/Video")))
12249         {
12250                 if (g_strrstr(factory_name, "omx_"))
12251                 {
12252                         char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
12253                         if (env != NULL)
12254                         {
12255                                 if (strncasecmp(env, "yes", 3) == 0)
12256                                 {
12257                                         debug_log ("skipping [%s] by disabled\n", factory_name);
12258                                         result = GST_AUTOPLUG_SELECT_SKIP;
12259                                         goto DONE;
12260                                 }
12261                         }
12262                 }
12263         }
12264
12265         if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
12266                 (g_strrstr(klass, "Codec/Decoder/Video")))
12267         {
12268                 gint stype = 0;
12269                 gint width = 0;
12270                 GstStructure *str = NULL;
12271                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
12272
12273                 /* don't make video because of not required */
12274                 if (stype == MM_DISPLAY_SURFACE_NULL)
12275                 {
12276                         debug_log ("no video because it's not required. -> return expose");
12277                         if (player->set_mode.media_packet_video_stream == FALSE)
12278                         {
12279                                 result = GST_AUTOPLUG_SELECT_EXPOSE;
12280                                 goto DONE;
12281                         }
12282                 }
12283
12284                 /* get w/h for omx state-tune */
12285                 str = gst_caps_get_structure (caps, 0);
12286                 gst_structure_get_int (str, "width", &width);
12287
12288                 if (width != 0) {
12289                         if (player->v_stream_caps) {
12290                                 gst_caps_unref(player->v_stream_caps);
12291                                 player->v_stream_caps = NULL;
12292                         }
12293
12294                         player->v_stream_caps = gst_caps_copy(caps);
12295                         debug_log ("take caps for video state tune");
12296                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
12297                 }
12298         }
12299
12300         if (g_strrstr(klass, "Decoder"))
12301         {
12302                 const char* mime = NULL;
12303                 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12304
12305                 if (g_str_has_prefix(mime, "video"))
12306                 {
12307                         // __mmplayer_check_video_zero_cpoy(player, factory);
12308
12309                         player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
12310                         player->can_support_codec |= FOUND_PLUGIN_VIDEO;
12311
12312                         player->videodec_linked = 1;
12313                 }
12314                 else if(g_str_has_prefix(mime, "audio"))
12315                 {
12316                         player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
12317                         player->can_support_codec |= FOUND_PLUGIN_AUDIO;
12318
12319                         player->audiodec_linked = 1;
12320                 }
12321         }
12322
12323 DONE:
12324         MMPLAYER_FREEIF(caps_str);
12325
12326         return result;
12327 }
12328
12329
12330 #if 0
12331 static GValueArray*
12332 __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad,
12333 GstCaps * caps,  gpointer data)
12334 {
12335         //mm_player_t* player = (mm_player_t*)data;
12336
12337         debug_log("decodebin is requesting factories for caps [%s] from element[%s]",
12338                 gst_caps_to_string(caps),
12339                 GST_ELEMENT_NAME(GST_PAD_PARENT(pad)));
12340
12341         return NULL;
12342 }
12343 #endif
12344
12345 static void
12346 __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad,
12347 gpointer data) // @
12348 {
12349         //mm_player_t* player = (mm_player_t*)data;
12350         GstCaps* caps = NULL;
12351
12352         debug_log("[Decodebin2] pad-removed signal\n");
12353
12354         caps = gst_pad_query_caps(new_pad, NULL);
12355         if (caps)
12356         {
12357                 gchar* caps_str = NULL;
12358                 caps_str = gst_caps_to_string(caps);
12359
12360                 debug_log("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem) );
12361
12362                 MMPLAYER_FREEIF(caps_str);
12363         }
12364 }
12365
12366 static void
12367 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
12368 {
12369         mm_player_t* player = (mm_player_t*)data;
12370
12371         MMPLAYER_FENTER();
12372         return_if_fail ( player );
12373
12374         debug_log("__mmplayer_gst_decode_drained");
12375
12376         if (player->use_deinterleave == TRUE)
12377         {
12378                 debug_log("group playing mode.");
12379                 return;
12380         }
12381
12382         if (!g_mutex_trylock(&player->cmd_lock))
12383         {
12384                 debug_warning("Fail to get cmd lock");
12385                 return;
12386         }
12387
12388         if (!__mmplayer_verify_next_play_path(player))
12389         {
12390                 debug_log("decoding is finished.");
12391                 player->gapless.running = FALSE;
12392                 player->gapless.start_time = 0;
12393                 g_mutex_unlock(&player->cmd_lock);
12394                 return;
12395         }
12396
12397         player->gapless.reconfigure = TRUE;
12398
12399         /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
12400         __mmplayer_deactivate_old_path(player);
12401
12402         g_mutex_unlock(&player->cmd_lock);
12403
12404         MMPLAYER_FLEAVE();
12405 }
12406
12407 static void
12408 __mmplayer_gst_element_added (GstElement *bin, GstElement *element, gpointer data)
12409 {
12410         mm_player_t* player = (mm_player_t*)data;
12411         const gchar* klass = NULL;
12412         gchar* factory_name = NULL;
12413
12414         klass = gst_element_factory_get_metadata (gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
12415         factory_name = GST_OBJECT_NAME (gst_element_get_factory(element));
12416
12417         debug_log("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
12418
12419         if (__mmplayer_add_dump_buffer_probe(player, element))
12420                 debug_log("add buffer probe");
12421
12422         //<-
12423         if (g_strrstr(klass, "Codec/Decoder/Audio"))
12424         {
12425                 gchar* selected = NULL;
12426                 selected = g_strdup( GST_ELEMENT_NAME(element));
12427                 player->audio_decoders = g_list_append (player->audio_decoders, selected);
12428         }
12429         //-> temp code
12430
12431         if (g_strrstr(klass, "Parser"))
12432         {
12433                 gchar* selected = NULL;
12434
12435                 selected = g_strdup (factory_name);
12436                 player->parsers = g_list_append (player->parsers, selected);
12437         }
12438
12439         if ((g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) && !(g_strrstr(klass, "Adaptive")))
12440         {
12441                 /* FIXIT : first value will be overwritten if there's more
12442                  * than 1 demuxer/parser
12443                  */
12444
12445                 //debug_log ("plugged element is demuxer. take it\n");
12446                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
12447                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
12448
12449                 /*Added for multi audio support */ // Q. del?
12450                 if (g_strrstr(klass, "Demux"))
12451                 {
12452                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
12453                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
12454                 }
12455         }
12456
12457         if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux"))
12458         {
12459                 int surface_type = 0;
12460
12461                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
12462
12463 #if 0   // this is for 0.10 plugin with downstream modification
12464                 /* playback protection if drm file */
12465                 if (player->use_video_stream || surface_type == MM_DISPLAY_SURFACE_EVAS || surface_type == MM_DISPLAY_SURFACE_X_EXT)
12466                 {
12467                         debug_log("playback can be protected if playready drm");
12468                         g_object_set (G_OBJECT(element), "playback-protection", TRUE, NULL);
12469                 }
12470 #endif
12471         }
12472
12473         // to support trust-zone only
12474         if (g_strrstr(factory_name, "asfdemux"))
12475         {
12476                 debug_log ("set file-location %s\n", player->profile.uri);
12477                 g_object_set (G_OBJECT(element), "file-location", player->profile.uri, NULL);
12478
12479                 if (player->video_hub_download_mode == TRUE)
12480                 {
12481                         g_object_set (G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
12482                 }
12483         }
12484         else if (g_strrstr(factory_name, "legacyh264parse"))
12485         {
12486                 debug_log ("[%s] output-format to legacyh264parse\n", "mssdemux");
12487                 g_object_set (G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
12488         }
12489         else if (g_strrstr(factory_name, "mpegaudioparse"))
12490         {
12491                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
12492                         (__mmplayer_is_only_mp3_type(player->type)))
12493                 {
12494                         debug_log ("[mpegaudioparse] set streaming pull mode.");
12495                         g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
12496                 }
12497         }
12498         else if (g_strrstr(factory_name, "omx"))
12499         {
12500                 if (g_strrstr(klass, "Codec/Decoder/Video"))
12501                 {
12502                         gboolean ret = FALSE;
12503
12504                         if (player->v_stream_caps != NULL)
12505                         {
12506                                 GstPad *pad = gst_element_get_static_pad(element, "sink");
12507
12508                                 if (pad)
12509                                 {
12510                                         ret = gst_pad_set_caps(pad, player->v_stream_caps);
12511                                         debug_log("found omx decoder, setting gst_pad_set_caps for omx (ret:%d)", ret);
12512                                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
12513                                         gst_object_unref (pad);
12514                                 }
12515                         }
12516                         g_object_set (G_OBJECT(element), "state-tuning", TRUE, NULL);
12517                 }
12518 #ifdef _MM_PLAYER_ALP_PARSER
12519                 if (g_strrstr(factory_name, "omx_mp3dec"))
12520                 {
12521                         g_list_foreach (player->parsers, check_name, player);
12522                 }
12523 #endif
12524                 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
12525         }
12526
12527         if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
12528                 (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue")))
12529         {
12530                 debug_log ("plugged element is multiqueue. take it\n");
12531
12532                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
12533                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
12534
12535                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
12536                         (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)))
12537                 {
12538                         /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
12539                         __mm_player_streaming_set_multiqueue(player->streamer,
12540                                 element,
12541                                 TRUE,
12542                                 player->ini.http_buffering_time,
12543                                 1.0,
12544                                 player->ini.http_buffering_limit);
12545
12546                         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
12547                 }
12548         }
12549
12550         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-added" );
12551         return;
12552 }
12553
12554 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
12555 {
12556         MMPLAYER_FENTER();
12557         return_val_if_fail ( player, FALSE );
12558
12559         if ( MMPLAYER_IS_STREAMING(player) )
12560                 return FALSE;
12561
12562         /* This callback can be set to music player only. */
12563         if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
12564         {
12565                 debug_warning("audio callback is not supported for video");
12566                 return FALSE;
12567         }
12568
12569         if (player->audio_stream_cb)
12570         {
12571                 {
12572                         GstPad *pad = NULL;
12573
12574                         pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
12575
12576                         if ( !pad )
12577                         {
12578                                 debug_error("failed to get sink pad from audiosink to probe data\n");
12579                                 return FALSE;
12580                         }
12581                         player->audio_cb_probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
12582                                 __mmplayer_audio_stream_probe, player, NULL);
12583
12584                         gst_object_unref (pad);
12585
12586                         pad = NULL;
12587                }
12588         }
12589         else
12590         {
12591                 debug_error("There is no audio callback to configure.\n");
12592                 return FALSE;
12593         }
12594
12595         MMPLAYER_FLEAVE();
12596
12597         return TRUE;
12598 }
12599
12600 static void
12601 __mmplayer_init_factories(mm_player_t* player) // @
12602 {
12603         return_if_fail ( player );
12604
12605         player->factories = gst_registry_feature_filter(gst_registry_get(),
12606                                         (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
12607         player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
12608 }
12609
12610 static void
12611 __mmplayer_release_factories(mm_player_t* player) // @
12612 {
12613         MMPLAYER_FENTER();
12614         return_if_fail ( player );
12615
12616         if (player->factories)
12617         {
12618                 gst_plugin_feature_list_free (player->factories);
12619                 player->factories = NULL;
12620         }
12621
12622         MMPLAYER_FLEAVE();
12623 }
12624
12625 static void
12626 __mmplayer_release_misc(mm_player_t* player)
12627 {
12628         int i;
12629         gboolean cur_mode = player->set_mode.rich_audio;
12630         MMPLAYER_FENTER();
12631
12632         return_if_fail ( player );
12633
12634         player->use_video_stream = FALSE;
12635         player->video_stream_cb = NULL;
12636         player->video_stream_cb_user_param = NULL;
12637
12638         player->audio_stream_cb = NULL;
12639         player->audio_stream_render_cb_ex = NULL;
12640         player->audio_stream_cb_user_param = NULL;
12641         player->audio_stream_sink_sync = false;
12642
12643         player->video_stream_changed_cb = NULL;
12644         player->video_stream_changed_cb_user_param = NULL;
12645
12646         player->audio_stream_changed_cb = NULL;
12647         player->audio_stream_changed_cb_user_param = NULL;
12648
12649         player->sent_bos = FALSE;
12650         player->playback_rate = DEFAULT_PLAYBACK_RATE;
12651
12652         player->doing_seek = FALSE;
12653
12654         player->updated_bitrate_count = 0;
12655         player->total_bitrate = 0;
12656         player->updated_maximum_bitrate_count = 0;
12657         player->total_maximum_bitrate = 0;
12658
12659         player->not_found_demuxer = 0;
12660
12661         player->last_position = 0;
12662         player->duration = 0;
12663         player->http_content_size = 0;
12664         player->not_supported_codec = MISSING_PLUGIN_NONE;
12665         player->can_support_codec = FOUND_PLUGIN_NONE;
12666         player->pending_seek.is_pending = FALSE;
12667         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
12668         player->pending_seek.pos = 0;
12669         player->msg_posted = FALSE;
12670         player->has_many_types = FALSE;
12671         player->is_drm_file = FALSE;
12672         player->max_audio_channels = 0;
12673         player->video_share_api_delta = 0;
12674         player->video_share_clock_delta = 0;
12675         player->sound_focus.keep_last_pos = FALSE;
12676         player->sound_focus.acquired = FALSE;
12677         player->is_subtitle_force_drop = FALSE;
12678         player->play_subtitle = FALSE;
12679         player->use_textoverlay = FALSE;
12680         player->adjust_subtitle_pos = 0;
12681         player->last_multiwin_status = FALSE;
12682         player->has_closed_caption = FALSE;
12683         player->set_mode.media_packet_video_stream = FALSE;
12684         memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
12685         /* recover mode */
12686         player->set_mode.rich_audio = cur_mode;
12687
12688         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
12689         {
12690                 player->bitrate[i] = 0;
12691                 player->maximum_bitrate[i] = 0;
12692         }
12693
12694         /* remove media stream cb (appsrc cb) */
12695         for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++)
12696         {
12697                 player->media_stream_buffer_status_cb[i] = NULL;
12698                 player->media_stream_seek_data_cb[i] = NULL;
12699         }
12700
12701         /* free memory related to audio effect */
12702         MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
12703
12704         if (player->state_tune_caps)
12705         {
12706                 gst_caps_unref(player->state_tune_caps);
12707                 player->state_tune_caps = NULL;
12708         }
12709
12710         if (player->video_cb_probe_id)
12711         {
12712                 GstPad *pad = NULL;
12713
12714                 pad = gst_element_get_static_pad (player->video_fakesink, "sink");
12715
12716                 if (pad) {
12717                         debug_log("release video probe\n");
12718
12719                         /* release audio callback */
12720                         gst_pad_remove_probe (pad, player->video_cb_probe_id);
12721                         player->video_cb_probe_id = 0;
12722                         player->video_stream_cb = NULL;
12723                         player->video_stream_cb_user_param = NULL;
12724                 }
12725         }
12726
12727         MMPLAYER_FLEAVE();
12728 }
12729
12730 static void
12731 __mmplayer_release_misc_post(mm_player_t* player)
12732 {
12733         char *original_uri = NULL;
12734         MMPLAYER_FENTER();
12735
12736         /* player->pipeline is already released before. */
12737
12738         return_if_fail ( player );
12739
12740         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
12741         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
12742
12743         /* clean found parsers */
12744         if (player->parsers)
12745         {
12746                 GList *parsers = player->parsers;
12747                 for ( ;parsers ; parsers = g_list_next(parsers))
12748                 {
12749                         gchar *name = parsers->data;
12750                         MMPLAYER_FREEIF(name);
12751                 }
12752                 g_list_free(player->parsers);
12753                 player->parsers = NULL;
12754         }
12755
12756         /* clean found audio decoders */
12757         if (player->audio_decoders)
12758         {
12759                 GList *a_dec = player->audio_decoders;
12760                 for ( ;a_dec ; a_dec = g_list_next(a_dec))
12761                 {
12762                         gchar *name = a_dec->data;
12763                         MMPLAYER_FREEIF(name);
12764                 }
12765                 g_list_free(player->audio_decoders);
12766                 player->audio_decoders = NULL;
12767         }
12768
12769         /* clean the uri list except original uri */
12770         if (player->uri_info.uri_list)
12771         {
12772                 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
12773
12774                 if (player->attrs)
12775                 {
12776                         mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
12777                         debug_log("restore original uri = %s\n", original_uri);
12778
12779                         if (mmf_attrs_commit(player->attrs))
12780                         {
12781                                 debug_error("failed to commit the original uri.\n");
12782                         }
12783                 }
12784
12785                 GList *uri_list = player->uri_info.uri_list;
12786                 for ( ;uri_list ; uri_list = g_list_next(uri_list))
12787                 {
12788                         gchar *uri = uri_list->data;
12789                         MMPLAYER_FREEIF(uri);
12790                 }
12791                 g_list_free(player->uri_info.uri_list);
12792                 player->uri_info.uri_list = NULL;
12793         }
12794
12795         player->uri_info.uri_idx = 0;
12796         MMPLAYER_FLEAVE();
12797 }
12798
12799 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
12800 {
12801         GstElement *element = NULL;
12802         GstPad *sinkpad;
12803
12804         debug_log("creating %s to plug\n", name);
12805
12806         element = gst_element_factory_make(name, NULL);
12807         if ( ! element )
12808         {
12809                 debug_error("failed to create queue\n");
12810                 return NULL;
12811         }
12812
12813         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
12814         {
12815                 debug_error("failed to set state READY to %s\n", name);
12816                 gst_object_unref (element);
12817                 return NULL;
12818         }
12819
12820         if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
12821         {
12822                 debug_error("failed to add %s\n", name);
12823                 gst_object_unref (element);
12824                 return NULL;
12825         }
12826
12827         sinkpad = gst_element_get_static_pad(element, "sink");
12828
12829         if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
12830         {
12831                 debug_error("failed to link %s\n", name);
12832                 gst_object_unref (sinkpad);
12833                 gst_object_unref (element);
12834                 return NULL;
12835         }
12836
12837         debug_log("linked %s to pipeline successfully\n", name);
12838
12839         gst_object_unref (sinkpad);
12840
12841         return element;
12842 }
12843
12844 static gboolean
12845 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
12846 const char *padname, const GList *templlist)
12847 {
12848         GstPad *pad = NULL;
12849         gboolean has_dynamic_pads = FALSE;
12850         gboolean has_many_types = FALSE;
12851         const char *klass = NULL;
12852         GstStaticPadTemplate *padtemplate = NULL;
12853         GstElementFactory *factory = NULL;
12854         GstElement* queue = NULL;
12855         GstElement* parser = NULL;
12856         GstPad *pssrcpad = NULL;
12857         GstPad *qsrcpad = NULL, *qsinkpad = NULL;
12858         MMPlayerGstElement *mainbin = NULL;
12859         GstStructure* str = NULL;
12860         GstCaps* srccaps = NULL;
12861         GstState target_state = GST_STATE_READY;
12862         gboolean isvideo_decoder = FALSE;
12863         guint q_max_size_time = 0;
12864
12865         MMPLAYER_FENTER();
12866
12867         return_val_if_fail ( player &&
12868                 player->pipeline &&
12869                 player->pipeline->mainbin,
12870                 FALSE );
12871
12872         mainbin = player->pipeline->mainbin;
12873
12874         debug_log("plugging pad %s:%s to newly create %s:%s\n",
12875                         GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
12876                         GST_PAD_NAME( srcpad ),
12877                         GST_ELEMENT_NAME( sinkelement ),
12878                         padname);
12879
12880         factory = gst_element_get_factory(sinkelement);
12881         klass = gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
12882
12883         /* check if player can do start continually */
12884         MMPLAYER_CHECK_CMD_IF_EXIT(player);
12885
12886         /* need it to warm up omx before linking to pipeline */
12887         if (g_strrstr(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ), "demux"))
12888         {
12889                 debug_log("get demux caps.\n");
12890                 if (player->state_tune_caps)
12891                 {
12892                         gst_caps_unref(player->state_tune_caps);
12893                         player->state_tune_caps = NULL;
12894                 }
12895                 player->state_tune_caps = gst_caps_copy(gst_pad_get_current_caps(srcpad));
12896         }
12897
12898         /* NOTE : OMX Codec can check if resource is available or not at this state. */
12899         if (g_strrstr(GST_ELEMENT_NAME(sinkelement), "omx"))
12900         {
12901                 if (player->state_tune_caps != NULL)
12902                 {
12903                         debug_log("set demux's caps to omx codec if resource is available");
12904                         if (gst_pad_set_caps(gst_element_get_static_pad(sinkelement, "sink"), player->state_tune_caps))
12905                         {
12906                                 target_state = GST_STATE_PAUSED;
12907                                 isvideo_decoder = TRUE;
12908                                 g_object_set(G_OBJECT(sinkelement), "state-tuning", TRUE, NULL);
12909                         }
12910                         else
12911                         {
12912                                 debug_warning("failed to set caps for state tuning");
12913                         }
12914                 }
12915                 gst_caps_unref(player->state_tune_caps);
12916                 player->state_tune_caps = NULL;
12917         }
12918
12919         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, target_state) )
12920         {
12921                 debug_error("failed to set %d state to %s\n", target_state, GST_ELEMENT_NAME( sinkelement ));
12922                 if (isvideo_decoder)
12923                 {
12924                         gst_element_set_state(sinkelement, GST_STATE_NULL);
12925                         gst_object_unref(G_OBJECT(sinkelement));
12926                         player->keep_detecting_vcodec = TRUE;
12927                 }
12928                 goto ERROR;
12929         }
12930
12931         /* add to pipeline */
12932         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
12933         {
12934                 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
12935                 goto ERROR;
12936         }
12937
12938         debug_log("element klass : %s\n", klass);
12939
12940         /* added to support multi track files */
12941         /* only decoder case and any of the video/audio still need to link*/
12942         if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
12943         {
12944                 gchar *name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
12945
12946                 if (g_strrstr(name, "mpegtsdemux")|| g_strrstr(name, "mssdemux"))
12947                 {
12948                         gchar *src_demux_caps_str = NULL;
12949                         gchar *needed_parser = NULL;
12950                         GstCaps *src_demux_caps = NULL;
12951                         gboolean smooth_streaming = FALSE;
12952
12953                         src_demux_caps = gst_pad_query_caps(srcpad, NULL);
12954                         src_demux_caps_str = gst_caps_to_string(src_demux_caps);
12955
12956                         gst_caps_unref(src_demux_caps);
12957
12958                         if (g_strrstr(src_demux_caps_str, "video/x-h264"))
12959                         {
12960                                 if (g_strrstr(name, "mssdemux"))
12961                                 {
12962                                         needed_parser = g_strdup("legacyh264parse");
12963                                         smooth_streaming = TRUE;
12964                                 }
12965                                 else
12966                                 {
12967                                         needed_parser = g_strdup("h264parse");
12968                                 }
12969                         }
12970                         else if (g_strrstr(src_demux_caps_str, "video/mpeg"))
12971                         {
12972                                 needed_parser = g_strdup("mpeg4videoparse");
12973                         }
12974                         MMPLAYER_FREEIF(src_demux_caps_str);
12975
12976                         if (needed_parser)
12977                         {
12978                                 parser = __mmplayer_element_create_and_link(player, srcpad, needed_parser);
12979                                 MMPLAYER_FREEIF(needed_parser);
12980
12981                                 if ( !parser )
12982                                 {
12983                                         debug_error("failed to create parser\n");
12984                                 }
12985                                 else
12986                                 {
12987                                         if (smooth_streaming)
12988                                         {
12989                                                 g_object_set (parser, "output-format", 1, NULL); /* NALU/Byte Stream format */
12990                                         }
12991
12992                                         /* update srcpad if parser is created */
12993                                         pssrcpad = gst_element_get_static_pad(parser, "src");
12994                                         srcpad = pssrcpad;
12995                                 }
12996                         }
12997                 }
12998                 MMPLAYER_FREEIF(name);
12999
13000                 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
13001                 if ( ! queue )
13002                 {
13003                         debug_error("failed to create queue\n");
13004                         goto ERROR;
13005                 }
13006
13007                 /* update srcpad to link with decoder */
13008                 qsrcpad = gst_element_get_static_pad(queue, "src");
13009                 srcpad = qsrcpad;
13010
13011                 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
13012
13013                 /* assigning queue handle for futher manipulation purpose */
13014                 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
13015                 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
13016                 {
13017                         mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
13018                         mainbin[MMPLAYER_M_Q1].gst = queue;
13019
13020                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
13021                         {
13022                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", 0 , NULL);
13023                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-buffers", 2, NULL);
13024                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-bytes", 0, NULL);
13025                         }
13026                         else
13027                         {
13028                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
13029                                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
13030                         }
13031                 }
13032                 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
13033                 {
13034                         mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
13035                         mainbin[MMPLAYER_M_Q2].gst = queue;
13036
13037                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
13038                         {
13039                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", 0 , NULL);
13040                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-buffers", 2, NULL);
13041                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-bytes", 0, NULL);
13042                         }
13043                         else
13044                         {
13045                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
13046                                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
13047                         }
13048                 }
13049                 else
13050                 {
13051                         debug_error("Not supporting more then two elementary stream\n");
13052                         g_assert(1);
13053                 }
13054
13055                 pad = gst_element_get_static_pad(sinkelement, padname);
13056
13057                 if ( ! pad )
13058                 {
13059                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
13060                                 padname, GST_ELEMENT_NAME(sinkelement) );
13061
13062                         pad = gst_element_get_static_pad(sinkelement, "sink");
13063                         if ( ! pad )
13064                         {
13065                                 debug_error("failed to get pad(sink) from %s. \n",
13066                                 GST_ELEMENT_NAME(sinkelement) );
13067                                 goto ERROR;
13068                         }
13069                 }
13070
13071                 /*  to check the video/audio type set the proper flag*/
13072                 const gchar *mime_type = NULL;
13073                 {
13074                         srccaps = gst_pad_query_caps(srcpad, NULL);
13075                         if ( !srccaps )
13076                                 goto ERROR;
13077
13078                         str = gst_caps_get_structure( srccaps, 0 );
13079                         if ( ! str )
13080                                 goto ERROR;
13081
13082                         mime_type = gst_structure_get_name(str);
13083                         if ( ! mime_type )
13084                                 goto ERROR;
13085                 }
13086
13087                 /* link queue and decoder. so, it will be queue - decoder. */
13088                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
13089                 {
13090                         gst_object_unref(GST_OBJECT(pad));
13091                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
13092
13093                         /* reconstitute supportable codec */
13094                         if (strstr(mime_type, "video"))
13095                         {
13096                                 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
13097                         }
13098                         else if (strstr(mime_type, "audio"))
13099                         {
13100                                 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
13101                         }
13102                         goto ERROR;
13103                 }
13104
13105                 if (strstr(mime_type, "video"))
13106                 {
13107                         player->videodec_linked = 1;
13108                         debug_msg("player->videodec_linked set to 1\n");
13109
13110                 }
13111                 else if (strstr(mime_type, "audio"))
13112                 {
13113                         player->audiodec_linked = 1;
13114                         debug_msg("player->auddiodec_linked set to 1\n");
13115                 }
13116
13117                 gst_object_unref(GST_OBJECT(pad));
13118                 gst_caps_unref(GST_CAPS(srccaps));
13119                 srccaps = NULL;
13120         }
13121
13122         if ( !MMPLAYER_IS_HTTP_PD(player) )
13123         {
13124                 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
13125                 {
13126                         if (MMPLAYER_IS_HTTP_STREAMING(player))
13127                         {
13128                                 gint64 dur_bytes = 0L;
13129                                 gchar *file_buffering_path = NULL;
13130                                 gboolean use_file_buffer = FALSE;
13131
13132                                 if ( !mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
13133                                 {
13134                                         debug_log("creating http streaming buffering queue\n");
13135
13136                                         queue = gst_element_factory_make("queue2", "queue2");
13137                                         if ( ! queue )
13138                                         {
13139                                                 debug_error ( "failed to create buffering queue element\n" );
13140                                                 goto ERROR;
13141                                         }
13142
13143                                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
13144                                         {
13145                                                 debug_error("failed to set state READY to buffering queue\n");
13146                                                 goto ERROR;
13147                                         }
13148
13149                                         if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
13150                                         {
13151                                                 debug_error("failed to add buffering queue\n");
13152                                                 goto ERROR;
13153                                         }
13154
13155                                         qsinkpad = gst_element_get_static_pad(queue, "sink");
13156                                         qsrcpad = gst_element_get_static_pad(queue, "src");
13157
13158                                         if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
13159                                         {
13160                                                 debug_error("failed to link buffering queue\n");
13161                                                 goto ERROR;
13162                                         }
13163                                         srcpad = qsrcpad;
13164
13165
13166                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
13167                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue;
13168
13169                                         if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
13170                                         {
13171                                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
13172                                                         debug_error("fail to get duration.\n");
13173
13174                                                 if (dur_bytes > 0)
13175                                                 {
13176                                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
13177                                                         file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
13178                                                 }
13179                                                 else
13180                                                 {
13181                                                         dur_bytes = 0;
13182                                                 }
13183                                         }
13184
13185                                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
13186                                         if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
13187                                         {
13188                                                 __mm_player_streaming_set_queue2(player->streamer,
13189                                                         queue,
13190                                                         TRUE,
13191                                                         player->ini.http_max_size_bytes,
13192                                                         player->ini.http_buffering_time,
13193                                                         1.0,
13194                                                         player->ini.http_buffering_limit,
13195                                                         use_file_buffer,
13196                                                         file_buffering_path,
13197                                                         (guint64)dur_bytes);
13198                                         }
13199
13200                                         MMPLAYER_FREEIF(file_buffering_path);
13201                                 }
13202                         }
13203                 }
13204         }
13205         /* if it is not decoder or */
13206         /* in decoder case any of the video/audio still need to link*/
13207         if(!g_strrstr(klass, "Decoder"))
13208         {
13209
13210                 pad = gst_element_get_static_pad(sinkelement, padname);
13211                 if ( ! pad )
13212                 {
13213                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
13214                                         padname, GST_ELEMENT_NAME(sinkelement) );
13215
13216                         pad = gst_element_get_static_pad(sinkelement, "sink");
13217
13218                         if ( ! pad )
13219                         {
13220                                 debug_error("failed to get pad(sink) from %s. \n",
13221                                         GST_ELEMENT_NAME(sinkelement) );
13222                                 goto ERROR;
13223                         }
13224                 }
13225
13226                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
13227                 {
13228                         gst_object_unref(GST_OBJECT(pad));
13229                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
13230                         goto ERROR;
13231                 }
13232
13233                 gst_object_unref(GST_OBJECT(pad));
13234         }
13235
13236         for(;templlist != NULL; templlist = templlist->next)
13237         {
13238                 padtemplate = templlist->data;
13239
13240                 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
13241
13242                 if(     padtemplate->direction != GST_PAD_SRC ||
13243                         padtemplate->presence == GST_PAD_REQUEST        )
13244                         continue;
13245
13246                 switch(padtemplate->presence)
13247                 {
13248                         case GST_PAD_ALWAYS:
13249                         {
13250                                 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
13251                                 GstCaps *caps = gst_pad_query_caps(srcpad, NULL);
13252
13253                                 /* Check whether caps has many types */
13254                                 if ( !gst_caps_is_fixed(caps))
13255                                 {
13256                                         debug_log ("always pad but, caps has many types");
13257                                         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
13258                                         has_many_types = TRUE;
13259                                         break;
13260                                 }
13261
13262                                 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
13263                                 {
13264                                         gst_object_unref(GST_OBJECT(srcpad));
13265                                         gst_caps_unref(GST_CAPS(caps));
13266
13267                                         debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
13268                                         goto ERROR;
13269                                 }
13270
13271                                 gst_caps_unref(GST_CAPS(caps));
13272                                 gst_object_unref(GST_OBJECT(srcpad));
13273
13274                         }
13275                         break;
13276
13277
13278                         case GST_PAD_SOMETIMES:
13279                                 has_dynamic_pads = TRUE;
13280                         break;
13281
13282                         default:
13283                                 break;
13284                 }
13285         }
13286
13287         /* check if player can do start continually */
13288         MMPLAYER_CHECK_CMD_IF_EXIT(player);
13289
13290         if( has_dynamic_pads )
13291         {
13292                 player->have_dynamic_pad = TRUE;
13293                 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
13294                         G_CALLBACK(__mmplayer_add_new_pad), player);
13295
13296                 /* for streaming, more then one typefind will used for each elementary stream
13297                  * so this doesn't mean the whole pipeline completion
13298                  */
13299                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
13300                 {
13301                         MMPLAYER_SIGNAL_CONNECT( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
13302                                 G_CALLBACK(__mmplayer_pipeline_complete), player);
13303                 }
13304         }
13305
13306         if (has_many_types)
13307         {
13308                 GstPad *pad = NULL;
13309
13310                 player->has_many_types = has_many_types;
13311
13312                 pad = gst_element_get_static_pad(sinkelement, "src");
13313                 MMPLAYER_SIGNAL_CONNECT (player, pad, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
13314                 gst_object_unref (GST_OBJECT(pad));
13315         }
13316
13317
13318         /* check if player can do start continually */
13319         MMPLAYER_CHECK_CMD_IF_EXIT(player);
13320
13321         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
13322         {
13323                 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
13324                 goto ERROR;
13325         }
13326
13327         if ( queue )
13328         {
13329                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
13330                 {
13331                         debug_error("failed to set state PAUSED to queue\n");
13332                         goto ERROR;
13333                 }
13334
13335                 queue = NULL;
13336
13337                 gst_object_unref (GST_OBJECT(qsrcpad));
13338                 qsrcpad = NULL;
13339         }
13340
13341         if ( parser )
13342         {
13343                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
13344                 {
13345                         debug_error("failed to set state PAUSED to queue\n");
13346                         goto ERROR;
13347                 }
13348
13349                 parser = NULL;
13350
13351                 gst_object_unref (GST_OBJECT(pssrcpad));
13352                 pssrcpad = NULL;
13353         }
13354
13355         MMPLAYER_FLEAVE();
13356
13357         return TRUE;
13358
13359 ERROR:
13360
13361         if ( queue )
13362         {
13363                 gst_object_unref(GST_OBJECT(qsrcpad));
13364
13365                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
13366                  * You need to explicitly set elements to the NULL state before
13367                  * dropping the final reference, to allow them to clean up.
13368                  */
13369                 gst_element_set_state(queue, GST_STATE_NULL);
13370                 /* And, it still has a parent "player".
13371                  * You need to let the parent manage the object instead of unreffing the object directly.
13372                  */
13373
13374                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
13375                 //gst_object_unref( queue );
13376         }
13377
13378         if ( srccaps )
13379                 gst_caps_unref(GST_CAPS(srccaps));
13380
13381     return FALSE;
13382 }
13383
13384 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
13385 {
13386         const gchar *klass;
13387         //const gchar *name;
13388
13389         /* we only care about element factories */
13390         if (!GST_IS_ELEMENT_FACTORY(feature))
13391                 return FALSE;
13392
13393         /* only parsers, demuxers and decoders */
13394                 klass = gst_element_factory_get_metadata (GST_ELEMENT_FACTORY(feature), GST_ELEMENT_METADATA_KLASS);
13395             //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
13396
13397         if( g_strrstr(klass, "Demux") == NULL &&
13398                 g_strrstr(klass, "Codec/Decoder") == NULL &&
13399                 g_strrstr(klass, "Depayloader") == NULL &&
13400                 g_strrstr(klass, "Parse") == NULL)
13401         {
13402                 return FALSE;
13403         }
13404     return TRUE;
13405 }
13406
13407
13408 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
13409 {
13410         mm_player_t* player = (mm_player_t*) data;
13411         GstCaps *caps = NULL;
13412         GstStructure *str = NULL;
13413         const char *name;
13414
13415         MMPLAYER_FENTER();
13416
13417         return_if_fail ( pad )
13418         return_if_fail ( unused )
13419         return_if_fail ( data )
13420
13421         caps = gst_pad_query_caps(pad, NULL);
13422         if ( !caps )
13423                 return;
13424
13425         str = gst_caps_get_structure(caps, 0);
13426         if ( !str )
13427                 return;
13428
13429         name = gst_structure_get_name(str);
13430         if ( !name )
13431                 return;
13432         debug_log("name=%s\n", name);
13433
13434         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
13435         {
13436                 debug_error("failed to autoplug for type (%s)\n", name);
13437                 gst_caps_unref(caps);
13438                 return;
13439         }
13440
13441         gst_caps_unref(caps);
13442
13443         __mmplayer_pipeline_complete( NULL, (gpointer)player );
13444
13445         MMPLAYER_FLEAVE();
13446
13447         return;
13448 }
13449
13450 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
13451 {
13452         GstStructure *str;
13453         gint version = 0;
13454         const char *stream_type;
13455         gchar *version_field = NULL;
13456
13457         MMPLAYER_FENTER();
13458
13459         return_if_fail ( player );
13460         return_if_fail ( caps );
13461
13462         str = gst_caps_get_structure(caps, 0);
13463         if ( !str )
13464                 return;
13465
13466         stream_type = gst_structure_get_name(str);
13467         if ( !stream_type )
13468                 return;
13469
13470
13471         /* set unlinked mime type for downloadable codec */
13472         if (g_str_has_prefix(stream_type, "video/"))
13473         {
13474                 if (g_str_has_prefix(stream_type, "video/mpeg"))
13475                 {
13476                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
13477                         version_field = MM_PLAYER_MPEG_VNAME;
13478                 }
13479                 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
13480                 {
13481                         gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
13482                         version_field = MM_PLAYER_WMV_VNAME;
13483
13484                 }
13485                 else if (g_str_has_prefix(stream_type, "video/x-divx"))
13486                 {
13487                         gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
13488                         version_field = MM_PLAYER_DIVX_VNAME;
13489                 }
13490
13491                 if (version)
13492                 {
13493                         player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
13494                 }
13495                 else
13496                 {
13497                         player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
13498                 }
13499         }
13500         else if (g_str_has_prefix(stream_type, "audio/"))
13501         {
13502                 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
13503                 {
13504                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
13505                         version_field = MM_PLAYER_MPEG_VNAME;
13506                 }
13507                 else if (g_str_has_prefix(stream_type, "audio/x-wma"))
13508                 {
13509                         gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
13510                         version_field = MM_PLAYER_WMA_VNAME;
13511                 }
13512
13513                 if (version)
13514                 {
13515                         player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
13516                 }
13517                 else
13518                 {
13519                         player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
13520                 }
13521         }
13522
13523         MMPLAYER_FLEAVE();
13524 }
13525
13526 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
13527 {
13528         mm_player_t* player = (mm_player_t*) data;
13529         GstCaps *caps = NULL;
13530         GstStructure *str = NULL;
13531         const char *name;
13532
13533         MMPLAYER_FENTER();
13534         return_if_fail ( player );
13535         return_if_fail ( pad );
13536
13537         GST_OBJECT_LOCK (pad);
13538         if ((caps = gst_pad_get_current_caps(pad)))
13539                 gst_caps_ref(caps);
13540         GST_OBJECT_UNLOCK (pad);
13541
13542         if ( NULL == caps )
13543         {
13544                 caps = gst_pad_query_caps(pad, NULL);
13545                 if ( !caps ) return;
13546         }
13547
13548         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
13549
13550         str = gst_caps_get_structure(caps, 0);
13551         if ( !str )
13552                 return;
13553
13554         name = gst_structure_get_name(str);
13555         if ( !name )
13556                 return;
13557
13558         player->num_dynamic_pad++;
13559         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
13560
13561         /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
13562           *     If want to play it, remove this code.
13563           */
13564         if (g_strrstr(name, "application"))
13565         {
13566                 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
13567                 {
13568                         /* If id3/ape tag comes, keep going */
13569                         debug_log("application mime exception : id3/ape tag");
13570                 }
13571                 else
13572                 {
13573                         /* Otherwise, we assume that this stream is subtile. */
13574                         debug_log(" application mime type pad is closed.");
13575                         return;
13576                 }
13577         }
13578         else if (g_strrstr(name, "audio"))
13579         {
13580                 gint samplerate = 0, channels = 0;
13581
13582                 if (player->audiodec_linked)
13583                 {
13584                         gst_caps_unref(caps);
13585                         debug_log("multi tracks. skip to plug");
13586                         return;
13587                 }
13588
13589                 /* set stream information */
13590                 /* if possible, set it here because the caps is not distrubed by resampler. */
13591                 gst_structure_get_int (str, "rate", &samplerate);
13592                 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
13593
13594                 gst_structure_get_int (str, "channels", &channels);
13595                 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
13596
13597                 debug_log("audio samplerate : %d        channels : %d", samplerate, channels);
13598         }
13599         else if (g_strrstr(name, "video"))
13600         {
13601                 gint stype;
13602                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
13603
13604                 /* don't make video because of not required */
13605                 if (stype == MM_DISPLAY_SURFACE_NULL)
13606                 {
13607                         debug_log("no video because it's not required");
13608                         return;
13609                 }
13610
13611                 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
13612         }
13613
13614         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
13615         {
13616                 debug_error("failed to autoplug for type (%s)", name);
13617
13618                 __mmplayer_set_unlinked_mime_type(player, caps);
13619         }
13620
13621         gst_caps_unref(caps);
13622
13623         MMPLAYER_FLEAVE();
13624         return;
13625 }
13626
13627 gboolean
13628 __mmplayer_check_subtitle( mm_player_t* player )
13629 {
13630         MMHandleType attrs = 0;
13631         char *subtitle_uri = NULL;
13632
13633         MMPLAYER_FENTER();
13634
13635         return_val_if_fail( player, FALSE );
13636
13637         /* get subtitle attribute */
13638         attrs = MMPLAYER_GET_ATTRS(player);
13639         if ( !attrs )
13640                 return FALSE;
13641
13642         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
13643         if ( !subtitle_uri || !strlen(subtitle_uri))
13644                 return FALSE;
13645
13646         debug_log ("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
13647         player->is_external_subtitle_present = TRUE;
13648
13649         MMPLAYER_FLEAVE();
13650
13651         return TRUE;
13652 }
13653
13654 static gboolean
13655 __mmplayer_can_extract_pcm( mm_player_t* player )
13656 {
13657         MMHandleType attrs = 0;
13658         gboolean is_drm = FALSE;
13659         gboolean sound_extraction = FALSE;
13660
13661         return_val_if_fail ( player, FALSE );
13662
13663         attrs = MMPLAYER_GET_ATTRS(player);
13664         if ( !attrs )
13665         {
13666                 debug_error("fail to get attributes.");
13667                 return FALSE;
13668         }
13669
13670         /* check file is drm or not */
13671         if (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm"))
13672                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
13673
13674         /* get sound_extraction property */
13675         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
13676
13677         if ( ! sound_extraction || is_drm )
13678         {
13679                 debug_log("checking pcm extraction mode : %d, drm : %d", sound_extraction, is_drm);
13680                 return FALSE;
13681         }
13682
13683         return TRUE;
13684 }
13685
13686 static gboolean
13687 __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message )
13688 {
13689         debug_log("\n");
13690         MMMessageParamType msg_param;
13691         gchar *msg_src_element = NULL;
13692         GstStructure *s = NULL;
13693         guint error_id = 0;
13694         gchar *error_string = NULL;
13695
13696         MMPLAYER_FENTER();
13697
13698         return_val_if_fail ( player, FALSE );
13699         return_val_if_fail ( message, FALSE );
13700
13701         s = malloc( sizeof(GstStructure) );
13702         memcpy ( s, gst_message_get_structure ( message ), sizeof(GstStructure));
13703
13704         if ( !gst_structure_get_uint (s, "error_id", &error_id) )
13705                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
13706
13707         switch ( error_id )
13708         {
13709                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
13710                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
13711                         break;
13712                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
13713                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
13714                         break;
13715                 case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
13716                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
13717                         break;
13718                 case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
13719                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
13720                         break;
13721                 case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
13722                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
13723                         break;
13724                 case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
13725                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
13726                         break;
13727                 case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
13728                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
13729                         break;
13730                 case MMPLAYER_STREAMING_ERROR_INVALID_URL:
13731                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
13732                         break;
13733                 case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
13734                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
13735                         break;
13736                 case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
13737                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
13738                         break;
13739                 case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
13740                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
13741                         break;
13742                 case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
13743                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
13744                         break;
13745                 case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
13746                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
13747                         break;
13748                 case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
13749                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
13750                         break;
13751                 case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
13752                         msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
13753                         break;
13754                 case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
13755                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
13756                         break;
13757                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
13758                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
13759                         break;
13760                 case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
13761                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
13762                         break;
13763                 case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
13764                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
13765                         break;
13766                 case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
13767                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
13768                         break;
13769                 case MMPLAYER_STREAMING_ERROR_GONE:
13770                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
13771                         break;
13772                 case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
13773                         msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
13774                         break;
13775                 case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
13776                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
13777                         break;
13778                 case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
13779                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
13780                         break;
13781                 case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
13782                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
13783                         break;
13784                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
13785                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
13786                         break;
13787                 case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
13788                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
13789                         break;
13790                 case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
13791                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
13792                         break;
13793                 case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
13794                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
13795                         break;
13796                 case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
13797                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
13798                         break;
13799                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
13800                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
13801                         break;
13802                 case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
13803                         msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
13804                         break;
13805                 case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
13806                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
13807                         break;
13808                 case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
13809                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
13810                         break;
13811                 case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
13812                         msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
13813                         break;
13814                 case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
13815                         msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
13816                         break;
13817                 case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
13818                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
13819                         break;
13820                 case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
13821                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
13822                         break;
13823                 case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
13824                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
13825                         break;
13826                 case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
13827                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
13828                         break;
13829                 case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
13830                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
13831                         break;
13832                 case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
13833                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
13834                         break;
13835                 case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
13836                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
13837                         break;
13838                 case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
13839                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
13840                         break;
13841                 case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
13842                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
13843                         break;
13844                 default:
13845                         {
13846                                 MMPLAYER_FREEIF(s);
13847                                 return MM_ERROR_PLAYER_STREAMING_FAIL;
13848                         }
13849         }
13850
13851         error_string = g_strdup(gst_structure_get_string (s, "error_string"));
13852         if ( error_string )
13853                 msg_param.data = (void *) error_string;
13854
13855         if ( message->src )
13856         {
13857                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
13858
13859                 debug_error("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
13860                         msg_src_element, msg_param.code, (char*)msg_param.data );
13861         }
13862
13863         /* post error to application */
13864         if ( ! player->msg_posted )
13865         {
13866                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
13867
13868                 /* don't post more if one was sent already */
13869                 player->msg_posted = TRUE;
13870         }
13871         else
13872         {
13873                 debug_log("skip error post because it's sent already.\n");
13874         }
13875
13876         MMPLAYER_FREEIF(s);
13877         MMPLAYER_FLEAVE();
13878         g_free(error_string);
13879
13880         return TRUE;
13881
13882 }
13883
13884 static void
13885 __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms )
13886 {
13887         return_if_fail( player );
13888
13889
13890         /* post now if delay is zero */
13891         if ( delay_in_ms == 0 || player->set_mode.pcm_extraction)
13892         {
13893                 debug_log("eos delay is zero. posting EOS now\n");
13894                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
13895
13896                 if ( player->set_mode.pcm_extraction )
13897                         __mmplayer_cancel_eos_timer(player);
13898
13899                 return;
13900         }
13901
13902         /* cancel if existing */
13903         __mmplayer_cancel_eos_timer( player );
13904
13905         /* init new timeout */
13906         /* NOTE : consider give high priority to this timer */
13907         debug_log("posting EOS message after [%d] msec\n", delay_in_ms);
13908
13909         player->eos_timer = g_timeout_add( delay_in_ms,
13910                 __mmplayer_eos_timer_cb, player );
13911
13912         player->context.global_default = g_main_context_default ();
13913         debug_log("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
13914
13915         /* check timer is valid. if not, send EOS now */
13916         if ( player->eos_timer == 0 )
13917         {
13918                 debug_warning("creating timer for delayed EOS has failed. sending EOS now\n");
13919                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
13920         }
13921 }
13922
13923 static void
13924 __mmplayer_cancel_eos_timer( mm_player_t* player )
13925 {
13926         return_if_fail( player );
13927
13928         if ( player->eos_timer )
13929         {
13930                 debug_log("cancel eos timer");
13931                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
13932                 player->eos_timer = 0;
13933         }
13934
13935         return;
13936 }
13937
13938 static gboolean
13939 __mmplayer_eos_timer_cb(gpointer u_data)
13940 {
13941         mm_player_t* player = NULL;
13942         player = (mm_player_t*) u_data;
13943
13944         return_val_if_fail( player, FALSE );
13945
13946         if ( player->play_count > 1 )
13947         {
13948                 gint ret_value = 0;
13949                 ret_value = __gst_set_position( player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
13950                 if (ret_value == MM_ERROR_NONE)
13951                 {
13952                         MMHandleType attrs = 0;
13953                         attrs = MMPLAYER_GET_ATTRS(player);
13954
13955                         /* we successeded to rewind. update play count and then wait for next EOS */
13956                         player->play_count--;
13957
13958                         mm_attrs_set_int_by_name(attrs, "profile_play_count", player->play_count);
13959                         mmf_attrs_commit ( attrs );
13960                 }
13961                 else
13962                 {
13963                         debug_error("seeking to 0 failed in repeat play");
13964                 }
13965         }
13966         else
13967         {
13968                 /* posting eos */
13969                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
13970         }
13971
13972         /* we are returning FALSE as we need only one posting */
13973         return FALSE;
13974 }
13975
13976 static gboolean
13977 __mmplayer_link_decoder( mm_player_t* player, GstPad *srcpad)
13978 {
13979         const gchar* name = NULL;
13980         GstStructure* str = NULL;
13981         GstCaps* srccaps = NULL;
13982
13983         MMPLAYER_FENTER();
13984
13985         return_val_if_fail( player, FALSE );
13986         return_val_if_fail ( srcpad, FALSE );
13987
13988         /* to check any of the decoder (video/audio) need to be linked  to parser*/
13989         srccaps = gst_pad_query_caps( srcpad, NULL);
13990         if ( !srccaps )
13991                 goto ERROR;
13992
13993         str = gst_caps_get_structure( srccaps, 0 );
13994         if ( ! str )
13995                 goto ERROR;
13996
13997         name = gst_structure_get_name(str);
13998         if ( ! name )
13999                 goto ERROR;
14000
14001         if (strstr(name, "video"))
14002         {
14003                 if(player->videodec_linked)
14004                 {
14005                     debug_msg("Video decoder already linked\n");
14006                         return FALSE;
14007                 }
14008         }
14009         if (strstr(name, "audio"))
14010         {
14011                 if(player->audiodec_linked)
14012                 {
14013                     debug_msg("Audio decoder already linked\n");
14014                         return FALSE;
14015                 }
14016         }
14017
14018         gst_caps_unref( srccaps );
14019
14020         MMPLAYER_FLEAVE();
14021
14022         return TRUE;
14023
14024 ERROR:
14025         if ( srccaps )
14026                 gst_caps_unref( srccaps );
14027
14028         return FALSE;
14029 }
14030
14031 static gboolean
14032 __mmplayer_link_sink( mm_player_t* player , GstPad *srcpad)
14033 {
14034         const gchar* name = NULL;
14035         GstStructure* str = NULL;
14036         GstCaps* srccaps = NULL;
14037
14038         MMPLAYER_FENTER();
14039
14040         return_val_if_fail ( player, FALSE );
14041         return_val_if_fail ( srcpad, FALSE );
14042
14043         /* to check any of the decoder (video/audio) need to be linked  to parser*/
14044         srccaps = gst_pad_query_caps( srcpad, NULL );
14045         if ( !srccaps )
14046                 goto ERROR;
14047
14048         str = gst_caps_get_structure( srccaps, 0 );
14049         if ( ! str )
14050                 goto ERROR;
14051
14052         name = gst_structure_get_name(str);
14053         if ( ! name )
14054                 goto ERROR;
14055
14056         if (strstr(name, "video"))
14057         {
14058                 if(player->videosink_linked)
14059                 {
14060                         debug_msg("Video Sink already linked\n");
14061                         return FALSE;
14062                 }
14063         }
14064         if (strstr(name, "audio"))
14065         {
14066                 if(player->audiosink_linked)
14067                 {
14068                         debug_msg("Audio Sink already linked\n");
14069                         return FALSE;
14070                 }
14071         }
14072         if (strstr(name, "text"))
14073         {
14074                 if(player->textsink_linked)
14075                 {
14076                         debug_msg("Text Sink already linked\n");
14077                         return FALSE;
14078                 }
14079         }
14080
14081         gst_caps_unref( srccaps );
14082
14083         MMPLAYER_FLEAVE();
14084
14085         return TRUE;
14086         //return (!player->videosink_linked || !player->audiosink_linked);
14087
14088 ERROR:
14089         if ( srccaps )
14090                 gst_caps_unref( srccaps );
14091
14092         return FALSE;
14093 }
14094
14095
14096 /* sending event to one of sinkelements */
14097 static gboolean
14098 __gst_send_event_to_sink( mm_player_t* player, GstEvent* event )
14099 {
14100         GstEvent * event2 = NULL;
14101         GList *sinks = NULL;
14102         gboolean res = FALSE;
14103         MMPLAYER_FENTER();
14104
14105         return_val_if_fail( player, FALSE );
14106         return_val_if_fail ( event, FALSE );
14107
14108         if ( player->play_subtitle && !player->use_textoverlay)
14109                 event2 = gst_event_copy((const GstEvent *)event);
14110
14111         sinks = player->sink_elements;
14112         while (sinks)
14113         {
14114                 GstElement *sink = GST_ELEMENT_CAST (sinks->data);
14115
14116                 if (GST_IS_ELEMENT(sink))
14117                 {
14118                         /* keep ref to the event */
14119                         gst_event_ref (event);
14120
14121                         if ( (res = gst_element_send_event (sink, event)) )
14122                         {
14123                                 debug_log("sending event[%s] to sink element [%s] success!\n",
14124                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
14125
14126                                 /* rtsp case, asyn_done is not called after seek during pause state */
14127                                 if (MMPLAYER_IS_RTSP_STREAMING(player))
14128                                 {
14129                                         if (strstr(GST_EVENT_TYPE_NAME(event), "seek"))
14130                                         {
14131                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
14132                                                 {
14133                                                         debug_log("RTSP seek completed, after pause state..\n");
14134                                                         player->doing_seek = FALSE;
14135                                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
14136                                                 }
14137
14138                                         }
14139                                 }
14140
14141                                 if( MMPLAYER_IS_ES_BUFF_SRC(player))
14142                                 {
14143                                         sinks = g_list_next (sinks);
14144                                         continue;
14145                                 }
14146                                 else
14147                                         break;
14148                         }
14149
14150                         debug_log("sending event[%s] to sink element [%s] failed. try with next one.\n",
14151                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
14152                 }
14153
14154                 sinks = g_list_next (sinks);
14155         }
14156
14157 #if 0
14158         if (internal_sub)
14159           request pad name = sink0;
14160         else
14161           request pad name = sink1; // external
14162 #endif
14163
14164         /* Note : Textbin is not linked to the video or audio bin.
14165          * It needs to send the event to the text sink seperatelly.
14166          */
14167          if ( player->play_subtitle && !player->use_textoverlay)
14168          {
14169                 GstElement *text_sink = GST_ELEMENT_CAST (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
14170
14171                 if (GST_IS_ELEMENT(text_sink))
14172                 {
14173                         /* keep ref to the event */
14174                         gst_event_ref (event2);
14175
14176                         if ((res = gst_element_send_event (text_sink, event2)))
14177                         {
14178                                 debug_log("sending event[%s] to subtitle sink element [%s] success!\n",
14179                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
14180                         }
14181                         else
14182                         {
14183                                 debug_error("sending event[%s] to subtitle sink element [%s] failed!\n",
14184                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
14185                         }
14186
14187                         gst_event_unref (event2);
14188                 }
14189          }
14190
14191         gst_event_unref (event);
14192
14193         MMPLAYER_FLEAVE();
14194
14195         return res;
14196 }
14197
14198 static void
14199 __mmplayer_add_sink( mm_player_t* player, GstElement* sink )
14200 {
14201         MMPLAYER_FENTER();
14202
14203         return_if_fail ( player );
14204         return_if_fail ( sink );
14205
14206         player->sink_elements =
14207                 g_list_append(player->sink_elements, sink);
14208
14209         MMPLAYER_FLEAVE();
14210 }
14211
14212 static void
14213 __mmplayer_del_sink( mm_player_t* player, GstElement* sink )
14214 {
14215         MMPLAYER_FENTER();
14216
14217         return_if_fail ( player );
14218         return_if_fail ( sink );
14219
14220         player->sink_elements =
14221                         g_list_remove(player->sink_elements, sink);
14222
14223         MMPLAYER_FLEAVE();
14224 }
14225
14226 static gboolean
14227 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
14228                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
14229                         gint64 cur, GstSeekType stop_type, gint64 stop )
14230 {
14231         GstEvent* event = NULL;
14232         gboolean result = FALSE;
14233
14234         MMPLAYER_FENTER();
14235
14236         return_val_if_fail( player, FALSE );
14237
14238         __mmplayer_drop_subtitle(player, FALSE);
14239
14240         event = gst_event_new_seek (rate, format, flags, cur_type,
14241                 cur, stop_type, stop);
14242
14243         result = __gst_send_event_to_sink( player, event );
14244
14245         MMPLAYER_FLEAVE();
14246
14247         return result;
14248 }
14249
14250 /* NOTE : be careful with calling this api. please refer to below glib comment
14251  * glib comment : Note that there is a bug in GObject that makes this function much
14252  * less useful than it might seem otherwise. Once gobject is disposed, the callback
14253  * will no longer be called, but, the signal handler is not currently disconnected.
14254  * If the instance is itself being freed at the same time than this doesn't matter,
14255  * since the signal will automatically be removed, but if instance persists,
14256  * then the signal handler will leak. You should not remove the signal yourself
14257  * because in a future versions of GObject, the handler will automatically be
14258  * disconnected.
14259  *
14260  * It's possible to work around this problem in a way that will continue to work
14261  * with future versions of GObject by checking that the signal handler is still
14262  * connected before disconnected it:
14263  *
14264  *  if (g_signal_handler_is_connected (instance, id))
14265  *    g_signal_handler_disconnect (instance, id);
14266  */
14267 static void
14268 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
14269 {
14270         GList* sig_list = NULL;
14271         MMPlayerSignalItem* item = NULL;
14272
14273         MMPLAYER_FENTER();
14274
14275         return_if_fail( player );
14276
14277         debug_log("release signals type : %d", type);
14278
14279         if ((type < MM_PLAYER_SIGNAL_TYPE_AUTOPLUG) || (type >= MM_PLAYER_SIGNAL_TYPE_ALL))
14280         {
14281                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
14282                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
14283                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
14284                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
14285                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
14286                 return;
14287         }
14288
14289         sig_list = player->signals[type];
14290
14291         for ( ; sig_list; sig_list = sig_list->next )
14292         {
14293                 item = sig_list->data;
14294
14295                 if ( item && item->obj && GST_IS_ELEMENT(item->obj) )
14296                 {
14297                         if ( g_signal_handler_is_connected ( item->obj, item->sig ) )
14298                         {
14299                                 g_signal_handler_disconnect ( item->obj, item->sig );
14300                         }
14301                 }
14302
14303                 MMPLAYER_FREEIF( item );
14304         }
14305
14306         g_list_free ( player->signals[type] );
14307         player->signals[type] = NULL;
14308
14309         MMPLAYER_FLEAVE();
14310
14311         return;
14312 }
14313
14314 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
14315 {
14316         mm_player_t* player = 0;
14317         int prev_display_surface_type = 0;
14318         void *prev_display_overlay = NULL;
14319         const gchar *klass = NULL;
14320         gchar *cur_videosink_name = NULL;
14321         int ret = 0;
14322         int i = 0;
14323         int num_of_dec = 2; /* DEC1, DEC2 */
14324
14325         MMPLAYER_FENTER();
14326
14327         return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
14328         return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
14329
14330         player = MM_PLAYER_CAST(handle);
14331
14332         if (surface_type < MM_DISPLAY_SURFACE_X && surface_type >= MM_DISPLAY_SURFACE_NUM)
14333         {
14334                 debug_error("Not support this surface type(%d) for changing vidoesink", surface_type);
14335                 MMPLAYER_FLEAVE();
14336                 return MM_ERROR_INVALID_ARGUMENT;
14337         }
14338
14339         /* load previous attributes */
14340         if (player->attrs)
14341         {
14342                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &prev_display_surface_type);
14343                 mm_attrs_get_data_by_name (player->attrs, "display_overlay", &prev_display_overlay);
14344                 debug_log("[0: X surface, 1: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
14345                 if (prev_display_surface_type == surface_type)
14346                 {
14347                         debug_log("incoming display surface type is same as previous one, do nothing..");
14348                         MMPLAYER_FLEAVE();
14349                         return MM_ERROR_NONE;
14350                 }
14351         }
14352         else
14353         {
14354                 debug_error("failed to load attributes");
14355                 MMPLAYER_FLEAVE();
14356                 return MM_ERROR_PLAYER_INTERNAL;
14357         }
14358
14359         /* check videosink element is created */
14360         if (!player->pipeline || !player->pipeline->videobin ||
14361                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
14362         {
14363                 debug_log("videosink element is not yet ready");
14364
14365                 /* videobin is not created yet, so we just set attributes related to display surface */
14366                 debug_log("store display attribute for given surface type(%d)", surface_type);
14367                 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
14368                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
14369                 if ( mmf_attrs_commit ( player->attrs ) )
14370                 {
14371                         debug_error("failed to commit attribute");
14372                         MMPLAYER_FLEAVE();
14373                         return MM_ERROR_PLAYER_INTERNAL;
14374                 }
14375                 MMPLAYER_FLEAVE();
14376                 return MM_ERROR_NONE;
14377         }
14378         else
14379         {
14380                 /* get player command status */
14381                 if ( !(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE) )
14382                 {
14383                         debug_error("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command",player->cmd);
14384                         MMPLAYER_FLEAVE();
14385                         return MM_ERROR_PLAYER_INVALID_STATE;
14386                 }
14387
14388                 /* get a current videosink name */
14389                 cur_videosink_name = GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
14390
14391                 /* surface change */
14392                 for ( i = 0 ; i < num_of_dec ; i++)
14393                 {
14394                         if ( player->pipeline->mainbin &&
14395                                 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst )
14396                         {
14397                                 GstElementFactory *decfactory;
14398                                 decfactory = gst_element_get_factory (player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst);
14399
14400                                 klass = gst_element_factory_get_metadata (decfactory, GST_ELEMENT_METADATA_KLASS);
14401                                 if ((g_strrstr(klass, "Codec/Decoder/Video")))
14402                                 {
14403                                         if ( !strncmp(cur_videosink_name, "x", 1) && (surface_type == MM_DISPLAY_SURFACE_EVAS) )
14404                                         {
14405                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_evas, surface_type, display_overlay);
14406                                                 if (ret)
14407                                                 {
14408                                                         goto ERROR_CASE;
14409                                                 }
14410                                                 else
14411                                                 {
14412                                                         debug_warning("success to changing display surface(%d)",surface_type);
14413                                                         MMPLAYER_FLEAVE();
14414                                                         return MM_ERROR_NONE;
14415                                                 }
14416                                         }
14417                                         else if (!strncmp(cur_videosink_name, "evas", 4) && (surface_type == MM_DISPLAY_SURFACE_X) )
14418                                         {
14419                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_x, surface_type, display_overlay);
14420                                                 if (ret)
14421                                                 {
14422                                                         goto ERROR_CASE;
14423                                                 }
14424                                                 else
14425                                                 {
14426                                                         debug_warning("success to changing display surface(%d)",surface_type);
14427                                                         MMPLAYER_FLEAVE();
14428                                                         return MM_ERROR_NONE;
14429                                                 }
14430                                         }
14431                                         else
14432                                         {
14433                                                 debug_error("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface",surface_type, cur_videosink_name);
14434                                                 ret = MM_ERROR_PLAYER_INTERNAL;
14435                                                 goto ERROR_CASE;
14436                                         }
14437                                 }
14438                         }
14439                 }
14440         }
14441
14442 ERROR_CASE:
14443         /* rollback to previous attributes */
14444         mm_attrs_set_int_by_name (player->attrs, "display_surface_type", prev_display_surface_type);
14445         mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(void*));
14446         if ( mmf_attrs_commit ( player->attrs ) )
14447         {
14448                 debug_error("failed to commit attributes to rollback");
14449                 MMPLAYER_FLEAVE();
14450                 return MM_ERROR_PLAYER_INTERNAL;
14451         }
14452         MMPLAYER_FLEAVE();
14453         return ret;
14454 }
14455
14456 /* NOTE : It does not support some use cases, eg using colorspace converter */
14457 int
14458 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
14459 {
14460         GstPad *src_pad_dec = NULL;
14461         GstPad *sink_pad_videosink = NULL;
14462         GstPad *sink_pad_videobin = NULL;
14463         GstClock *clock = NULL;
14464         MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
14465         int ret = MM_ERROR_NONE;
14466         gboolean is_audiobin_created = TRUE;
14467
14468         MMPLAYER_FENTER();
14469
14470         return_val_if_fail(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
14471         return_val_if_fail(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
14472         return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
14473
14474         debug_log("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
14475         debug_log("surface type(%d), display overlay(%x)", surface_type, display_overlay);
14476
14477         /* get information whether if audiobin is created */
14478         if ( !player->pipeline->audiobin ||
14479                      !player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
14480         {
14481                 debug_warning("audiobin is null, this video content may not have audio data");
14482                 is_audiobin_created = FALSE;
14483         }
14484
14485         /* get current state of player */
14486         previous_state = MMPLAYER_CURRENT_STATE(player);
14487         debug_log("previous state(%d)", previous_state);
14488
14489
14490         /* get src pad of decoder and block it */
14491         src_pad_dec = gst_element_get_static_pad (GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
14492         if (!src_pad_dec)
14493         {
14494                 debug_error("failed to get src pad from decode in mainbin");
14495                 return MM_ERROR_PLAYER_INTERNAL;
14496         }
14497
14498         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
14499         {
14500                 debug_warning("trying to block pad(video)");
14501 //              if (!gst_pad_set_blocked (src_pad_dec, TRUE))
14502                 gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
14503                         NULL, NULL, NULL);
14504
14505                 {
14506                         debug_error("failed to set block pad(video)");
14507                         return MM_ERROR_PLAYER_INTERNAL;
14508                 }
14509                 debug_warning("pad is blocked(video)");
14510         }
14511         else
14512         {
14513                 /* no data flows, so no need to do pad_block */
14514                 if (player->doing_seek) {
14515                         debug_warning("not completed seek(%d), do nothing", player->doing_seek);
14516                 }
14517                 debug_log("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
14518         }
14519
14520         /* remove pad */
14521         if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
14522                 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin))))
14523         {
14524                 debug_error("failed to remove previous ghost_pad for videobin");
14525                 return MM_ERROR_PLAYER_INTERNAL;
14526         }
14527
14528         /* change state of videobin to NULL */
14529         debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
14530         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
14531         if (ret != GST_STATE_CHANGE_SUCCESS)
14532         {
14533                 debug_error("failed to change state of videobin to NULL");
14534                 return MM_ERROR_PLAYER_INTERNAL;
14535         }
14536
14537         /* unlink between decoder and videobin and remove previous videosink from videobin */
14538         GST_ELEMENT_UNLINK(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst),GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
14539         if ( !gst_bin_remove (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst)) )
14540         {
14541                 debug_error("failed to remove former videosink from videobin");
14542                 return MM_ERROR_PLAYER_INTERNAL;
14543         }
14544
14545         __mmplayer_del_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
14546
14547         /* create a new videosink and add it to videobin */
14548         player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, videosink_element);
14549         gst_bin_add (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
14550         __mmplayer_add_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
14551         g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
14552
14553         /* save attributes */
14554         if (player->attrs)
14555         {
14556                 /* set a new display surface type */
14557                 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
14558                 /* set a new diplay overlay */
14559                 switch (surface_type)
14560                 {
14561                         case MM_DISPLAY_SURFACE_X:
14562                                 debug_log("save attributes related to display surface to X : xid = %d", *(int*)display_overlay);
14563                                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
14564                                 break;
14565                         case MM_DISPLAY_SURFACE_EVAS:
14566                                 debug_log("save attributes related to display surface to EVAS : evas image object = %x", display_overlay);
14567                                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(void*));
14568                                 break;
14569                         default:
14570                                 debug_error("invalid type(%d) for changing display surface",surface_type);
14571                                 MMPLAYER_FLEAVE();
14572                                 return MM_ERROR_INVALID_ARGUMENT;
14573                 }
14574                 if ( mmf_attrs_commit ( player->attrs ) )
14575                 {
14576                         debug_error("failed to commit");
14577                         MMPLAYER_FLEAVE();
14578                         return MM_ERROR_PLAYER_INTERNAL;
14579                 }
14580         }
14581         else
14582         {
14583                 debug_error("player->attrs is null, failed to save attributes");
14584                 MMPLAYER_FLEAVE();
14585                 return MM_ERROR_PLAYER_INTERNAL;
14586         }
14587
14588         /* update video param */
14589         if ( MM_ERROR_NONE != _mmplayer_update_video_param( player ) )
14590         {
14591                 debug_error("failed to update video param");
14592                 return MM_ERROR_PLAYER_INTERNAL;
14593         }
14594
14595         /* change state of videobin to READY */
14596         debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
14597         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
14598         if (ret != GST_STATE_CHANGE_SUCCESS)
14599         {
14600                 debug_error("failed to change state of videobin to READY");
14601                 return MM_ERROR_PLAYER_INTERNAL;
14602         }
14603
14604         /* change ghostpad */
14605         sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
14606         if ( !sink_pad_videosink )
14607         {
14608                 debug_error("failed to get sink pad from videosink element");
14609                 return MM_ERROR_PLAYER_INTERNAL;
14610         }
14611         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
14612         if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE))
14613         {
14614                 debug_error("failed to set active to ghost_pad");
14615                 return MM_ERROR_PLAYER_INTERNAL;
14616         }
14617         if ( FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
14618         {
14619                 debug_error("failed to change ghostpad for videobin");
14620                 return MM_ERROR_PLAYER_INTERNAL;
14621         }
14622         gst_object_unref(sink_pad_videosink);
14623
14624         /* link decoder with videobin */
14625         sink_pad_videobin = gst_element_get_static_pad( GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
14626         if ( !sink_pad_videobin )
14627         {
14628                 debug_error("failed to get sink pad from videobin");
14629                 return MM_ERROR_PLAYER_INTERNAL;
14630         }
14631         if ( GST_PAD_LINK_OK != GST_PAD_LINK(src_pad_dec, sink_pad_videobin) )
14632         {
14633                 debug_error("failed to link");
14634                 return MM_ERROR_PLAYER_INTERNAL;
14635         }
14636         gst_object_unref(sink_pad_videobin);
14637
14638         /* clock setting for a new videosink plugin */
14639         /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
14640                         so we set it from audiosink plugin or pipeline(system clock) */
14641         if (!is_audiobin_created)
14642         {
14643                 debug_warning("audiobin is not created, get clock from pipeline..");
14644                 clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
14645         }
14646         else
14647         {
14648                 clock = GST_ELEMENT_CLOCK (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
14649         }
14650         if (clock)
14651         {
14652                 GstClockTime now;
14653                 GstClockTime base_time;
14654                 debug_log("set the clock to videosink");
14655                 gst_element_set_clock (GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
14656                 clock = GST_ELEMENT_CLOCK (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
14657                 if (clock)
14658                 {
14659                         debug_log("got clock of videosink");
14660                         now = gst_clock_get_time ( clock );
14661                         base_time = GST_ELEMENT_CAST (player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
14662                         debug_log ("at time %" GST_TIME_FORMAT ", base %"
14663                                         GST_TIME_FORMAT, GST_TIME_ARGS (now), GST_TIME_ARGS (base_time));
14664                 }
14665                 else
14666                 {
14667                         debug_error("failed to get clock of videosink after setting clock");
14668                         return MM_ERROR_PLAYER_INTERNAL;
14669                 }
14670         }
14671         else
14672         {
14673                 debug_warning("failed to get clock, maybe it is the time before first playing");
14674         }
14675
14676         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
14677         {
14678                 /* change state of videobin to PAUSED */
14679                 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
14680                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
14681                 if (ret != GST_STATE_CHANGE_FAILURE)
14682                 {
14683                         debug_warning("change state of videobin to PLAYING, ret(%d)", ret);
14684                 }
14685                 else
14686                 {
14687                         debug_error("failed to change state of videobin to PLAYING");
14688                         return MM_ERROR_PLAYER_INTERNAL;
14689                 }
14690
14691                 /* release blocked and unref src pad of video decoder */
14692                 #if 0
14693                 if (!gst_pad_set_blocked (src_pad_dec, FALSE))
14694                 {
14695                         debug_error("failed to set pad blocked FALSE(video)");
14696                         return MM_ERROR_PLAYER_INTERNAL;
14697                 }
14698                 #endif
14699                 debug_warning("pad is unblocked(video)");
14700         }
14701         else
14702         {
14703                 if (player->doing_seek) {
14704                         debug_warning("not completed seek(%d)", player->doing_seek);
14705                 }
14706                 /* change state of videobin to PAUSED */
14707                 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
14708                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
14709                 if (ret != GST_STATE_CHANGE_FAILURE)
14710                 {
14711                         debug_warning("change state of videobin to PAUSED, ret(%d)", ret);
14712                 }
14713                 else
14714                 {
14715                         debug_error("failed to change state of videobin to PLAYING");
14716                         return MM_ERROR_PLAYER_INTERNAL;
14717                 }
14718
14719                 /* already skipped pad block */
14720                 debug_log("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
14721         }
14722
14723         /* do get/set position for new videosink plugin */
14724         {
14725                 unsigned long position = 0;
14726                 gint64 pos_msec = 0;
14727
14728                 debug_log("do get/set position for new videosink plugin");
14729                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
14730                 {
14731                         debug_error("failed to get position");
14732                         return MM_ERROR_PLAYER_INTERNAL;
14733                 }
14734 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
14735                 /* accurate seek */
14736                 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE ))
14737                 {
14738                         debug_error("failed to set position");
14739                         return MM_ERROR_PLAYER_INTERNAL;
14740                 }
14741 #else
14742                 /* key unit seek */
14743                 pos_msec = position * G_GINT64_CONSTANT(1000000);
14744                 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
14745                                 GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT ),
14746                                                         GST_SEEK_TYPE_SET, pos_msec,
14747                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
14748                 if ( !ret  )
14749                 {
14750                         debug_error("failed to set position");
14751                         return MM_ERROR_PLAYER_INTERNAL;
14752                 }
14753 #endif
14754         }
14755
14756         if (src_pad_dec)
14757         {
14758                 gst_object_unref (src_pad_dec);
14759         }
14760         debug_log("success to change sink");
14761
14762         MMPLAYER_FLEAVE();
14763
14764         return MM_ERROR_NONE;
14765 }
14766
14767
14768 /* Note : if silent is true, then subtitle would not be displayed. :*/
14769 int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent)
14770 {
14771         mm_player_t* player = (mm_player_t*) hplayer;
14772
14773         MMPLAYER_FENTER();
14774
14775         /* check player handle */
14776         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14777
14778         player->set_mode.subtitle_off = silent;
14779
14780         debug_log("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
14781
14782         MMPLAYER_FLEAVE();
14783
14784         return MM_ERROR_NONE;
14785 }
14786
14787 int _mmplayer_remove_audio_parser_decoder(mm_player_t* player,GstPad *inpad)
14788 {
14789         int result = MM_ERROR_NONE;
14790         GstPad *peer = NULL,*pad = NULL;
14791         GstElement *Element = NULL;
14792         MMPlayerGstElement* mainbin = NULL;
14793         mainbin = player->pipeline->mainbin;
14794
14795         #if 0
14796         if(!gst_pad_set_blocked(inpad,TRUE))
14797         {
14798                 result = MM_ERROR_PLAYER_INTERNAL;
14799                 goto EXIT;
14800         }
14801         #endif
14802         gst_pad_add_probe(inpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
14803                         NULL, NULL, NULL);
14804
14805         /*Getting pad connected to demuxer audio pad */
14806         peer = gst_pad_get_peer(inpad);
14807         /* Disconnecting Demuxer and its peer plugin [audio] */
14808         if(peer)
14809         {
14810                 if(!gst_pad_unlink(inpad,peer))
14811                 {
14812                         result = MM_ERROR_PLAYER_INTERNAL;
14813                         goto EXIT;
14814                 }
14815         }
14816         else
14817         {
14818                 result = MM_ERROR_PLAYER_INTERNAL;
14819                 goto EXIT;
14820         }
14821         /*Removing elements between Demuxer and audiobin*/
14822         while(peer != NULL)
14823         {
14824                 gchar *Element_name = NULL;
14825                 gchar *factory_name = NULL;
14826                 GList *elements = NULL;
14827                 GstElementFactory *factory = NULL;
14828                 /*Getting peer element*/
14829                 Element = gst_pad_get_parent_element(peer);
14830                 if(Element == NULL)
14831                 {
14832                         gst_object_unref(peer);
14833                         result = MM_ERROR_PLAYER_INTERNAL;
14834                         break;
14835                 }
14836
14837                 Element_name = gst_element_get_name(Element);
14838                 factory = gst_element_get_factory(Element);
14839                 /*checking the element is audio bin*/
14840                 if(!strcmp(Element_name,"audiobin"))
14841                 {
14842                         gst_object_unref(peer);
14843                         result = MM_ERROR_NONE;
14844             g_free(Element_name);
14845                         break;
14846                 }
14847                 factory_name = GST_OBJECT_NAME(factory);
14848                 pad = gst_element_get_static_pad(Element,"src");
14849                 if(pad == NULL)
14850                 {
14851                         result = MM_ERROR_PLAYER_INTERNAL;
14852             g_free(Element_name);
14853                         break;
14854                 }
14855                 gst_object_unref(peer);
14856                 peer = gst_pad_get_peer(pad);
14857                 if(peer)
14858                 {
14859                         if(!gst_pad_unlink(pad,peer))
14860                         {
14861                                 gst_object_unref(peer);
14862                                 gst_object_unref(pad);
14863                                 result = MM_ERROR_PLAYER_INTERNAL;
14864                 g_free(Element_name);
14865                                 break;
14866                         }
14867                 }
14868                 elements = player->parsers;
14869                 /* Removing the element form the list*/
14870                 for ( ; elements; elements = g_list_next(elements))
14871                 {
14872                         Element_name = elements->data;
14873                         if(g_strrstr(Element_name,factory_name))
14874                         {
14875                                 player->parsers = g_list_remove(player->parsers,elements->data);
14876                         }
14877                 }
14878                 gst_element_set_state(Element,GST_STATE_NULL);
14879                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),Element);
14880                 gst_object_unref(pad);
14881                 if(Element == mainbin[MMPLAYER_M_Q1].gst)
14882                 {
14883                         mainbin[MMPLAYER_M_Q1].gst = NULL;
14884                 }
14885                 else if(Element == mainbin[MMPLAYER_M_Q2].gst)
14886                 {
14887                         mainbin[MMPLAYER_M_Q2].gst = NULL;
14888                 }
14889                 else if(Element == mainbin[MMPLAYER_M_DEC1].gst)
14890                 {
14891                         mainbin[MMPLAYER_M_DEC1].gst = NULL;
14892                 }
14893                 else if(Element == mainbin[MMPLAYER_M_DEC2].gst)
14894                 {
14895                         mainbin[MMPLAYER_M_DEC2].gst = NULL;
14896                 }
14897                 gst_object_unref(Element);
14898         }
14899 EXIT:
14900         return result;
14901 }
14902
14903 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
14904 {
14905         MMPlayerGstElement* mainbin = NULL;
14906         MMPlayerGstElement* textbin = NULL;
14907         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
14908         GstState current_state = GST_STATE_VOID_PENDING;
14909         GstState element_state = GST_STATE_VOID_PENDING;
14910         GstState element_pending_state = GST_STATE_VOID_PENDING;
14911         gint64 time = 0;
14912         GstEvent *event = NULL;
14913         int result = MM_ERROR_NONE;
14914
14915         GstClock *curr_clock = NULL;
14916         GstClockTime base_time, start_time, curr_time;
14917
14918
14919         MMPLAYER_FENTER();
14920
14921         /* check player handle */
14922         return_val_if_fail ( player && player->pipeline , MM_ERROR_PLAYER_NOT_INITIALIZED);
14923
14924         if (!(player->pipeline->mainbin) || !(player->pipeline->textbin))
14925         {
14926                 debug_error("Pipeline is not in proper state\n");
14927                 result = MM_ERROR_PLAYER_NOT_INITIALIZED;
14928                 goto EXIT;
14929         }
14930
14931         mainbin = player->pipeline->mainbin;
14932         textbin = player->pipeline->textbin;
14933
14934         current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
14935
14936         // sync clock with current pipeline
14937         curr_clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
14938         curr_time = gst_clock_get_time (curr_clock);
14939
14940         base_time = gst_element_get_base_time (GST_ELEMENT_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
14941         start_time = gst_element_get_start_time (GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
14942
14943         debug_log ("base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
14944                 GST_TIME_ARGS (base_time), GST_TIME_ARGS (start_time), GST_TIME_ARGS (curr_time));
14945
14946         if (current_state > GST_STATE_READY)
14947         {
14948                 // sync state with current pipeline
14949                 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
14950                 gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_PAUSED);
14951                 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
14952
14953                 ret = gst_element_get_state (mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
14954                 if ( GST_STATE_CHANGE_FAILURE == ret )
14955                 {
14956                         debug_error("fail to state change.\n");
14957                 }
14958         }
14959
14960         gst_element_set_base_time (textbin[MMPLAYER_T_BIN].gst, base_time);
14961         gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
14962
14963         if (curr_clock)
14964         {
14965                 gst_element_set_clock (textbin[MMPLAYER_T_BIN].gst, curr_clock);
14966                 gst_object_unref (curr_clock);
14967         }
14968
14969         // seek to current position
14970         if (!gst_element_query_position (mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time))
14971         {
14972                 result = MM_ERROR_PLAYER_INVALID_STATE;
14973                 debug_error("gst_element_query_position failed, invalid state\n");
14974                 goto EXIT;
14975         }
14976
14977         debug_log("seek time = %lld\n", time);
14978         event = gst_event_new_seek (1.0, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
14979         if (event)
14980         {
14981                 __gst_send_event_to_sink(player, event);
14982         }
14983         else
14984         {
14985                 result = MM_ERROR_PLAYER_INTERNAL;
14986                 debug_error("gst_event_new_seek failed\n");
14987                 goto EXIT;
14988         }
14989
14990         // sync state with current pipeline
14991         gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
14992         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
14993         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
14994
14995 EXIT:
14996         return result;
14997 }
14998
14999 static int
15000 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
15001 {
15002         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
15003         GstState current_state = GST_STATE_VOID_PENDING;
15004
15005         MMHandleType attrs = 0;
15006         MMPlayerGstElement* mainbin = NULL;
15007         MMPlayerGstElement* textbin = NULL;
15008
15009         gchar* subtitle_uri = NULL;
15010         int result = MM_ERROR_NONE;
15011         const gchar *charset = NULL;
15012
15013         MMPLAYER_FENTER();
15014
15015         /* check player handle */
15016         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15017         return_val_if_fail( filepath, MM_ERROR_COMMON_INVALID_ARGUMENT );
15018
15019         if (!(player->pipeline) || !(player->pipeline->mainbin))
15020         {
15021                 result = MM_ERROR_PLAYER_INVALID_STATE;
15022                 debug_error("Pipeline is not in proper state\n");
15023                 goto EXIT;
15024         }
15025
15026         mainbin = player->pipeline->mainbin;
15027         textbin = player->pipeline->textbin;
15028
15029         current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
15030         if (current_state < GST_STATE_READY)
15031         {
15032                 result = MM_ERROR_PLAYER_INVALID_STATE;
15033                 debug_error("Pipeline is not in proper state\n");
15034                 goto EXIT;
15035         }
15036
15037         attrs = MMPLAYER_GET_ATTRS(player);
15038         if (!attrs)
15039         {
15040                 debug_error("cannot get content attribute\n");
15041                 result = MM_ERROR_PLAYER_INTERNAL;
15042                 goto EXIT;
15043         }
15044
15045         mm_attrs_get_string_by_name (attrs, "subtitle_uri", &subtitle_uri);
15046         if (!subtitle_uri || strlen(subtitle_uri) < 1)
15047         {
15048                 debug_error("subtitle uri is not proper filepath\n");
15049                 result = MM_ERROR_PLAYER_INVALID_URI;
15050                 goto EXIT;
15051         }
15052
15053         debug_log("old subtitle file path is [%s]\n", subtitle_uri);
15054         debug_log("new subtitle file path is [%s]\n", filepath);
15055
15056         if (!strcmp (filepath, subtitle_uri))
15057         {
15058                 debug_log("No need to swtich subtitle, as input filepath is same as current filepath\n");
15059                 goto EXIT;
15060         }
15061         else
15062         {
15063                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
15064                 if (mmf_attrs_commit(player->attrs))
15065                 {
15066                         debug_error("failed to commit.\n");
15067                         goto EXIT;
15068                 }
15069         }
15070
15071         //gst_pad_set_blocked_async(src-srcpad, TRUE)
15072
15073         ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
15074         if (ret != GST_STATE_CHANGE_SUCCESS)
15075         {
15076                 debug_error("failed to change state of textbin to READY");
15077                 result = MM_ERROR_PLAYER_INTERNAL;
15078                 goto EXIT;
15079         }
15080
15081         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_READY);
15082         if (ret != GST_STATE_CHANGE_SUCCESS)
15083         {
15084                 debug_error("failed to change state of subparse to READY");
15085                 result = MM_ERROR_PLAYER_INTERNAL;
15086                 goto EXIT;
15087         }
15088
15089         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
15090         if (ret != GST_STATE_CHANGE_SUCCESS)
15091         {
15092                 debug_error("failed to change state of filesrc to READY");
15093                 result = MM_ERROR_PLAYER_INTERNAL;
15094                 goto EXIT;
15095         }
15096
15097         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
15098
15099         charset = util_get_charset(filepath);
15100         if (charset)
15101         {
15102                 debug_log ("detected charset is %s\n", charset );
15103                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
15104         }
15105
15106         result = _mmplayer_sync_subtitle_pipeline(player);
15107
15108 EXIT:
15109         MMPLAYER_FLEAVE();
15110         return result;
15111 }
15112
15113 /* API to switch between external subtitles */
15114 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
15115 {
15116         int result = MM_ERROR_NONE;
15117         mm_player_t* player = (mm_player_t*)hplayer;
15118
15119         MMPLAYER_FENTER();
15120
15121         /* check player handle */
15122         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15123
15124         if (!player->pipeline)  // IDLE state
15125         {
15126                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
15127                 if (mmf_attrs_commit(player->attrs))
15128                 {
15129                         debug_error("failed to commit.\n");
15130                         result= MM_ERROR_PLAYER_INTERNAL;
15131                 }
15132         }
15133         else    // curr state <> IDLE (READY, PAUSE, PLAYING..)
15134         {
15135                 if ( filepath == NULL )
15136                         return MM_ERROR_COMMON_INVALID_ARGUMENT;
15137
15138                 if (!__mmplayer_check_subtitle(player))
15139                 {
15140                         mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
15141                         if (mmf_attrs_commit(player->attrs))
15142                         {
15143                                 debug_error("failed to commit.\n");
15144                                 result = MM_ERROR_PLAYER_INTERNAL;
15145                         }
15146
15147                         if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
15148                                 debug_error("fail to create subtitle src\n");
15149
15150                         result = _mmplayer_sync_subtitle_pipeline(player);
15151                 }
15152                 else
15153                 {
15154                         result = __mmplayer_change_external_subtitle_language(player, filepath);
15155                 }
15156         }
15157
15158         MMPLAYER_FLEAVE();
15159         return result;
15160 }
15161
15162 static int
15163 __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index)
15164 {
15165         int result = MM_ERROR_NONE;
15166         gchar* change_pad_name = NULL;
15167         GstPad* sinkpad = NULL;
15168         MMPlayerGstElement* mainbin = NULL;
15169         enum MainElementID elemId = MMPLAYER_M_NUM;
15170         GstCaps* caps = NULL;
15171         gint total_track_num = 0;
15172
15173         MMPLAYER_FENTER();
15174
15175         return_val_if_fail (player && player->pipeline && player->pipeline->mainbin,
15176                                                                                                         MM_ERROR_PLAYER_NOT_INITIALIZED);
15177
15178         debug_log ("Change Track(%d) to %d\n", type, index);
15179
15180         mainbin = player->pipeline->mainbin;
15181
15182         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
15183         {
15184                 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
15185         }
15186         else if (type == MM_PLAYER_TRACK_TYPE_TEXT)
15187         {
15188                 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
15189         }
15190         else
15191         {
15192                 debug_error ("Track Type Error\n");
15193                 goto EXIT;
15194         }
15195
15196         if (mainbin[elemId].gst == NULL)
15197         {
15198                 result = MM_ERROR_PLAYER_NO_OP;
15199                 debug_log ("Req track doesn't exist\n");
15200                 goto EXIT;
15201         }
15202
15203         total_track_num = player->selector[type].total_track_num;
15204         if (total_track_num <= 0)
15205         {
15206                 result = MM_ERROR_PLAYER_NO_OP;
15207                 debug_log ("Language list is not available \n");
15208                 goto EXIT;
15209         }
15210
15211         if ((index < 0) || (index >= total_track_num))
15212         {
15213                 result = MM_ERROR_INVALID_ARGUMENT;
15214                 debug_log ("Not a proper index : %d \n", index);
15215                 goto EXIT;
15216         }
15217
15218         /*To get the new pad from the selector*/
15219         change_pad_name = g_strdup_printf ("sink_%u", index);
15220         if (change_pad_name == NULL)
15221         {
15222                 result = MM_ERROR_PLAYER_INTERNAL;
15223                 debug_log ("Pad does not exists\n");
15224                 goto EXIT;
15225         }
15226
15227         debug_log ("new active pad name: %s\n", change_pad_name);
15228
15229         sinkpad = gst_element_get_static_pad (mainbin[elemId].gst, change_pad_name);
15230         if (sinkpad == NULL)
15231         {
15232                 debug_log ("sinkpad is NULL");
15233                 result = MM_ERROR_PLAYER_INTERNAL;
15234                 goto EXIT;
15235         }
15236
15237         debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
15238         g_object_set (mainbin[elemId].gst, "active-pad", sinkpad, NULL);
15239
15240         caps = gst_pad_get_current_caps(sinkpad);
15241         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
15242
15243         if (sinkpad)
15244                 gst_object_unref (sinkpad);
15245
15246         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
15247         {
15248                 __mmplayer_set_audio_attrs (player, caps);
15249         }
15250
15251 EXIT:
15252
15253         MMPLAYER_FREEIF(change_pad_name);
15254         return result;
15255 }
15256
15257 int _mmplayer_change_track_language (MMHandleType hplayer, MMPlayerTrackType type, int index)
15258 {
15259         int result = MM_ERROR_NONE;
15260         mm_player_t* player = NULL;
15261         MMPlayerGstElement* mainbin = NULL;
15262
15263         gint current_active_index = 0;
15264
15265         GstState current_state = GST_STATE_VOID_PENDING;
15266         GstEvent* event = NULL;
15267         gint64 time = 0;
15268
15269         MMPLAYER_FENTER();
15270
15271         player = (mm_player_t*)hplayer;
15272         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15273
15274         if (!player->pipeline)
15275         {
15276                 debug_error ("Track %d pre setting -> %d\n", type, index);
15277
15278                 player->selector[type].active_pad_index = index;
15279                 goto EXIT;
15280         }
15281
15282         mainbin = player->pipeline->mainbin;
15283
15284         current_active_index = player->selector[type].active_pad_index;
15285
15286         /*If index is same as running index no need to change the pad*/
15287         if (current_active_index == index)
15288         {
15289                 goto EXIT;
15290         }
15291
15292         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time))
15293         {
15294                 result = MM_ERROR_PLAYER_INVALID_STATE;
15295                 goto EXIT;
15296         }
15297
15298         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
15299         if (current_state < GST_STATE_PAUSED)
15300         {
15301                 result = MM_ERROR_PLAYER_INVALID_STATE;
15302                 debug_warning ("Pipeline not in porper state\n");
15303                 goto EXIT;
15304         }
15305
15306         result = __mmplayer_change_selector_pad(player, type, index);
15307         if (result != MM_ERROR_NONE)
15308         {
15309                 debug_error ("change selector pad error\n");
15310                 goto EXIT;
15311         }
15312
15313         player->selector[type].active_pad_index = index;
15314
15315         if (current_state == GST_STATE_PLAYING)
15316         {
15317                 event = gst_event_new_seek (1.0, 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);
15318                 if (event)
15319                 {
15320                         __gst_send_event_to_sink (player, event);
15321                 }
15322                 else
15323                 {
15324                         result = MM_ERROR_PLAYER_INTERNAL;
15325                         goto EXIT;
15326                 }
15327         }
15328
15329 EXIT:
15330         return result;
15331 }
15332
15333 int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent)
15334 {
15335         mm_player_t* player = (mm_player_t*) hplayer;
15336
15337         MMPLAYER_FENTER();
15338
15339         /* check player handle */
15340         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15341
15342         *silent = player->set_mode.subtitle_off;
15343
15344         debug_log("subtitle is %s.\n", silent ? "ON" : "OFF");
15345
15346         MMPLAYER_FLEAVE();
15347
15348         return MM_ERROR_NONE;
15349 }
15350
15351 gboolean
15352 __is_es_buff_src( mm_player_t* player )
15353 {
15354         return_val_if_fail ( player, FALSE );
15355
15356         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF) ? TRUE : FALSE;
15357 }
15358
15359 gboolean
15360 __has_suffix(mm_player_t* player, const gchar* suffix)
15361 {
15362         return_val_if_fail( player, FALSE );
15363         return_val_if_fail( suffix, FALSE );
15364
15365         gboolean ret = FALSE;
15366         gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
15367         gchar* t_suffix = g_ascii_strdown(suffix, -1);
15368
15369         if ( g_str_has_suffix(player->profile.uri, suffix) )
15370         {
15371                 ret = TRUE;
15372         }
15373
15374         MMPLAYER_FREEIF(t_url);
15375         MMPLAYER_FREEIF(t_suffix);
15376
15377         return ret;
15378 }
15379
15380 int
15381 _mmplayer_set_display_zoom(MMHandleType hplayer, float level, int x, int y)
15382 {
15383         mm_player_t* player = (mm_player_t*) hplayer;
15384
15385         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15386
15387         MMPLAYER_VIDEO_SINK_CHECK(player);
15388
15389         debug_log("setting display zoom level = %f, offset = %d, %d", level, x, y);
15390
15391         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", level, "zoom-pos-x", x, "zoom-pos-y", y, NULL);
15392
15393         return MM_ERROR_NONE;
15394 }
15395 int
15396 _mmplayer_get_display_zoom(MMHandleType hplayer, float *level, int *x, int *y)
15397 {
15398
15399         mm_player_t* player = (mm_player_t*) hplayer;
15400         float _level = 0.0;
15401         int _x = 0;
15402         int _y = 0;
15403
15404         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15405
15406         MMPLAYER_VIDEO_SINK_CHECK(player);
15407
15408         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", &_level, "zoom-pos-x", &_x, "zoom-pos-y", &_y, NULL);
15409
15410         debug_log("display zoom level = %f, start off x = %d, y = %d", _level, _x, _y);
15411
15412         *level = _level;
15413         *x = _x;
15414         *y = _y;
15415
15416         return MM_ERROR_NONE;
15417 }
15418
15419 int
15420 _mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
15421 {
15422         mm_player_t* player = (mm_player_t*) hplayer;
15423
15424         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15425
15426         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL)
15427         {
15428                 MMPLAYER_PRINT_STATE(player);
15429                 debug_error("wrong-state : can't set the download mode to parse");
15430                 return MM_ERROR_PLAYER_INVALID_STATE;
15431         }
15432
15433         debug_log("set video hub download mode to %s", (mode)?"ON":"OFF");
15434         player->video_hub_download_mode = mode;
15435
15436         return MM_ERROR_NONE;
15437 }
15438
15439 int
15440 _mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
15441 {
15442         mm_player_t* player = (mm_player_t*) hplayer;
15443
15444         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15445
15446         debug_log("enable sync handler : %s", (enable)?"ON":"OFF");
15447         player->sync_handler = enable;
15448
15449         return MM_ERROR_NONE;
15450 }
15451
15452 int
15453 _mmplayer_set_video_share_master_clock( MMHandleType hplayer,
15454                                         long long clock,
15455                                         long long clock_delta,
15456                                         long long video_time,
15457                                         long long media_clock,
15458                                         long long audio_time)
15459 {
15460         mm_player_t* player = (mm_player_t*) hplayer;
15461         MMPlayerGstElement* mainbin = NULL;
15462         GstClockTime start_time_audio = 0, start_time_video = 0;
15463         GstClockTimeDiff base_time = 0, new_base_time = 0;
15464         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
15465         gint64 api_delta = 0;
15466         gint64 position = 0, position_delta = 0;
15467         gint64 adj_base_time = 0;
15468         GstClock *curr_clock = NULL;
15469         GstClockTime curr_time = 0;
15470         gboolean query_ret = TRUE;
15471         int result = MM_ERROR_NONE;
15472
15473         MMPLAYER_FENTER();
15474
15475         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
15476         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
15477         return_val_if_fail ( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
15478
15479         // debug_log("in(us) : %lld, %lld, %lld, %lld, %lld", clock, clock_delta, video_time, media_clock, audio_time);
15480
15481         if ((video_time < 0) || (player->doing_seek))
15482         {
15483                 debug_log("skip setting master clock.  %lld", video_time);
15484                 goto EXIT;
15485         }
15486
15487         mainbin = player->pipeline->mainbin;
15488
15489         curr_clock = gst_pipeline_get_clock (GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
15490         curr_time = gst_clock_get_time (curr_clock);
15491
15492         current_state = MMPLAYER_CURRENT_STATE(player);
15493
15494         if ( current_state == MM_PLAYER_STATE_PLAYING )
15495                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
15496
15497         if ( ( current_state != MM_PLAYER_STATE_PLAYING ) ||
15498                  ( !query_ret ))
15499         {
15500                 position = player->last_position;
15501                 debug_log ("query fail. %lld", position);
15502         }
15503
15504         clock*= GST_USECOND;
15505         clock_delta *= GST_USECOND;
15506
15507         api_delta = clock - curr_time;
15508         if ((player->video_share_api_delta == 0 ) || (player->video_share_api_delta > api_delta))
15509         {
15510                 player->video_share_api_delta = api_delta;
15511         }
15512         else
15513         {
15514                 clock_delta += (api_delta - player->video_share_api_delta);
15515         }
15516
15517         if ((player->video_share_clock_delta == 0 ) || (player->video_share_clock_delta > clock_delta))
15518         {
15519                 player->video_share_clock_delta = (gint64)clock_delta;
15520
15521                 position_delta = (position/GST_USECOND) - video_time;
15522                 position_delta *= GST_USECOND;
15523
15524                 adj_base_time = position_delta;
15525                 debug_log ("video_share_clock_delta = %lld, adj = %lld", player->video_share_clock_delta, adj_base_time);
15526
15527         }
15528         else
15529         {
15530                 gint64 new_play_time = 0;
15531                 gint64 network_delay =0;
15532
15533                 video_time *= GST_USECOND;
15534
15535                 network_delay = clock_delta - player->video_share_clock_delta;
15536                 new_play_time = video_time + network_delay;
15537
15538                 adj_base_time = position - new_play_time;
15539
15540                 debug_log ("%lld(delay) = %lld - %lld / %lld(adj) = %lld(slave_pos) - %lld(master_pos) - %lld(delay)",
15541                         network_delay, clock_delta, player->video_share_clock_delta, adj_base_time, position, video_time, network_delay);
15542         }
15543
15544         /* Adjust Current Stream Time with base_time of sink
15545          * 1. Set Start time to CLOCK NONE, to control the base time by MSL
15546          * 2. Set new base time
15547          *    if adj_base_time is positive value, the stream time will be decreased.
15548          * 3. If seek event is occurred, the start time will be reset. */
15549         if ((player->pipeline->audiobin) &&
15550                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
15551         {
15552                 start_time_audio = gst_element_get_start_time (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
15553
15554                 if (start_time_audio != GST_CLOCK_TIME_NONE)
15555                 {
15556                         debug_log ("audio sink : gst_element_set_start_time -> NONE");
15557                         gst_element_set_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, GST_CLOCK_TIME_NONE);
15558                 }
15559
15560                 base_time = gst_element_get_base_time (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
15561         }
15562
15563         if ((player->pipeline->videobin) &&
15564                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
15565         {
15566                 start_time_video = gst_element_get_start_time (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
15567
15568                 if (start_time_video != GST_CLOCK_TIME_NONE)
15569                 {
15570                         debug_log ("video sink : gst_element_set_start_time -> NONE");
15571                         gst_element_set_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst, GST_CLOCK_TIME_NONE);
15572                 }
15573
15574                 // if videobin exist, get base_time from videobin.
15575                 base_time = gst_element_get_base_time (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
15576         }
15577
15578         new_base_time = base_time + adj_base_time;
15579
15580         if ((player->pipeline->audiobin) &&
15581                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
15582                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), (GstClockTime)new_base_time);
15583
15584         if ((player->pipeline->videobin) &&
15585                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
15586                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), (GstClockTime)new_base_time);
15587
15588 EXIT:
15589         MMPLAYER_FLEAVE();
15590
15591         return result;
15592 }
15593
15594 int
15595 _mmplayer_get_video_share_master_clock( MMHandleType hplayer,
15596                                         long long *video_time,
15597                                         long long *media_clock,
15598                                         long long *audio_time)
15599 {
15600         mm_player_t* player = (mm_player_t*) hplayer;
15601         MMPlayerGstElement* mainbin = NULL;
15602         GstClock *curr_clock = NULL;
15603         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
15604         gint64 position = 0;
15605         gboolean query_ret = TRUE;
15606
15607         MMPLAYER_FENTER();
15608
15609         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
15610         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
15611         return_val_if_fail ( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
15612
15613         return_val_if_fail ( video_time, MM_ERROR_COMMON_INVALID_ARGUMENT );
15614         return_val_if_fail ( media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT );
15615         return_val_if_fail ( audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT );
15616
15617         mainbin = player->pipeline->mainbin;
15618
15619         curr_clock = gst_pipeline_get_clock (GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
15620
15621         current_state = MMPLAYER_CURRENT_STATE(player);
15622
15623         if ( current_state != MM_PLAYER_STATE_PAUSED )
15624                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
15625
15626         if ( ( current_state == MM_PLAYER_STATE_PAUSED ) ||
15627                  ( !query_ret ))
15628         {
15629                 position = player->last_position;
15630         }
15631
15632         *media_clock = *video_time = *audio_time = (position/GST_USECOND);
15633
15634         debug_log("media_clock: %lld, video_time: %lld (us)", *media_clock, *video_time);
15635
15636         if (curr_clock)
15637                 gst_object_unref (curr_clock);
15638
15639         MMPLAYER_FLEAVE();
15640
15641         return MM_ERROR_NONE;
15642 }
15643
15644 int
15645 _mmplayer_get_video_rotate_angle(MMHandleType hplayer, int *angle)
15646 {
15647         mm_player_t* player = (mm_player_t*) hplayer;
15648         int org_angle = 0;
15649
15650         MMPLAYER_FENTER();
15651
15652         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15653         return_val_if_fail ( angle, MM_ERROR_COMMON_INVALID_ARGUMENT );
15654
15655         if (player->v_stream_caps)
15656         {
15657                 GstStructure *str = NULL;
15658
15659                 str = gst_caps_get_structure (player->v_stream_caps, 0);
15660                 if ( !gst_structure_get_int (str, "orientation", &org_angle))
15661                 {
15662                         debug_log ("missing 'orientation' field in video caps");
15663                 }
15664         }
15665
15666         debug_log("orientation: %d", org_angle);
15667         *angle = org_angle;
15668
15669         MMPLAYER_FLEAVE();
15670         return MM_ERROR_NONE;
15671 }
15672
15673 gboolean
15674 __mmplayer_is_streaming(mm_player_t* player)
15675 {
15676         gboolean result = FALSE;
15677
15678         MMPLAYER_FENTER();
15679
15680         return_val_if_fail (player, FALSE);
15681         result = __is_streaming (player) ;
15682
15683         MMPLAYER_FLEAVE();
15684         return result;
15685 }
15686
15687 static gboolean
15688 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
15689 {
15690         return_val_if_fail (player, FALSE);
15691         return_val_if_fail (element, FALSE);
15692
15693         gchar *factory_name = GST_OBJECT_NAME (gst_element_get_factory(element));
15694         gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
15695
15696         int idx = 0;
15697
15698         for ( idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++ )
15699         {
15700                 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx]))
15701                 {
15702                         debug_log("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
15703                         mm_player_dump_t *dump_s;
15704                         dump_s = g_malloc (sizeof(mm_player_dump_t));
15705
15706                         if (dump_s == NULL)
15707                         {
15708                                 debug_error ("malloc fail");
15709                                 return FALSE;
15710                         }
15711
15712                         dump_s->dump_element_file = NULL;
15713                         dump_s->dump_pad = NULL;
15714                         dump_s->dump_pad = gst_element_get_static_pad (element, "sink");
15715
15716                         if (dump_s->dump_pad)
15717                         {
15718                                 memset (dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
15719                                 sprintf (dump_file_name, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
15720                                 dump_s->dump_element_file = fopen(dump_file_name,"w+");
15721                                 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);
15722                                 /* add list for removed buffer probe and close FILE */
15723                                 player->dump_list = g_list_append (player->dump_list, dump_s);
15724                                 debug_log ("%s sink pad added buffer probe for dump", factory_name);
15725                                 return TRUE;
15726                         }
15727                         else
15728                         {
15729                                 g_free(dump_s);
15730                                 dump_s = NULL;
15731                                 debug_error ("failed to get %s sink pad added", factory_name);
15732                         }
15733
15734
15735                 }
15736         }
15737         return FALSE;
15738 }
15739
15740 static GstPadProbeReturn
15741 __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data)
15742 {
15743         FILE *dump_data = (FILE *) u_data;
15744 //      int written = 0;
15745         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
15746         GstMapInfo probe_info = GST_MAP_INFO_INIT;
15747
15748         return_val_if_fail ( dump_data, FALSE );
15749
15750         gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
15751
15752 //      debug_log ("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS( GST_BUFFER_TIMESTAMP(buffer)));
15753
15754         fwrite ( probe_info.data, 1, probe_info.size , dump_data);
15755
15756         return GST_PAD_PROBE_OK;
15757 }
15758
15759 static void
15760 __mmplayer_release_dump_list (GList *dump_list)
15761 {
15762         if (dump_list)
15763         {
15764                 GList *d_list = dump_list;
15765                 for ( ;d_list ; d_list = g_list_next(d_list))
15766                 {
15767                         mm_player_dump_t *dump_s = d_list->data;
15768                         if (dump_s->dump_pad)
15769                         {
15770                                 if (dump_s->probe_handle_id)
15771                                 {
15772                                         gst_pad_remove_probe (dump_s->dump_pad, dump_s->probe_handle_id);
15773                                 }
15774
15775                         }
15776                         if (dump_s->dump_element_file)
15777                         {
15778                                 fclose(dump_s->dump_element_file);
15779                                 dump_s->dump_element_file = NULL;
15780                         }
15781                         MMPLAYER_FREEIF(dump_s);
15782                 }
15783                 g_list_free(dump_list);
15784                 dump_list = NULL;
15785         }
15786 }
15787
15788 int
15789 _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
15790 {
15791         mm_player_t* player = (mm_player_t*) hplayer;
15792
15793         MMPLAYER_FENTER();
15794
15795         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15796         return_val_if_fail ( exist, MM_ERROR_INVALID_ARGUMENT );
15797
15798         *exist = player->has_closed_caption;
15799
15800         MMPLAYER_FLEAVE();
15801
15802         return MM_ERROR_NONE;
15803 }
15804
15805 int
15806 _mmplayer_enable_media_packet_video_stream(MMHandleType hplayer, bool enable)
15807 {
15808         mm_player_t* player = (mm_player_t*) hplayer;
15809
15810         MMPLAYER_FENTER();
15811
15812         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15813         return_val_if_fail (enable == TRUE || enable == FALSE, MM_ERROR_INVALID_ARGUMENT);
15814         if(enable)
15815                 player->bufmgr = tbm_bufmgr_init(-1);
15816         else {
15817                 tbm_bufmgr_deinit(player->bufmgr);
15818                 player->bufmgr = NULL;
15819         }
15820
15821         player->set_mode.media_packet_video_stream = enable;
15822
15823         MMPLAYER_FLEAVE();
15824
15825         return MM_ERROR_NONE;
15826 }
15827
15828 void * _mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer)
15829 {
15830         void * ret = NULL
15831         MMPLAYER_FENTER();
15832         /* increase ref count of gst buffer */
15833         if (buffer)
15834                 ret = gst_buffer_ref((GstBuffer *)buffer);
15835
15836         MMPLAYER_FLEAVE();
15837         return ret;
15838 }
15839
15840 void _mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer)
15841 {
15842         MMPLAYER_FENTER();
15843         if (buffer) {
15844                 gst_buffer_unref((GstBuffer *)buffer);
15845                 buffer = NULL;
15846         }
15847         MMPLAYER_FLEAVE();
15848 }
15849
15850 void
15851 __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data)
15852 {
15853         mm_player_t *player  = (mm_player_t*)user_data;
15854         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
15855
15856         return_if_fail ( player );
15857
15858         debug_msg("app-src: feed audio\n");
15859
15860         if (player->media_stream_buffer_status_cb[type])
15861         {
15862                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
15863         }
15864 }
15865
15866 void
15867 __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data)
15868 {
15869         mm_player_t *player  = (mm_player_t*)user_data;
15870         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
15871
15872         return_if_fail ( player );
15873
15874         debug_msg("app-src: feed video\n");
15875
15876         if (player->media_stream_buffer_status_cb[type])
15877         {
15878                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
15879         }
15880 }
15881
15882 void
15883 __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data)
15884 {
15885         mm_player_t *player  = (mm_player_t*)user_data;
15886         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
15887
15888         return_if_fail ( player );
15889
15890         debug_msg("app-src: feed subtitle\n");
15891
15892         if (player->media_stream_buffer_status_cb[type])
15893         {
15894                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
15895         }
15896 }
15897
15898 void
15899 __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data)
15900 {
15901         mm_player_t *player  = (mm_player_t*)user_data;
15902         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
15903
15904         return_if_fail ( player );
15905
15906         debug_msg("app-src: audio buffer is full.\n");
15907
15908         if (player->media_stream_buffer_status_cb[type])
15909         {
15910                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
15911         }
15912 }
15913
15914 void
15915 __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data)
15916 {
15917         mm_player_t *player  = (mm_player_t*)user_data;
15918         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
15919
15920         return_if_fail ( player );
15921
15922         debug_msg("app-src: video buffer is full.\n");
15923
15924         if (player->media_stream_buffer_status_cb[type])
15925         {
15926                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
15927         }
15928 }
15929
15930 gboolean
15931 __gst_seek_audio_data (GstElement * appsrc, guint64 position, gpointer user_data)
15932 {
15933         mm_player_t *player  = (mm_player_t*)user_data;
15934         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
15935
15936         return_val_if_fail( player, FALSE );
15937
15938         debug_log("app-src: seek audio data\n");
15939
15940         if (player->media_stream_seek_data_cb[type])
15941         {
15942                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
15943         }
15944
15945         return TRUE;
15946 }
15947
15948 gboolean
15949 __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data)
15950 {
15951         mm_player_t *player  = (mm_player_t*)user_data;
15952         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
15953
15954         return_val_if_fail( player, FALSE );
15955
15956         debug_log("app-src: seek video data\n");
15957
15958         if (player->media_stream_seek_data_cb[type])
15959         {
15960                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
15961         }
15962
15963         return TRUE;
15964 }
15965
15966 gboolean
15967 __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data)
15968 {
15969         mm_player_t *player  = (mm_player_t*)user_data;
15970         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
15971
15972         return_val_if_fail( player, FALSE );
15973
15974         debug_log("app-src: seek subtitle data\n");
15975
15976         if (player->media_stream_seek_data_cb[type])
15977         {
15978                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
15979         }
15980
15981         return TRUE;
15982 }
15983
15984 int
15985 _mmplayer_set_pcm_spec(MMHandleType hplayer, int samplerate, int channel)
15986 {
15987         mm_player_t* player = (mm_player_t*) hplayer;
15988
15989         MMPLAYER_FENTER();
15990
15991         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15992
15993         player->pcm_samplerate = samplerate;
15994         player->pcm_channel = channel;
15995
15996         MMPLAYER_FLEAVE();
15997         return MM_ERROR_NONE;
15998 }
15999
16000 int _mmplayer_get_raw_video_caps(mm_player_t *player, char **caps)
16001 {
16002         GstCaps *v_caps = NULL;
16003         GstPad *pad = NULL;
16004         GstElement *gst;
16005         gint stype = 0;
16006
16007         if(!player->videosink_linked) {
16008                 debug_log("No video sink");
16009                 return MM_ERROR_NONE;
16010         }
16011         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
16012
16013         if (stype == MM_DISPLAY_SURFACE_NULL) {
16014                 debug_log("Display type is NULL");
16015                 if(!player->video_fakesink) {
16016                         debug_error("No fakesink");
16017                         return MM_ERROR_PLAYER_INVALID_STATE;
16018                 }
16019                 gst = player->video_fakesink;
16020         }
16021         else {
16022                 if ( !player->pipeline || !player->pipeline->videobin ||
16023                                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst ) {
16024                         debug_error("No video pipeline");
16025                         return MM_ERROR_PLAYER_INVALID_STATE;
16026                 }
16027                 gst = player->pipeline->videobin[MMPLAYER_V_SINK].gst;
16028         }
16029         pad = gst_element_get_static_pad(gst, "sink");
16030         if(!pad) {
16031                 debug_error("static pad is NULL");
16032                 return MM_ERROR_PLAYER_INVALID_STATE;
16033         }
16034         v_caps = gst_pad_get_current_caps(pad);
16035         gst_object_unref( pad );
16036
16037         if(!v_caps) {
16038                 debug_error("fail to get caps");
16039                 return MM_ERROR_PLAYER_INVALID_STATE;
16040         }
16041
16042         *caps = gst_caps_to_string(v_caps);
16043
16044         gst_caps_unref(v_caps);
16045
16046         return MM_ERROR_NONE;
16047 }