8d1463f1f906e44b5647cb3eb0a1ee3424b390e7
[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
47 #include "mm_player_priv.h"
48 #include "mm_player_ini.h"
49 #include "mm_player_attrs.h"
50 #include "mm_player_capture.h"
51 #include "mm_player_utils.h"
52 #include "mm_player_tracks.h"
53 #include <sched.h>
54
55 #include <mm_sound.h>
56 #include <mm_sound_focus.h>
57
58 #define MM_SMOOTH_STREAMING
59
60 /*===========================================================================================
61 |                                                                                                                                                                                       |
62 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
63 |                                                                                                                                                                                       |
64 ========================================================================================== */
65
66 /*---------------------------------------------------------------------------
67 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
68 ---------------------------------------------------------------------------*/
69
70 /*---------------------------------------------------------------------------
71 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
72 ---------------------------------------------------------------------------*/
73
74 /*---------------------------------------------------------------------------
75 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
76 ---------------------------------------------------------------------------*/
77
78 /*---------------------------------------------------------------------------
79 |    LOCAL #defines:                                                                                                            |
80 ---------------------------------------------------------------------------*/
81 #define TRICK_PLAY_MUTE_THRESHOLD_MAX   2.0
82 #define TRICK_PLAY_MUTE_THRESHOLD_MIN   0.0
83
84 #define MM_VOLUME_FACTOR_DEFAULT                1.0
85 #define MM_VOLUME_FACTOR_MIN                    0
86 #define MM_VOLUME_FACTOR_MAX                    1.0
87
88 #define MM_PLAYER_FADEOUT_TIME_DEFAULT  700000 // 700 msec
89
90 #define MM_PLAYER_MPEG_VNAME                            "mpegversion"
91 #define MM_PLAYER_DIVX_VNAME                            "divxversion"
92 #define MM_PLAYER_WMV_VNAME                             "wmvversion"
93 #define MM_PLAYER_WMA_VNAME                             "wmaversion"
94
95 #define DEFAULT_PLAYBACK_RATE                   1.0
96 #define PLAYBACK_RATE_EX_AUDIO_MIN              0.5
97 #define PLAYBACK_RATE_EX_AUDIO_MAX              2.0
98 #define PLAYBACK_RATE_EX_VIDEO_MIN              0.5
99 #define PLAYBACK_RATE_EX_VIDEO_MAX              1.5
100
101 #define GST_QUEUE_DEFAULT_TIME                  4
102 #define GST_QUEUE_HLS_TIME                              8
103
104 #define DEFAULT_AUDIO_CH                                0
105
106 #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) )
107
108 #define LAZY_PAUSE_TIMEOUT_MSEC 700
109 #define MM_PLAYER_NAME  "mmplayer"
110
111 #define SMOOTH_STREAMING_DEMUX "mssdemux"
112 /*
113  * g_array_index(a,t,i) does not calculate gst private structure.
114  * It replaces the g_array_index(a,t,i)
115  */
116 #define g_array_undef_struct_idx_p(a,t,i)       ((t *)(void *)((a)->data + ((i) * (a)->len)))
117
118 //#define ENABLE_DRMSRC
119
120 /*---------------------------------------------------------------------------
121 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
122 ---------------------------------------------------------------------------*/
123
124 /*---------------------------------------------------------------------------
125 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
126 ---------------------------------------------------------------------------*/
127
128 /*---------------------------------------------------------------------------
129 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
130 ---------------------------------------------------------------------------*/
131
132 /*---------------------------------------------------------------------------
133 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
134 ---------------------------------------------------------------------------*/
135
136 /*---------------------------------------------------------------------------
137 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
138 ---------------------------------------------------------------------------*/
139 static int              __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
140 static int              __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
141 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player);
142 static int              __mmplayer_gst_create_subtitle_src(mm_player_t* player);
143 static int              __mmplayer_gst_create_pipeline(mm_player_t* player);
144 static int              __mmplayer_gst_destroy_pipeline(mm_player_t* player);
145 static int              __mmplayer_gst_element_link_bucket(GList* element_bucket);
146
147 static GstPadProbeReturn        __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data);
148 static void             __mmplayer_gst_decode_pad_added(GstElement* elem, GstPad* pad, gpointer data);
149 static void             __mmplayer_gst_decode_no_more_pads(GstElement* elem, gpointer data);
150 static void             __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gpointer data);
151 static void             __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad, GstCaps *caps, gpointer data);
152 static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
153 static gint             __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad, GstCaps * caps, GstElementFactory* factory, gpointer data);
154 //static GValueArray* __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
155 static void __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad, gpointer data);
156 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
157 static void     __mmplayer_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
158 static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
159 static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
160
161 static void     __mmplayer_typefind_have_type(  GstElement *tf, guint probability, GstCaps *caps, gpointer data);
162 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
163 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
164 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
165 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
166 static void     __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
167 //static void   __mmplayer_check_video_zero_cpoy(mm_player_t* player, GstElementFactory* factory);
168
169 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
170 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
171 static void             __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
172
173 static void             __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data);
174 //static void    __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
175 static void             __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
176 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player );
177 static gboolean __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
178
179
180 static void             __mmplayer_init_factories(mm_player_t* player);
181 static void             __mmplayer_release_factories(mm_player_t* player);
182 static void             __mmplayer_release_misc(mm_player_t* player);
183 static void             __mmplayer_release_misc_post(mm_player_t* player);
184 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
185 static GstBusSyncReply __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data);
186 static gboolean __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data);
187
188 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
189 static gboolean      __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
190
191 int             __mmplayer_switch_audio_sink (mm_player_t* player);
192 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
193 static GstPadProbeReturn __mmplayer_audio_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
194 static GstPadProbeReturn __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
195 static GstPadProbeReturn __mmplayer_subtitle_adjust_position_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
196 static int __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index);
197
198 static gboolean __mmplayer_check_subtitle( mm_player_t* player );
199 static gboolean __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message );
200 static void             __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms );
201 static void             __mmplayer_cancel_eos_timer( mm_player_t* player );
202 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
203 static gboolean __mmplayer_link_decoder( mm_player_t* player,GstPad *srcpad);
204 static gboolean __mmplayer_link_sink( mm_player_t* player,GstPad *srcpad);
205 static int              __mmplayer_handle_missed_plugin(mm_player_t* player);
206 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
207 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
208 static void             __mmplayer_add_sink( mm_player_t* player, GstElement* sink);
209 static void             __mmplayer_del_sink( mm_player_t* player, GstElement* sink);
210 static void             __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
211 static gpointer __mmplayer_next_play_thread(gpointer data);
212 static gpointer __mmplayer_repeat_thread(gpointer data);
213 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
214
215
216 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
217 static GstPadProbeReturn __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data);
218 static void __mmplayer_release_dump_list (GList *dump_list);
219
220 static int              __gst_realize(mm_player_t* player);
221 static int              __gst_unrealize(mm_player_t* player);
222 static int              __gst_start(mm_player_t* player);
223 static int              __gst_stop(mm_player_t* player);
224 static int              __gst_pause(mm_player_t* player, gboolean async);
225 static int              __gst_resume(mm_player_t* player, gboolean async);
226 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
227                                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
228                                         gint64 cur, GstSeekType stop_type, gint64 stop );
229 static int __gst_pending_seek ( mm_player_t* player );
230
231 static int              __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called);
232 static int              __gst_get_position(mm_player_t* player, int format, unsigned long *position);
233 static int              __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
234 static int              __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
235 static int              __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
236
237 static gboolean __gst_send_event_to_sink( mm_player_t* player, GstEvent* event );
238
239 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
240 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
241
242 /*fadeout */
243 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
244 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
245
246 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
247 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
248
249 /* util */
250 static gboolean __is_es_buff_src(mm_player_t* player);
251 static gboolean __has_suffix(mm_player_t * player, const gchar * suffix);
252
253 static int  __mmplayer_realize_streaming_ext(mm_player_t* player);
254 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
255 static int __mmplayer_start_streaming_ext(mm_player_t *player);
256 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
257 static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
258
259 static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
260 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
261 static void __mmplayer_check_pipeline(mm_player_t* player);
262 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
263 static void __mmplayer_deactivate_old_path(mm_player_t *player);
264 #if 0 // We'll need this in future.
265 static int __mmplayer_gst_switching_element(mm_player_t *player, GstElement *search_from, const gchar *removal_name, const gchar *new_element_name);
266 #endif
267
268 static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg);
269 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
270 static gboolean __mmplayer_can_do_interrupt(mm_player_t *player);
271
272 /* device change post proc */
273 void __mmplayer_device_change_post_process(gpointer user);
274 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score);
275 void __mmplayer_inc_cb_score(mm_player_t* player);
276 void __mmplayer_post_proc_reset(mm_player_t* player);
277 void __mmplayer_device_change_trigger_post_process(mm_player_t* player);
278 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
279 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name);
280 static void             __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data);
281 static void             __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data);
282 static void     __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data);
283 static void             __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data);
284 static void             __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data);
285 static gboolean __gst_seek_audio_data (GstElement * appsrc, guint64 position, gpointer user_data);
286 static gboolean __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data);
287 static gboolean __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data);
288 /*===========================================================================================
289 |                                                                                                                                                                                       |
290 |  FUNCTION DEFINITIONS                                                                                                                                         |
291 |                                                                                                                                                                                       |
292 ========================================================================================== */
293
294 #if 0 //debug
295 static void
296 print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
297 {
298   gint i, count;
299
300   count = gst_tag_list_get_tag_size (list, tag);
301
302   debug_log("count = %d", count);
303
304   for (i = 0; i < count; i++) {
305     gchar *str;
306
307     if (gst_tag_get_type (tag) == G_TYPE_STRING) {
308       if (!gst_tag_list_get_string_index (list, tag, i, &str))
309         g_assert_not_reached ();
310     } else {
311       str =
312           g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
313     }
314
315     if (i == 0) {
316       g_print ("  %15s: %s\n", gst_tag_get_nick (tag), str);
317     } else {
318       g_print ("                 : %s\n", str);
319     }
320
321     g_free (str);
322   }
323 }
324 #endif
325
326 static void
327 __mmplayer_videostream_cb(GstElement *element, void *data,
328 int width, int height, gpointer user_data) // @
329 {
330         mm_player_t* player = (mm_player_t*)user_data;
331
332         return_if_fail ( player );
333
334         MMPLAYER_FENTER();
335
336         if (player->is_drm_file)
337         {
338                 MMMessageParamType msg_param = { 0, };
339                 debug_warning("not supported in drm file");
340                 msg_param.code = MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
341                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
342         }
343         else if ( !player->set_mode.media_packet_video_stream && player->video_stream_cb)
344         {
345                 MMPlayerVideoStreamDataType stream;
346
347                 /* clear stream data structure */
348                 memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
349
350                 stream.data[0] = data;
351                 stream.length_total = width * height * 4; // for rgb 32bit
352                 stream.height = height;
353                 stream.width = width;
354                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
355         }
356
357         MMPLAYER_FLEAVE();
358 }
359
360 static void
361 __mmplayer_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer data)
362 {
363         mm_player_t* player = (mm_player_t*)data;
364
365         return_if_fail ( player );
366
367         MMPLAYER_FENTER();
368
369         if (player->video_frame_render_error_cb )
370         {
371                 if (player->attrs)
372                 {
373                         int surface_type = 0;
374                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
375                         switch (surface_type)
376                         {
377                         case MM_DISPLAY_SURFACE_X_EXT:
378                                 player->video_frame_render_error_cb((unsigned int*)error_id, player->video_frame_render_error_cb_user_param);
379                                 debug_log("display surface type(X_EXT) : render error callback(%p) is finished", player->video_frame_render_error_cb);
380                                 break;
381                         default:
382                                 debug_error("video_frame_render_error_cb was set, but this surface type(%d) is not supported", surface_type);
383                                 break;
384                         }
385                 }
386                 else
387                 {
388                         debug_error("could not get surface type");
389                 }
390         }
391         else
392         {
393                 debug_warning("video_frame_render_error_cb was not set");
394         }
395
396         MMPLAYER_FLEAVE();
397 }
398
399 void
400 __mmplayer_device_change_post_process(gpointer user)
401 {
402         mm_player_t* player = (mm_player_t*)user;
403         unsigned long position = 0;
404         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
405         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
406
407         MMPLAYER_FENTER();
408
409         if (! player ||
410                 ! player->pipeline ||
411                 ! player->pipeline->mainbin ||
412                 ! player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
413         {
414                 goto EXIT;
415         }
416
417         current_state = MMPLAYER_CURRENT_STATE(player);
418         pending_state = MMPLAYER_PENDING_STATE(player);
419
420         if (player->post_proc.need_pause_and_resume)
421         {
422                 debug_log("pausing");
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_PAUSED);
426         }
427
428         /* seek should be done within pause and resume */
429         if (player->post_proc.need_seek)
430         {
431                 debug_log("seeking");
432                 __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position);
433                 debug_log(">> seek to current position = %ld ms", position);
434                 __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE);
435         }
436
437         if (player->post_proc.need_pause_and_resume)
438         {
439                 debug_log("resuming");
440                 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
441                         ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
442                         gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING);
443         }
444
445         /* async */
446         if (player->post_proc.need_async)
447         {
448                 debug_log("setting async");
449
450                 /* TODO : need some comment here */
451                 if (player->pipeline->textbin && player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst)
452                         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
453         }
454
455 EXIT:
456         /* reset all */
457         __mmplayer_post_proc_reset(player);
458         return;
459 }
460
461 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score)
462 {
463         return_if_fail(player);
464         player->post_proc.required_cb_score = score;
465         debug_log("set required score to : %d", score);
466 }
467
468 void __mmplayer_inc_cb_score(mm_player_t* player)
469 {
470         return_if_fail(player);
471         player->post_proc.cb_score++;
472         debug_log("post proc cb score increased to %d", player->post_proc.cb_score);
473 }
474
475 void __mmplayer_post_proc_reset(mm_player_t* player)
476 {
477         return_if_fail(player);
478
479         /* check if already triggered */
480         if (player->post_proc.id)
481         {
482                 /* TODO : need to consider multiple main context. !!!! */
483                 if (FALSE == g_source_remove(player->post_proc.id) )
484                 {
485                         debug_error("failed to remove exist post_proc item");
486                 }
487                 player->post_proc.id = 0;
488         }
489
490         memset(&player->post_proc, 0, sizeof(mm_player_post_proc_t));
491
492         /* set default required cb score 1 as only audio device has changed in this case.
493            if display status is changed with audio device, required cb score is set 2 in display status callback.
494            this logic bases on the assumption which audio device callback is called after calling display status callback. */
495         player->post_proc.required_cb_score = 1;
496 }
497
498 void
499 __mmplayer_device_change_trigger_post_process(mm_player_t* player)
500 {
501         return_if_fail(player);
502
503         /* check score */
504         if ( player->post_proc.cb_score < player->post_proc.required_cb_score )
505         {
506                 /* wait for next turn */
507                 debug_log("wait for next turn. required cb score : %d   current score : %d\n",
508                         player->post_proc.required_cb_score, player->post_proc.cb_score);
509                 return;
510         }
511
512         /* check if already triggered */
513         if (player->post_proc.id)
514         {
515                 /* TODO : need to consider multiple main context. !!!! */
516                 if (FALSE == g_source_remove(player->post_proc.id) )
517                 {
518                         debug_error("failed to remove exist post_proc item");
519                 }
520                 player->post_proc.id = 0;
521         }
522
523         player->post_proc.id = g_idle_add((GSourceFunc)__mmplayer_device_change_post_process, (gpointer)player);
524 }
525 #if 0
526 /* NOTE : Sound module has different latency according to output device So,
527  * synchronization problem can be happened whenever device is changed.
528  * To avoid this issue, we do reset avsystem or seek as workaroud.
529  */
530 static void
531 __mmplayer_sound_device_info_changed_cb_func (MMSoundDevice_t device_h, int changed_info_type, void *user_data)
532 {
533     int ret;
534     mm_sound_device_type_e device_type;
535         mm_player_t* player = (mm_player_t*) user_data;
536
537         return_if_fail( player );
538
539         debug_warning("device_info_changed_cb is called, device_h[0x%x], changed_info_type[%d]\n", device_h, changed_info_type);
540
541         __mmplayer_inc_cb_score(player);
542
543         /* get device type with device_h*/
544         ret = mm_sound_get_device_type(device_h, &device_type);
545         if (ret) {
546                 debug_error("failed to mm_sound_get_device_type()\n");
547         }
548
549         /* do pause and resume only if video is playing  */
550         if ( player->videodec_linked && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING )
551         {
552                 switch (device_type)
553                 {
554                         case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
555                         case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
556                         case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
557                         case MM_SOUND_DEVICE_TYPE_HDMI:
558                         case MM_SOUND_DEVICE_TYPE_MIRRORING:
559                         {
560                                 player->post_proc.need_pause_and_resume = TRUE;
561                         }
562                         break;
563
564                         default:
565                                 debug_log("do nothing");
566                 }
567         }
568         debug_warning("dispatched");
569
570         __mmplayer_device_change_trigger_post_process(player);
571 }
572 #endif
573 /* This function should be called after the pipeline goes PAUSED or higher
574 state. */
575 gboolean
576 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
577 {
578         static gboolean has_duration = FALSE;
579         static gboolean has_video_attrs = FALSE;
580         static gboolean has_audio_attrs = FALSE;
581         static gboolean has_bitrate = FALSE;
582         gboolean missing_only = FALSE;
583         gboolean all = FALSE;
584         gint64 dur_nsec = 0;
585         GstStructure* p = NULL;
586         MMHandleType attrs = 0;
587         gchar *path = NULL;
588         gint stream_service_type = STREAMING_SERVICE_NONE;
589         struct stat sb;
590
591         MMPLAYER_FENTER();
592
593         return_val_if_fail ( player, FALSE );
594
595         /* check player state here */
596         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
597                 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING )
598         {
599                 /* give warning now only */
600                 debug_warning("be careful. content attributes may not available in this state ");
601         }
602
603         /* get content attribute first */
604         attrs = MMPLAYER_GET_ATTRS(player);
605         if ( !attrs )
606         {
607                 debug_error("cannot get content attribute");
608                 return FALSE;
609         }
610
611         /* get update flag */
612
613         if ( flag & ATTR_MISSING_ONLY )
614         {
615                 missing_only = TRUE;
616                 debug_log("updating missed attr only");
617         }
618
619         if ( flag & ATTR_ALL )
620         {
621                 all = TRUE;
622                 has_duration = FALSE;
623                 has_video_attrs = FALSE;
624                 has_audio_attrs = FALSE;
625                 has_bitrate = FALSE;
626
627                 debug_log("updating all attrs");
628         }
629
630         if ( missing_only && all )
631         {
632                 debug_warning("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
633                 missing_only = FALSE;
634         }
635
636         if (  (flag & ATTR_DURATION) || (!has_duration && missing_only) || all )
637         {
638                 debug_log("try to update duration");
639                 has_duration = FALSE;
640
641                 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
642                 {
643                         player->duration = dur_nsec;
644                         debug_warning("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
645                 }
646
647                 /* try to get streaming service type */
648                 stream_service_type = __mmplayer_get_stream_service_type( player );
649                 mm_attrs_set_int_by_name ( attrs, "streaming_type", stream_service_type );
650
651                 /* check duration is OK */
652                 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
653                 {
654                         /* FIXIT : find another way to get duration here. */
655                         debug_error("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
656                 }
657                 else
658                 {
659                         /*update duration */
660                         mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
661                         has_duration = TRUE;
662                 }
663         }
664
665         if (  (flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all )
666         {
667                 /* update audio params
668                 NOTE : We need original audio params and it can be only obtained from src pad of audio
669                 decoder. Below code only valid when we are not using 'resampler' just before
670                 'audioconverter'. */
671
672                 debug_log("try to update audio attrs");
673                 has_audio_attrs = FALSE;
674
675                 if ( player->pipeline->audiobin &&
676                          player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
677                 {
678                         GstCaps *caps_a = NULL;
679                         GstPad* pad = NULL;
680                         gint samplerate = 0, channels = 0;
681
682                         pad = gst_element_get_static_pad(
683                                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
684
685                         if ( pad )
686                         {
687                                 caps_a = gst_pad_get_current_caps( pad );
688
689                                 if ( caps_a )
690                                 {
691                                         p = gst_caps_get_structure (caps_a, 0);
692
693                                         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
694
695                                         gst_structure_get_int (p, "rate", &samplerate);
696                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
697
698                                         gst_structure_get_int (p, "channels", &channels);
699                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
700
701                                         secure_debug_log("samplerate : %d       channels : %d", samplerate, channels);
702
703                                         gst_caps_unref( caps_a );
704                                         caps_a = NULL;
705
706                                         has_audio_attrs = TRUE;
707                                 }
708                                 else
709                                 {
710                                         debug_warning("not ready to get audio caps");
711                                 }
712
713                                 gst_object_unref( pad );
714                         }
715                         else
716                         {
717                                 debug_warning("failed to get pad from audiosink");
718                         }
719                 }
720         }
721
722         if ( (flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all )
723         {
724                 debug_log("try to update video attrs");
725                 has_video_attrs = FALSE;
726
727                 if ( player->pipeline->videobin &&
728                          player->pipeline->videobin[MMPLAYER_V_SINK].gst )
729                 {
730                         GstCaps *caps_v = NULL;
731                         GstPad* pad = NULL;
732                         gint tmpNu, tmpDe;
733                         gint width, height;
734
735                         pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
736                         if ( pad )
737                         {
738                                 caps_v = gst_pad_get_current_caps( pad );
739
740                                 /* Use v_stream_caps, if fail to get video_sink sink pad*/
741                                 if (!caps_v && player->v_stream_caps)
742                                 {
743                                         caps_v = player->v_stream_caps;
744                                         gst_caps_ref(caps_v);
745                                 }
746
747                                 if (caps_v)
748                                 {
749                                         p = gst_caps_get_structure (caps_v, 0);
750                                         gst_structure_get_int (p, "width", &width);
751                                         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
752
753                                         gst_structure_get_int (p, "height", &height);
754                                         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
755
756                                         gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
757
758                                         secure_debug_log("width : %d     height : %d", width, height );
759
760                                         gst_caps_unref( caps_v );
761                                         caps_v = NULL;
762
763                                         if (tmpDe > 0)
764                                         {
765                                                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
766                                                 secure_debug_log("fps : %d", tmpNu / tmpDe);
767                                         }
768
769                                         has_video_attrs = TRUE;
770                                 }
771                                 else
772                                 {
773                                         debug_log("no negitiated caps from videosink");
774                                 }
775                                 gst_object_unref( pad );
776                                 pad = NULL;
777                         }
778                         else
779                         {
780                                 debug_log("no videosink sink pad");
781                         }
782                 }
783         }
784
785
786         if ( (flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all )
787         {
788                 has_bitrate = FALSE;
789
790                 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
791                 if (player->duration)
792                 {
793                         guint64 data_size = 0;
794
795                         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
796                         {
797                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
798
799                                 if (stat(path, &sb) == 0)
800                                 {
801                                         data_size = (guint64)sb.st_size;
802                                 }
803                         }
804                         else if (MMPLAYER_IS_HTTP_STREAMING(player))
805                         {
806                                 data_size = player->http_content_size;
807                         }
808                         debug_log("try to update bitrate : data_size = %lld", data_size);
809
810                         if (data_size)
811                         {
812                                 guint64 bitrate = 0;
813                                 guint64 msec_dur = 0;
814
815                                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
816                                 bitrate = data_size * 8 * 1000 / msec_dur;
817                                 secure_debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
818                                 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
819
820                                 has_bitrate = TRUE;
821                         }
822
823                         if (MMPLAYER_IS_RTSP_STREAMING(player))
824                         {
825                                 if(player->total_bitrate)
826                                 {
827                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
828                                         has_bitrate = TRUE;
829                                 }
830                         }
831                 }
832         }
833
834         /* validate all */
835         if (  mmf_attrs_commit ( attrs ) )
836         {
837                 debug_error("failed to update attributes\n");
838                 return FALSE;
839         }
840
841         MMPLAYER_FLEAVE();
842
843         return TRUE;
844 }
845
846 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player )
847 {
848         gint streaming_type = STREAMING_SERVICE_NONE;
849
850         MMPLAYER_FENTER();
851
852         return_val_if_fail ( player &&
853                         player->pipeline &&
854                         player->pipeline->mainbin &&
855                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
856                         FALSE );
857
858         /* streaming service type if streaming */
859         if ( ! MMPLAYER_IS_STREAMING(player) )
860                 return STREAMING_SERVICE_NONE;
861
862         if (MMPLAYER_IS_HTTP_STREAMING(player))
863         {
864                 streaming_type = (player->duration == 0) ?
865                         STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
866         }
867
868         switch ( streaming_type )
869         {
870                 case STREAMING_SERVICE_LIVE:
871                         debug_log("it's live streaming");
872                 break;
873                 case STREAMING_SERVICE_VOD:
874                         debug_log("it's vod streaming");
875                 break;
876                 case STREAMING_SERVICE_NONE:
877                         debug_error("should not get here");
878                 break;
879                 default:
880                         debug_error("should not get here");
881         }
882
883         player->streaming_type = streaming_type;
884         MMPLAYER_FLEAVE();
885
886         return streaming_type;
887 }
888
889
890 /* this function sets the player state and also report
891  * it to applicaton by calling callback function
892  */
893 int
894 __mmplayer_set_state(mm_player_t* player, int state) // @
895 {
896         MMMessageParamType msg = {0, };
897         int sound_result = MM_ERROR_NONE;
898         gboolean post_bos = FALSE;
899         gboolean interrupted_by_asm = FALSE;
900         int ret = MM_ERROR_NONE;
901
902         return_val_if_fail ( player, FALSE );
903
904         if ( MMPLAYER_CURRENT_STATE(player) == state )
905         {
906                 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
907                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
908                 return ret;
909         }
910
911         /* update player states */
912         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
913         MMPLAYER_CURRENT_STATE(player) = state;
914
915         /* FIXIT : it's better to do like below code
916         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player) )
917                         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
918         and add more code to handling PENDING_STATE.
919         */
920         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
921                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
922
923         /* print state */
924         MMPLAYER_PRINT_STATE(player);
925
926         /* do some FSM stuffs before posting new state to application  */
927         interrupted_by_asm = player->sound_focus.by_asm_cb;
928
929         switch ( MMPLAYER_CURRENT_STATE(player) )
930         {
931                 case MM_PLAYER_STATE_NULL:
932                 case MM_PLAYER_STATE_READY:
933                 {
934                         if (player->cmd == MMPLAYER_COMMAND_STOP)
935                         {
936                                 sound_result = _mmplayer_sound_release_focus(&player->sound_focus);
937                                 if ( sound_result != MM_ERROR_NONE )
938                                 {
939                                         debug_error("failed to release sound focus\n");
940                                         return MM_ERROR_POLICY_INTERNAL;
941                                 }
942                         }
943                 }
944                 break;
945
946                 case MM_PLAYER_STATE_PAUSED:
947                 {
948                          if ( ! player->sent_bos )
949                          {
950                                 int found = 0;
951                                 #define MMPLAYER_MAX_SOUND_PRIORITY     3
952
953                                 /* it's first time to update all content attrs. */
954                                 _mmplayer_update_content_attrs( player, ATTR_ALL );
955                                 /* set max sound priority to keep own sound and not to mute other's one */
956                                 mm_attrs_get_int_by_name(player->attrs, "content_video_found", &found);
957                                 if (found)
958                                 {
959                                         mm_attrs_get_int_by_name(player->attrs, "content_audio_found", &found);
960                                         if (found)
961                                         {
962                                                 debug_log("set max audio priority");
963                                                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "priority", MMPLAYER_MAX_SOUND_PRIORITY, NULL);
964                                         }
965                                 }
966
967                          }
968
969                         /* add audio callback probe if condition is satisfied */
970                         if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
971                         {
972                                 __mmplayer_configure_audio_callback(player);
973                                 /* FIXIT : handle return value */
974                         }
975
976                         if (!MMPLAYER_IS_STREAMING(player) || (player->streamer && !player->streamer->is_buffering))
977                         {
978                                 sound_result = _mmplayer_sound_release_focus(&player->sound_focus);
979                                 if ( sound_result != MM_ERROR_NONE )
980                                 {
981                                         debug_error("failed to release sound focus\n");
982                                         return MM_ERROR_POLICY_INTERNAL;
983                                 }
984                         }
985                 }
986                 break;
987
988                 case MM_PLAYER_STATE_PLAYING:
989                 {
990                         /* try to get content metadata */
991                         if ( ! player->sent_bos )
992                         {
993                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
994                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
995                                  * legacy mmfw-player api */
996                                 _mmplayer_update_content_attrs( player, ATTR_MISSING_ONLY);
997                         }
998
999                         if ( (player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME) )
1000                         {
1001                                 if (!player->sent_bos)
1002                                 {
1003                                         __mmplayer_handle_missed_plugin ( player );
1004                                 }
1005                                 sound_result = _mmplayer_sound_acquire_focus(&player->sound_focus);
1006                                 if (sound_result != MM_ERROR_NONE)
1007                                 {
1008                                         // FIXME : need to check history
1009                                         if (player->pipeline->videobin)
1010                                         {
1011                                                 MMMessageParamType msg = {0, };
1012
1013                                                 debug_error("failed to go ahead because of video conflict\n");
1014
1015                                                 msg.union_type = MM_MSG_UNION_CODE;
1016                                                 msg.code = MM_ERROR_POLICY_INTERRUPTED;
1017                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
1018
1019                                                 _mmplayer_unrealize((MMHandleType)player);
1020                                         }
1021                                         else
1022                                         {
1023                                                 debug_error("failed to play by sound focus error : 0x%X\n", sound_result);
1024                                                 _mmplayer_pause((MMHandleType)player);
1025                                                 return sound_result;
1026                                         }
1027
1028                                         return MM_ERROR_POLICY_INTERNAL;
1029                                 }
1030                         }
1031
1032                         if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
1033                         {
1034                                 /* initialize because auto resume is done well. */
1035                                 player->resumed_by_rewind = FALSE;
1036                                 player->playback_rate = 1.0;
1037                         }
1038
1039                         if ( !player->sent_bos )
1040                         {
1041                                 /* check audio codec field is set or not
1042                                  * we can get it from typefinder or codec's caps.
1043                                  */
1044                                 gchar *audio_codec = NULL;
1045                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
1046
1047                                 /* The codec format can't be sent for audio only case like amr, mid etc.
1048                                  * Because, parser don't make related TAG.
1049                                  * So, if it's not set yet, fill it with found data.
1050                                  */
1051                                 if ( ! audio_codec )
1052                                 {
1053                                         if ( g_strrstr(player->type, "audio/midi"))
1054                                         {
1055                                                 audio_codec = g_strdup("MIDI");
1056
1057                                         }
1058                                         else if ( g_strrstr(player->type, "audio/x-amr"))
1059                                         {
1060                                                 audio_codec = g_strdup("AMR");
1061                                         }
1062                                         else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
1063                                         {
1064                                                 audio_codec = g_strdup("AAC");
1065                                         }
1066                                         else
1067                                         {
1068                                                 audio_codec = g_strdup("unknown");
1069                                         }
1070                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1071
1072                                         MMPLAYER_FREEIF(audio_codec);
1073                                         mmf_attrs_commit(player->attrs);
1074                                         debug_log("set audio codec type with caps\n");
1075                                 }
1076
1077                                 post_bos = TRUE;
1078                         }
1079                 }
1080                 break;
1081
1082                 case MM_PLAYER_STATE_NONE:
1083                 default:
1084                         debug_warning("invalid target state, there is nothing to do.\n");
1085                         break;
1086         }
1087
1088
1089         /* post message to application */
1090         if (MMPLAYER_TARGET_STATE(player) == state)
1091         {
1092                 /* fill the message with state of player */
1093                 msg.state.previous = MMPLAYER_PREV_STATE(player);
1094                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
1095
1096                 debug_log ("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
1097
1098                 /* state changed by asm callback */
1099                 if ( interrupted_by_asm )
1100                 {
1101                         msg.union_type = MM_MSG_UNION_CODE;
1102                         msg.code = player->sound_focus.focus_changed_msg;       /* FIXME: player.c convert function have to be modified. */
1103                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
1104                 }
1105                 /* state changed by usecase */
1106                 else
1107                 {
1108                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
1109                 }
1110         }
1111         else
1112         {
1113                 debug_log ("intermediate state, do nothing.\n");
1114                 MMPLAYER_PRINT_STATE(player);
1115                 return ret;
1116         }
1117
1118         if ( post_bos )
1119         {
1120                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
1121                 player->sent_bos = TRUE;
1122         }
1123
1124         return ret;
1125 }
1126
1127 static gpointer __mmplayer_next_play_thread(gpointer data)
1128 {
1129         mm_player_t* player = (mm_player_t*) data;
1130         MMPlayerGstElement *mainbin = NULL;
1131
1132         return_val_if_fail ( player, NULL );
1133
1134         g_mutex_lock(&player->next_play_thread_mutex);
1135         while ( ! player->next_play_thread_exit )
1136         {
1137                 debug_log("next play thread started. waiting for signal.\n");
1138                 g_cond_wait(&player->next_play_thread_cond, &player->next_play_thread_mutex );
1139
1140                 debug_log("reconfigure pipeline for gapless play.\n");
1141
1142                 if ( player->next_play_thread_exit )
1143                 {
1144                         if(player->gapless.reconfigure)
1145                         {
1146                                 player->gapless.reconfigure = false;
1147                                 MMPLAYER_PLAYBACK_UNLOCK(player);
1148                         }
1149                         debug_log("exiting gapless play thread\n");
1150                         break;
1151                 }
1152
1153                 mainbin = player->pipeline->mainbin;
1154
1155                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
1156                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
1157                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
1158                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
1159                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
1160
1161                 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
1162         }
1163         g_mutex_unlock(&player->next_play_thread_mutex);
1164
1165         return NULL;
1166 }
1167
1168 static gpointer __mmplayer_repeat_thread(gpointer data)
1169 {
1170         mm_player_t* player = (mm_player_t*) data;
1171         gboolean ret_value = FALSE;
1172         MMHandleType attrs = 0;
1173         gint count = 0;
1174
1175         return_val_if_fail ( player, NULL );
1176
1177         g_mutex_lock(&player->repeat_thread_mutex);
1178         while ( ! player->repeat_thread_exit )
1179         {
1180                 debug_log("repeat thread started. waiting for signal.\n");
1181                 g_cond_wait(&player->repeat_thread_cond, &player->repeat_thread_mutex );
1182
1183                 if ( player->repeat_thread_exit )
1184                 {
1185                         debug_log("exiting repeat thread\n");
1186                         break;
1187                 }
1188
1189
1190                 /* lock */
1191                 g_mutex_lock(&player->cmd_lock);
1192
1193                 attrs = MMPLAYER_GET_ATTRS(player);
1194
1195                 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1196                 {
1197                         debug_error("can not get play count\n");
1198                         break;
1199                 }
1200
1201                 if ( player->section_repeat )
1202                 {
1203                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1204                 }
1205                 else
1206                 {
1207                         if ( player->playback_rate < 0.0 )
1208                         {
1209                                 player->resumed_by_rewind = TRUE;
1210                                 _mmplayer_set_mute((MMHandleType)player, 0);
1211                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1212                         }
1213
1214                         ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
1215                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1216                                 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1217
1218                         /* initialize */
1219                         player->sent_bos = FALSE;
1220                 }
1221
1222                 if ( ! ret_value )
1223                 {
1224                         debug_error("failed to set position to zero for rewind\n");
1225                         continue;
1226                 }
1227
1228                 /* decrease play count */
1229                 if ( count > 1 )
1230                 {
1231                         /* we successeded to rewind. update play count and then wait for next EOS */
1232                         count--;
1233
1234                         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1235
1236                         /* commit attribute */
1237                         if ( mmf_attrs_commit ( attrs ) )
1238                         {
1239                                 debug_error("failed to commit attribute\n");
1240                         }
1241                 }
1242
1243                 /* unlock */
1244                 g_mutex_unlock(&player->cmd_lock);
1245         }
1246
1247         g_mutex_unlock(&player->repeat_thread_mutex);
1248         return NULL;
1249 }
1250
1251 static void
1252 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
1253 {
1254         MMHandleType attrs = 0;
1255         guint64 data_size = 0;
1256         gchar* path = NULL;
1257         unsigned long pos_msec = 0;
1258         struct stat sb;
1259
1260         return_if_fail( player && player->pipeline && player->pipeline->mainbin);
1261
1262         __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_msec);       // update last_position
1263
1264         attrs = MMPLAYER_GET_ATTRS(player);
1265         if ( !attrs )
1266         {
1267                 debug_error("fail to get attributes.\n");
1268                 return;
1269         }
1270
1271         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1272         {
1273                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1274
1275                 if (stat(path, &sb) == 0)
1276                 {
1277                         data_size = (guint64)sb.st_size;
1278                 }
1279         }
1280         else if (MMPLAYER_IS_HTTP_STREAMING(player))
1281         {
1282                 data_size = player->http_content_size;
1283         }
1284
1285         __mm_player_streaming_buffering(        player->streamer,
1286                                                                                 buffering_msg,
1287                                                                                 data_size,
1288                                                                                 player->last_position,
1289                                                                                 player->duration);
1290
1291         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
1292
1293         return;
1294 }
1295
1296 static int
1297 __mmplayer_handle_buffering_message ( mm_player_t* player )
1298 {
1299         int ret = MM_ERROR_NONE;
1300         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1301         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1302         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1303         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1304
1305         MMPLAYER_CMD_LOCK( player );
1306
1307         if( !player || !player->streamer || MMPLAYER_IS_LIVE_STREAMING(player))
1308         {
1309                 ret = MM_ERROR_PLAYER_INVALID_STATE;
1310                 goto unlock_exit;
1311         }
1312
1313         prev_state = MMPLAYER_PREV_STATE(player);
1314         current_state = MMPLAYER_CURRENT_STATE(player);
1315         target_state = MMPLAYER_TARGET_STATE(player);
1316         pending_state = MMPLAYER_PENDING_STATE(player);
1317
1318         debug_log( "player state : prev %s, current %s, pending %s, target %s, buffering %d",
1319                 MMPLAYER_STATE_GET_NAME(prev_state),
1320                 MMPLAYER_STATE_GET_NAME(current_state),
1321                 MMPLAYER_STATE_GET_NAME(pending_state),
1322                 MMPLAYER_STATE_GET_NAME(target_state),
1323                 player->streamer->is_buffering);
1324
1325         if ( !player->streamer->is_buffering )
1326         {
1327                 /* NOTE : if buffering has done, player has to go to target state. */
1328                 switch ( target_state )
1329                 {
1330                         case MM_PLAYER_STATE_PAUSED :
1331                         {
1332                                 switch ( pending_state )
1333                                 {
1334                                         case MM_PLAYER_STATE_PLAYING:
1335                                         {
1336                                                 __gst_pause ( player, TRUE );
1337                                         }
1338                                         break;
1339
1340                                         case MM_PLAYER_STATE_PAUSED:
1341                                         {
1342                                                 debug_log("player is already going to paused state, there is nothing to do.\n");
1343                                         }
1344                                         break;
1345
1346                                         case MM_PLAYER_STATE_NONE:
1347                                         case MM_PLAYER_STATE_NULL:
1348                                         case MM_PLAYER_STATE_READY:
1349                                         default :
1350                                         {
1351                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1352                                         }
1353                                                 break;
1354                                 }
1355                         }
1356                         break;
1357
1358                         case MM_PLAYER_STATE_PLAYING :
1359                         {
1360                                 switch ( pending_state )
1361                                 {
1362                                         case MM_PLAYER_STATE_NONE:
1363                                         {
1364                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
1365                                                         __gst_resume ( player, TRUE );
1366                                         }
1367                                         break;
1368
1369                                         case MM_PLAYER_STATE_PAUSED:
1370                                         {
1371                                                 /* NOTE: It should be worked as asynchronously.
1372                                                  * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1373                                                  */
1374                                                 __gst_resume ( player, TRUE );
1375                                         }
1376                                         break;
1377
1378                                         case MM_PLAYER_STATE_PLAYING:
1379                                         {
1380                                                 debug_log("player is already going to playing state, there is nothing to do.\n");
1381                                         }
1382                                         break;
1383
1384                                         case MM_PLAYER_STATE_NULL:
1385                                         case MM_PLAYER_STATE_READY:
1386                                         default :
1387                                         {
1388                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1389                                         }
1390                                                 break;
1391                                 }
1392                         }
1393                         break;
1394
1395                         case MM_PLAYER_STATE_NULL :
1396                         case MM_PLAYER_STATE_READY :
1397                         case MM_PLAYER_STATE_NONE :
1398                         default:
1399                         {
1400                                 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1401                         }
1402                                 break;
1403                 }
1404         }
1405         else
1406         {
1407                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1408                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
1409                  */
1410                 switch ( pending_state )
1411                 {
1412                         case MM_PLAYER_STATE_NONE:
1413                         {
1414                                 if (current_state != MM_PLAYER_STATE_PAUSED)
1415                                 {
1416                                         debug_log("set pause state during buffering\n");
1417                                         __gst_pause ( player, TRUE );
1418
1419                                         // to cover the weak-signal environment.
1420                                         if (MMPLAYER_IS_RTSP_STREAMING(player))
1421                                         {
1422                                                 unsigned long position = 0;
1423                                                 gint64 pos_msec = 0;
1424
1425                                                 debug_log("[RTSP] seek to the buffering start point\n");
1426
1427                                                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
1428                                                 {
1429                                                         debug_error("failed to get position\n");
1430                                                         break;
1431                                                 }
1432
1433                                                 /* key unit seek */
1434                                                 pos_msec = position * G_GINT64_CONSTANT(1000000);
1435
1436                                                 __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
1437                                                                         GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1438                                                                         pos_msec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1439                                         }
1440                                 }
1441                         }
1442                         break;
1443
1444                         case MM_PLAYER_STATE_PLAYING:
1445                         {
1446                                 __gst_pause ( player, TRUE );
1447                         }
1448                         break;
1449
1450                         case MM_PLAYER_STATE_PAUSED:
1451                         {
1452                         }
1453                         break;
1454
1455                         case MM_PLAYER_STATE_NULL:
1456                         case MM_PLAYER_STATE_READY:
1457                         default :
1458                         {
1459                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1460                         }
1461                                 break;
1462                 }
1463         }
1464
1465 unlock_exit:
1466         MMPLAYER_CMD_UNLOCK( player );
1467         return ret;
1468 }
1469
1470 static void
1471 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
1472 {
1473         MMPlayerGstElement *textbin;
1474         MMPLAYER_FENTER();
1475
1476         return_if_fail ( player &&
1477                                         player->pipeline &&
1478                                         player->pipeline->textbin);
1479
1480         return_if_fail (player->pipeline->textbin[MMPLAYER_T_IDENTITY].gst);
1481
1482         textbin = player->pipeline->textbin;
1483
1484         if (is_drop)
1485         {
1486                 debug_log("Drop subtitle text after getting EOS\n");
1487
1488                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
1489                 g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1490
1491                 player->is_subtitle_force_drop = TRUE;
1492         }
1493         else
1494         {
1495                 if (player->is_subtitle_force_drop == TRUE)
1496                 {
1497                         debug_log("Enable subtitle data path without drop\n");
1498
1499                         g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1500                         g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
1501
1502                         debug_log ("non-connected with external display");
1503
1504                         player->is_subtitle_force_drop = FALSE;
1505                 }
1506         }
1507 }
1508
1509 static gboolean
1510 __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
1511 {
1512         mm_player_t* player = (mm_player_t*) data;
1513         gboolean ret = TRUE;
1514         static gboolean async_done = FALSE;
1515
1516         return_val_if_fail ( player, FALSE );
1517         return_val_if_fail ( msg && GST_IS_MESSAGE(msg), FALSE );
1518
1519         switch ( GST_MESSAGE_TYPE( msg ) )
1520         {
1521                 case GST_MESSAGE_UNKNOWN:
1522                         debug_log("unknown message received\n");
1523                 break;
1524
1525                 case GST_MESSAGE_EOS:
1526                 {
1527                         MMHandleType attrs = 0;
1528                         gint count = 0;
1529
1530                         debug_log("GST_MESSAGE_EOS received\n");
1531
1532                         /* NOTE : EOS event is comming multiple time. watch out it */
1533                         /* check state. we only process EOS when pipeline state goes to PLAYING */
1534                         if ( ! (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) )
1535                         {
1536                                 debug_log("EOS received on non-playing state. ignoring it\n");
1537                                 break;
1538                         }
1539
1540                         __mmplayer_drop_subtitle(player, TRUE);
1541
1542                         if ( (player->audio_stream_cb) && (player->set_mode.pcm_extraction) && (!player->audio_stream_render_cb_ex))
1543                         {
1544                                 GstPad *pad = NULL;
1545
1546                                 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1547
1548                                 debug_log("release audio callback\n");
1549
1550                                 /* release audio callback */
1551                                 gst_pad_remove_probe (pad, player->audio_cb_probe_id);
1552                                 player->audio_cb_probe_id = 0;
1553                                 /* audio callback should be free because it can be called even though probe remove.*/
1554                                 player->audio_stream_cb = NULL;
1555                                 player->audio_stream_cb_user_param = NULL;
1556
1557                         }
1558
1559                         /* rewind if repeat count is greater then zero */
1560                         /* get play count */
1561                         attrs = MMPLAYER_GET_ATTRS(player);
1562
1563                         if ( attrs )
1564                         {
1565                                 gboolean smooth_repeat = FALSE;
1566
1567                                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1568                                 mm_attrs_get_int_by_name(attrs, "profile_smooth_repeat", &smooth_repeat);
1569
1570                                 player->play_count = count;
1571
1572                                 debug_log("remaining play count: %d, playback rate: %f\n", count, player->playback_rate);
1573
1574                                 if ( count > 1 || count == -1 || player->playback_rate < 0.0 ) /* default value is 1 */
1575                                 {
1576                                         if ( smooth_repeat )
1577                                         {
1578                                                 debug_log("smooth repeat enabled. seeking operation will be excuted in new thread\n");
1579
1580                                                 g_cond_signal( &player->repeat_thread_cond );
1581
1582                                                 break;
1583                                         }
1584                                         else
1585                                         {
1586                                                 gint ret_value = 0;
1587
1588                                                 if ( player->section_repeat )
1589                                                 {
1590                                                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1591                                                 }
1592                                                 else
1593                                                 {
1594                                                         if ( player->playback_rate < 0.0 )
1595                                                         {
1596                                                                 player->resumed_by_rewind = TRUE;
1597                                                                 _mmplayer_set_mute((MMHandleType)player, 0);
1598                                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1599                                                         }
1600
1601                                                         __mmplayer_handle_eos_delay( player, player->ini.delay_before_repeat );
1602
1603                                                         /* initialize */
1604                                                         player->sent_bos = FALSE;
1605                                                 }
1606
1607                                                 if ( MM_ERROR_NONE != ret_value )
1608                                                 {
1609                                                         debug_error("failed to set position to zero for rewind\n");
1610                                                 }
1611
1612                                                 /* not posting eos when repeating */
1613                                                 break;
1614                                         }
1615                                 }
1616                         }
1617
1618                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-eos" );
1619
1620                         /* post eos message to application */
1621                         __mmplayer_handle_eos_delay( player, player->ini.eos_delay );
1622
1623                         /* reset last position */
1624                         player->last_position = 0;
1625                 }
1626                 break;
1627
1628                 case GST_MESSAGE_ERROR:
1629                 {
1630                         GError *error = NULL;
1631                         gchar* debug = NULL;
1632
1633                         /* generating debug info before returning error */
1634                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-error" );
1635
1636                         /* get error code */
1637                         gst_message_parse_error( msg, &error, &debug );
1638
1639                         if ( gst_structure_has_name ( gst_message_get_structure(msg), "streaming_error" ) )
1640                         {
1641                                 /* Note : the streaming error from the streaming source is handled
1642                                  *   using __mmplayer_handle_streaming_error.
1643                                  */
1644                                 __mmplayer_handle_streaming_error ( player, msg );
1645
1646                                 /* dump state of all element */
1647                                 __mmplayer_dump_pipeline_state( player );
1648                         }
1649                         else
1650                         {
1651                                 /* traslate gst error code to msl error code. then post it
1652                                  * to application if needed
1653                                  */
1654                                 __mmplayer_handle_gst_error( player, msg, error );
1655
1656                                 if (debug)
1657                                 {
1658                                         debug_error ("error debug : %s", debug);
1659                                 }
1660
1661                         }
1662
1663                         if (MMPLAYER_IS_HTTP_PD(player))
1664                         {
1665                                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
1666                         }
1667
1668                         MMPLAYER_FREEIF( debug );
1669                         g_error_free( error );
1670                 }
1671                 break;
1672
1673                 case GST_MESSAGE_WARNING:
1674                 {
1675                         char* debug = NULL;
1676                         GError* error = NULL;
1677
1678                         gst_message_parse_warning(msg, &error, &debug);
1679
1680                         debug_log("warning : %s\n", error->message);
1681                         debug_log("debug : %s\n", debug);
1682
1683                         MMPLAYER_POST_MSG( player, MM_MESSAGE_WARNING, NULL );
1684
1685                         MMPLAYER_FREEIF( debug );
1686                         g_error_free( error );
1687                 }
1688                 break;
1689
1690                 case GST_MESSAGE_TAG:
1691                 {
1692                         debug_log("GST_MESSAGE_TAG\n");
1693                         if ( ! __mmplayer_gst_extract_tag_from_msg( player, msg ) )
1694                         {
1695                                 debug_warning("failed to extract tags from gstmessage\n");
1696                         }
1697                 }
1698                 break;
1699
1700                 case GST_MESSAGE_BUFFERING:
1701                 {
1702                         MMMessageParamType msg_param = {0, };
1703
1704                         if (!MMPLAYER_IS_STREAMING(player))
1705                                 break;
1706
1707                         /* ignore the prev buffering message */
1708                         if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (player->streamer->is_buffering_done == TRUE))
1709                         {
1710                                 gint buffer_percent = 0;
1711
1712                                 gst_message_parse_buffering (msg, &buffer_percent);
1713
1714                                 if (buffer_percent == MAX_BUFFER_PERCENT)
1715                                 {
1716                                         debug_log ("Ignored all the previous buffering msg! (got %d%%)\n", buffer_percent);
1717                                         player->streamer->is_buffering_done = FALSE;
1718                                 }
1719
1720                                 break;
1721                         }
1722
1723                         __mmplayer_update_buffer_setting(player, msg);
1724
1725                         if(__mmplayer_handle_buffering_message ( player ) == MM_ERROR_NONE) {
1726
1727                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1728                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param );
1729                                 if (MMPLAYER_IS_RTSP_STREAMING(player) &&
1730                                                 (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT))
1731                                 {
1732                                         if (player->doing_seek)
1733                                         {
1734                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
1735                                                 {
1736                                                         player->doing_seek = FALSE;
1737                                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
1738                                                 }
1739                                                 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
1740                                                 {
1741                                                         async_done = TRUE;
1742                                                 }
1743                                         }
1744                                 }
1745                         }
1746                 }
1747                 break;
1748
1749                 case GST_MESSAGE_STATE_CHANGED:
1750                 {
1751                         MMPlayerGstElement *mainbin;
1752                         const GValue *voldstate, *vnewstate, *vpending;
1753                         GstState oldstate, newstate, pending;
1754
1755                         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
1756                         {
1757                                 debug_error("player pipeline handle is null");
1758                                 break;
1759                         }
1760
1761                         mainbin = player->pipeline->mainbin;
1762
1763                         /* we only handle messages from pipeline */
1764                         if( msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst )
1765                                 break;
1766
1767                         /* get state info from msg */
1768                         voldstate = gst_structure_get_value (gst_message_get_structure(msg), "old-state");
1769                         vnewstate = gst_structure_get_value (gst_message_get_structure(msg), "new-state");
1770                         vpending = gst_structure_get_value (gst_message_get_structure(msg), "pending-state");
1771
1772                         oldstate = (GstState)voldstate->data[0].v_int;
1773                         newstate = (GstState)vnewstate->data[0].v_int;
1774                         pending = (GstState)vpending->data[0].v_int;
1775
1776                         debug_log("state changed [%s] : %s ---> %s     final : %s\n",
1777                                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
1778                                 gst_element_state_get_name( (GstState)oldstate ),
1779                                 gst_element_state_get_name( (GstState)newstate ),
1780                                 gst_element_state_get_name( (GstState)pending ) );
1781
1782                         if (oldstate == newstate)
1783                         {
1784                                 debug_log("pipeline reports state transition to old state");
1785                                 break;
1786                         }
1787
1788                         switch(newstate)
1789                         {
1790                                 case GST_STATE_VOID_PENDING:
1791                                 break;
1792
1793                                 case GST_STATE_NULL:
1794                                 break;
1795
1796                                 case GST_STATE_READY:
1797                                 break;
1798
1799                                 case GST_STATE_PAUSED:
1800                                 {
1801                                         gboolean prepare_async = FALSE;
1802                                         gboolean is_drm = FALSE;
1803
1804                                         if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
1805                                                 __mmplayer_configure_audio_callback(player);
1806
1807                                         if ( ! player->sent_bos && oldstate == GST_STATE_READY) // managed prepare async case
1808                                         {
1809                                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
1810                                                 debug_log("checking prepare mode for async transition - %d", prepare_async);
1811                                         }
1812
1813                                         if ( MMPLAYER_IS_STREAMING(player) || prepare_async )
1814                                         {
1815                                                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
1816
1817                                                 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
1818                                                 {
1819                                                         __mm_player_streaming_set_content_bitrate(player->streamer,
1820                                                                 player->total_maximum_bitrate, player->total_bitrate);
1821                                                 }
1822                                         }
1823
1824                                         /* NOTE : should consider streaming case */
1825                                         /* check if drm file */
1826                                         if ((player->pipeline->mainbin[MMPLAYER_M_SRC].gst) &&
1827                                                 (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm")))
1828                                         {
1829                                                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
1830
1831                                                 if (is_drm)
1832                                                 {
1833                                                         player->is_drm_file = TRUE;
1834                                                 }
1835                                         }
1836                                 }
1837                                 break;
1838
1839                                 case GST_STATE_PLAYING:
1840                                 {
1841 /* for audio tunning */
1842 #ifndef IS_SDK
1843                                         if (player->can_support_codec == 0x03) {
1844                                                 gint volume_type;
1845                                                 mm_attrs_get_int_by_name(player->attrs, "sound_volume_type", &volume_type);
1846                                                 volume_type |= MM_SOUND_VOLUME_GAIN_VIDEO;
1847                                                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "volumetype", volume_type, NULL);
1848                                         }
1849 #endif
1850                                         if ( MMPLAYER_IS_STREAMING(player) ) // managed prepare async case when buffering is completed
1851                                         {
1852                                                 // pending state should be reset oyherwise, it's still playing even though it's resumed after bufferging.
1853                                                 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
1854                                                         (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
1855                                                 {
1856                                                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING);
1857                                                 }
1858                                         }
1859
1860                                         if (player->gapless.stream_changed)
1861                                         {
1862                                                 _mmplayer_update_content_attrs(player, ATTR_ALL);
1863                                         }
1864
1865                                         if (player->doing_seek && async_done)
1866                                         {
1867                                                 player->doing_seek = FALSE;
1868                                                 async_done = FALSE;
1869                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
1870                                         }
1871                                 }
1872                                 break;
1873
1874                                 default:
1875                                 break;
1876                         }
1877                 }
1878                 break;
1879
1880                 case GST_MESSAGE_CLOCK_LOST:
1881                         {
1882                                 GstClock *clock = NULL;
1883                                 gboolean need_new_clock = FALSE;
1884
1885                                 gst_message_parse_clock_lost (msg, &clock);
1886                                 debug_log("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
1887
1888                                 if (!player->videodec_linked)
1889                                 {
1890                                         need_new_clock = TRUE;
1891                                 }
1892                                 else if (!player->ini.use_system_clock)
1893                                 {
1894                                         need_new_clock = TRUE;
1895                                 }
1896
1897                                 if (need_new_clock) {
1898                                         debug_log ("Provide clock is TRUE, do pause->resume\n");
1899                                         __gst_pause(player, FALSE);
1900                                         __gst_resume(player, FALSE);
1901                                 }
1902                         }
1903                         break;
1904
1905                 case GST_MESSAGE_NEW_CLOCK:
1906                         {
1907                                 GstClock *clock = NULL;
1908                                 gst_message_parse_new_clock (msg, &clock);
1909                                 debug_log("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
1910                         }
1911                         break;
1912
1913                 case GST_MESSAGE_ELEMENT:
1914                         {
1915                                 const gchar *structure_name;
1916                                 gint count = 0;
1917                                 MMHandleType attrs = 0;
1918
1919                                 attrs = MMPLAYER_GET_ATTRS(player);
1920                                 if ( !attrs )
1921                                 {
1922                                         debug_error("cannot get content attribute");
1923                                         ret = FALSE;
1924                                         break;
1925                                 }
1926
1927                                 if(gst_message_get_structure(msg) == NULL)
1928                                         break;
1929
1930                                 structure_name = gst_structure_get_name(gst_message_get_structure(msg));
1931                                 if(!strcmp(structure_name, "Language_list"))
1932                                 {
1933                                         const GValue *lang_list = NULL;
1934                                         lang_list = gst_structure_get_value (gst_message_get_structure(msg), "lang_list");
1935                                         if(lang_list != NULL)
1936                                         {
1937                                                 count = g_list_length((GList *)g_value_get_pointer (lang_list));
1938                                                 if (count > 1)
1939                                                         debug_log("Total audio tracks (from parser) = %d \n",count);
1940                                         }
1941                                 }
1942
1943                                 if (!strcmp (structure_name, "Ext_Sub_Language_List"))
1944                                 {
1945                                         const GValue *lang_list = NULL;
1946                                         MMPlayerLangStruct *temp = NULL;
1947
1948                                         lang_list = gst_structure_get_value (gst_message_get_structure(msg), "lang_list");
1949                                         if (lang_list != NULL)
1950                                         {
1951                                                 count = g_list_length ((GList *)g_value_get_pointer (lang_list));
1952                                                 if (count)
1953                                                 {
1954                                                         player->subtitle_language_list = (GList *)g_value_get_pointer (lang_list);
1955                                                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
1956                                                         if (mmf_attrs_commit (attrs))
1957                                                           debug_error("failed to commit.\n");
1958                                                         debug_log("Total subtitle tracks = %d \n", count);
1959                                                 }
1960                                                 while (count)
1961                                                 {
1962                                                         temp = g_list_nth_data (player->subtitle_language_list, count - 1);
1963                                                         debug_log ("value of lang_key is %s and lang_code is %s",
1964                                                                                 temp->language_key, temp->language_code);
1965                                                         count--;
1966                                                 }
1967                                         }
1968                                 }
1969
1970                                 /* custom message */
1971                                 if (!strcmp (structure_name, "audio_codec_not_supported")) {
1972                                         MMMessageParamType msg_param = {0,};
1973                                         msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
1974                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
1975                                 }
1976                         }
1977                         break;
1978
1979                 case GST_MESSAGE_DURATION_CHANGED:
1980                 {
1981                         debug_log("GST_MESSAGE_DURATION_CHANGED\n");
1982                         ret = __mmplayer_gst_handle_duration(player, msg);
1983                         if (!ret)
1984                         {
1985                                 debug_warning("failed to update duration");
1986                         }
1987                 }
1988
1989                 break;
1990
1991                 case GST_MESSAGE_ASYNC_START:
1992                 {
1993                         debug_log("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1994                 }
1995                 break;
1996
1997                 case GST_MESSAGE_ASYNC_DONE:
1998                 {
1999                         debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2000
2001                         /* we only handle messages from pipeline */
2002                         if( msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
2003                                 break;
2004
2005                         if (player->doing_seek)
2006                         {
2007                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2008                                 {
2009                                         player->doing_seek = FALSE;
2010                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2011                                 }
2012                                 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2013                                 {
2014                                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2015                                                 (player->streamer) &&
2016                                                 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
2017                                                 (player->streamer->is_buffering == FALSE))
2018                                         {
2019                                                 GstQuery *query = NULL;
2020                                                 gboolean busy = FALSE;
2021                                                 gint percent = 0;
2022
2023                                                 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer)
2024                                                 {
2025                                                         query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
2026                                                         if ( gst_element_query (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query ) )
2027                                                         {
2028                                                                 gst_query_parse_buffering_percent ( query, &busy, &percent);
2029                                                         }
2030                                                         gst_query_unref (query);
2031
2032                                                         debug_log("buffered percent(%s): %d\n",
2033                                                                 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
2034                                                 }
2035
2036                                                 if (percent >= 100)
2037                                                 {
2038                                                         player->streamer->is_buffering = FALSE;
2039                                                         __mmplayer_handle_buffering_message(player);
2040                                                 }
2041                                         }
2042
2043                                         async_done = TRUE;
2044                                 }
2045                         }
2046                 }
2047                 break;
2048
2049                 #if 0 /* delete unnecessary logs */
2050                 case GST_MESSAGE_REQUEST_STATE:         debug_log("GST_MESSAGE_REQUEST_STATE\n"); break;
2051                 case GST_MESSAGE_STEP_START:            debug_log("GST_MESSAGE_STEP_START\n"); break;
2052                 case GST_MESSAGE_QOS:                           debug_log("GST_MESSAGE_QOS\n"); break;
2053                 case GST_MESSAGE_PROGRESS:                      debug_log("GST_MESSAGE_PROGRESS\n"); break;
2054                 case GST_MESSAGE_ANY:                           debug_log("GST_MESSAGE_ANY\n"); break;
2055                 case GST_MESSAGE_INFO:                          debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2056                 case GST_MESSAGE_STATE_DIRTY:           debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2057                 case GST_MESSAGE_STEP_DONE:                     debug_log("GST_MESSAGE_STEP_DONE\n"); break;
2058                 case GST_MESSAGE_CLOCK_PROVIDE:         debug_log("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
2059                 case GST_MESSAGE_STRUCTURE_CHANGE:      debug_log("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
2060                 case GST_MESSAGE_STREAM_STATUS:         debug_log("GST_MESSAGE_STREAM_STATUS\n"); break;
2061                 case GST_MESSAGE_APPLICATION:           debug_log("GST_MESSAGE_APPLICATION\n"); break;
2062                 case GST_MESSAGE_SEGMENT_START:         debug_log("GST_MESSAGE_SEGMENT_START\n"); break;
2063                 case GST_MESSAGE_SEGMENT_DONE:          debug_log("GST_MESSAGE_SEGMENT_DONE\n"); break;
2064                 case GST_MESSAGE_LATENCY:                               debug_log("GST_MESSAGE_LATENCY\n"); break;
2065                 #endif
2066
2067                 default:
2068                 break;
2069         }
2070
2071         /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
2072          * gst_element_post_message api takes ownership of the message.
2073          */
2074         //gst_message_unref( msg );
2075
2076         return ret;
2077 }
2078
2079 static gboolean
2080 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
2081 {
2082         gint64 bytes = 0;
2083
2084         MMPLAYER_FENTER();
2085
2086         return_val_if_fail(player, FALSE);
2087         return_val_if_fail(msg, FALSE);
2088
2089         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2090                 (msg->src) && (msg->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst))
2091         {
2092                 debug_log("msg src : [%s]", GST_ELEMENT_NAME(GST_ELEMENT_CAST(msg->src)));
2093
2094                 if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes))
2095                 {
2096                         debug_log("data total size of http content: %lld", bytes);
2097                         player->http_content_size = bytes;
2098                 }
2099         }
2100         else
2101         {
2102                 /* handling audio clip which has vbr. means duration is keep changing */
2103                 _mmplayer_update_content_attrs (player, ATTR_DURATION );
2104         }
2105
2106         MMPLAYER_FLEAVE();
2107
2108         return TRUE;
2109 }
2110
2111
2112 static gboolean
2113 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg) // @
2114 {
2115
2116 /* macro for better code readability */
2117 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
2118 if (gst_tag_list_get_string(tag_list, gsttag, &string)) \
2119 {\
2120         if (string != NULL)\
2121         {\
2122                 secure_debug_log ( "update tag string : %s\n", string); \
2123                 mm_attrs_set_string_by_name(attribute, playertag, string); \
2124                 g_free(string);\
2125                 string = NULL;\
2126         }\
2127 }
2128
2129 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
2130 GstSample *sample = NULL;\
2131 if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample))\
2132 {\
2133         GstMapInfo info = GST_MAP_INFO_INIT;\
2134         buffer = gst_sample_get_buffer(sample);\
2135         if (!gst_buffer_map(buffer, &info, GST_MAP_READ)){\
2136                 debug_log("failed to get image data from tag");\
2137                 return FALSE;\
2138         }\
2139         secure_debug_log ( "update album cover data : %p, size : %d\n", info.data, info.size);\
2140         MMPLAYER_FREEIF(player->album_art); \
2141         player->album_art = (gchar *)g_malloc(info.size); \
2142         if (player->album_art) \
2143         { \
2144                 memcpy(player->album_art, info.data, info.size); \
2145                 mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, info.size); \
2146                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) \
2147                 { \
2148                         msg_param.data = (void *)player->album_art; \
2149                         msg_param.size = info.size; \
2150                         MMPLAYER_POST_MSG (player, MM_MESSAGE_IMAGE_BUFFER, &msg_param); \
2151                         secure_debug_log ( "post message image buffer data : %p, size : %d\n", info.data, info.size); \
2152                 } \
2153         } \
2154         gst_buffer_unmap(buffer, &info); \
2155 }
2156
2157 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
2158 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint))\
2159 {\
2160         if(v_uint)\
2161         {\
2162                 if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) \
2163                 {\
2164                         if (player->updated_bitrate_count == 0) \
2165                                 mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
2166                         if (player->updated_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2167                         {\
2168                                 player->bitrate[player->updated_bitrate_count] = v_uint;\
2169                                 player->total_bitrate += player->bitrate[player->updated_maximum_bitrate_count]; \
2170                                 player->updated_bitrate_count++; \
2171                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate);\
2172                                 secure_debug_log ( "update bitrate %d[bps] of stream #%d.\n", v_uint, player->updated_bitrate_count);\
2173                         }\
2174                 }\
2175                 else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) \
2176                 {\
2177                         if (player->updated_maximum_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2178                         {\
2179                                 player->maximum_bitrate[player->updated_maximum_bitrate_count] = v_uint;\
2180                                 player->total_maximum_bitrate += player->maximum_bitrate[player->updated_maximum_bitrate_count]; \
2181                                 player->updated_maximum_bitrate_count++; \
2182                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate); \
2183                                 secure_debug_log ( "update maximum bitrate %d[bps] of stream #%d\n", v_uint, player->updated_maximum_bitrate_count);\
2184                         }\
2185                 }\
2186                 else\
2187                 {\
2188                         mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
2189                 }\
2190                 v_uint = 0;\
2191         }\
2192 }
2193
2194 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
2195 if (gst_tag_list_get_date(tag_list, gsttag, &date))\
2196 {\
2197         if (date != NULL)\
2198         {\
2199                 string = g_strdup_printf("%d", g_date_get_year(date));\
2200                 mm_attrs_set_string_by_name(attribute, playertag, string);\
2201                 secure_debug_log ( "metainfo year : %s\n", string);\
2202                 MMPLAYER_FREEIF(string);\
2203                 g_date_free(date);\
2204         }\
2205 }
2206
2207 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
2208 if(gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64))\
2209 {\
2210         if(v_uint64)\
2211         {\
2212                 /* FIXIT : don't know how to store date */\
2213                 g_assert(1);\
2214                 v_uint64 = 0;\
2215         }\
2216 }
2217
2218 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
2219 if(gst_tag_list_get_double(tag_list, gsttag, &v_double))\
2220 {\
2221         if(v_double)\
2222         {\
2223                 /* FIXIT : don't know how to store date */\
2224                 g_assert(1);\
2225                 v_double = 0;\
2226         }\
2227 }
2228
2229         /* function start */
2230         GstTagList* tag_list = NULL;
2231
2232         MMHandleType attrs = 0;
2233
2234         char *string = NULL;
2235         guint v_uint = 0;
2236         GDate *date = NULL;
2237         /* album cover */
2238         GstBuffer *buffer = NULL;
2239         gint index = 0;
2240         MMMessageParamType msg_param = {0, };
2241
2242         /* currently not used. but those are needed for above macro */
2243         //guint64 v_uint64 = 0;
2244         //gdouble v_double = 0;
2245
2246         return_val_if_fail( player && msg, FALSE );
2247
2248         attrs = MMPLAYER_GET_ATTRS(player);
2249
2250         return_val_if_fail( attrs, FALSE );
2251
2252         /* get tag list from gst message */
2253         gst_message_parse_tag(msg, &tag_list);
2254
2255         /* store tags to player attributes */
2256         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
2257         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
2258         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
2259         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
2260         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
2261         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
2262         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
2263         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
2264         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
2265         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
2266         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
2267         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
2268         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
2269         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
2270         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
2271         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
2272         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
2273         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
2274         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
2275         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
2276         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
2277         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
2278         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
2279         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
2280         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
2281         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
2282         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
2283         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
2284         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
2285         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
2286         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
2287         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
2288         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
2289         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
2290         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
2291         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
2292         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
2293         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
2294         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
2295         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
2296         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
2297         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
2298         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
2299         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
2300         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
2301         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, attrs, "content_video_orientation");
2302
2303         if ( mmf_attrs_commit ( attrs ) )
2304                 debug_error("failed to commit.\n");
2305
2306         gst_tag_list_free(tag_list);
2307
2308         return TRUE;
2309 }
2310
2311 static void
2312 __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data)  // @
2313 {
2314         mm_player_t* player = (mm_player_t*) data;
2315
2316         MMPLAYER_FENTER();
2317
2318         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2319           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2320           * num_dynamic_pad. and this is no-more-pad situation which means mo more pad will be added.
2321           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2322
2323           * [1] audio and video will be dumped with filesink.
2324           * [2] autoplugging is done by just using pad caps.
2325           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
2326           * and the video will be dumped via filesink.
2327           */
2328         if ( player->num_dynamic_pad == 0 )
2329         {
2330                 debug_log("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
2331
2332                 if ( ! __mmplayer_gst_remove_fakesink( player,
2333                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
2334                 {
2335                         /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
2336                          * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
2337                          * source element are not same. To overcome this situation, this function will called
2338                          * several places and several times. Therefore, this is not an error case.
2339                          */
2340                         return;
2341                 }
2342         }
2343
2344         /* create dot before error-return. for debugging */
2345         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-no-more-pad" );
2346
2347         player->no_more_pad = TRUE;
2348
2349         MMPLAYER_FLEAVE();
2350 }
2351
2352 static gboolean
2353 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink) // @
2354 {
2355         GstElement* parent = NULL;
2356
2357         return_val_if_fail(player && player->pipeline, FALSE);
2358
2359         /* if we have no fakesink. this meas we are using decodebin which doesn'
2360         t need to add extra fakesink */
2361         return_val_if_fail(fakesink, TRUE);
2362
2363         /* lock */
2364         g_mutex_lock(&player->fsink_lock );
2365
2366         if ( ! fakesink->gst )
2367         {
2368                 goto ERROR;
2369         }
2370
2371         /* get parent of fakesink */
2372         parent = (GstElement*)gst_object_get_parent( (GstObject*)fakesink->gst );
2373         if ( ! parent )
2374         {
2375                 debug_log("fakesink already removed\n");
2376                 goto ERROR;
2377         }
2378
2379         gst_element_set_locked_state( fakesink->gst, TRUE );
2380
2381         /* setting the state to NULL never returns async
2382          * so no need to wait for completion of state transiton
2383          */
2384         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (fakesink->gst, GST_STATE_NULL) )
2385         {
2386                 debug_error("fakesink state change failure!\n");
2387
2388                 /* FIXIT : should I return here? or try to proceed to next? */
2389                 /* return FALSE; */
2390         }
2391
2392         /* remove fakesink from it's parent */
2393         if ( ! gst_bin_remove( GST_BIN( parent ), fakesink->gst ) )
2394         {
2395                 debug_error("failed to remove fakesink\n");
2396
2397                 gst_object_unref( parent );
2398
2399                 goto ERROR;
2400         }
2401
2402         gst_object_unref( parent );
2403
2404         debug_log("state-holder removed\n");
2405
2406         gst_element_set_locked_state( fakesink->gst, FALSE );
2407
2408         g_mutex_unlock( &player->fsink_lock );
2409         return TRUE;
2410
2411 ERROR:
2412         if ( fakesink->gst )
2413         {
2414                 gst_element_set_locked_state( fakesink->gst, FALSE );
2415         }
2416
2417         g_mutex_unlock( &player->fsink_lock );
2418         return FALSE;
2419 }
2420
2421
2422 static void
2423 __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2424 {
2425         GstPad *sinkpad = NULL;
2426         GstCaps* caps = NULL;
2427         GstElement* new_element = NULL;
2428         GstStructure* str = NULL;
2429         const gchar* name = NULL;
2430
2431         mm_player_t* player = (mm_player_t*) data;
2432
2433         MMPLAYER_FENTER();
2434
2435         return_if_fail( element && pad );
2436         return_if_fail( player &&
2437                                         player->pipeline &&
2438                                         player->pipeline->mainbin );
2439
2440
2441         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2442          * num_dynamic_pad will decreased after creating a sinkbin.
2443          */
2444         player->num_dynamic_pad++;
2445         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2446
2447         caps = gst_pad_query_caps( pad, NULL );
2448
2449         MMPLAYER_CHECK_NULL( caps );
2450
2451         /* clear  previous result*/
2452         player->have_dynamic_pad = FALSE;
2453
2454         str = gst_caps_get_structure(caps, 0);
2455
2456         if ( ! str )
2457         {
2458                 debug_error ("cannot get structure from caps.\n");
2459                 goto ERROR;
2460         }
2461
2462         name = gst_structure_get_name (str);
2463         if ( ! name )
2464         {
2465                 debug_error ("cannot get mimetype from structure.\n");
2466                 goto ERROR;
2467         }
2468
2469         if (strstr(name, "video"))
2470         {
2471                 gint stype = 0;
2472                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
2473
2474                 if (stype == MM_DISPLAY_SURFACE_NULL)
2475                 {
2476                         if (player->v_stream_caps)
2477                         {
2478                                 gst_caps_unref(player->v_stream_caps);
2479                                 player->v_stream_caps = NULL;
2480                         }
2481
2482                         new_element = gst_element_factory_make("fakesink", NULL);
2483                         player->num_dynamic_pad--;
2484                         goto NEW_ELEMENT;
2485                 }
2486         }
2487
2488         /* clear  previous result*/
2489         player->have_dynamic_pad = FALSE;
2490
2491         if ( !__mmplayer_try_to_plug_decodebin(player, pad, caps))
2492         {
2493                 debug_error("failed to autoplug for caps");
2494                 goto ERROR;
2495         }
2496
2497         /* check if there's dynamic pad*/
2498         if( player->have_dynamic_pad )
2499         {
2500                 debug_error("using pad caps assums there's no dynamic pad !\n");
2501                 goto ERROR;
2502         }
2503
2504         gst_caps_unref( caps );
2505         caps = NULL;
2506
2507 NEW_ELEMENT:
2508
2509         /* excute new_element if created*/
2510         if ( new_element )
2511         {
2512                 debug_log("adding new element to pipeline\n");
2513
2514                 /* set state to READY before add to bin */
2515                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2516
2517                 /* add new element to the pipeline */
2518                 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2519                 {
2520                         debug_error("failed to add autoplug element to bin\n");
2521                         goto ERROR;
2522                 }
2523
2524                 /* get pad from element */
2525                 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2526                 if ( !sinkpad )
2527                 {
2528                         debug_error("failed to get sinkpad from autoplug element\n");
2529                         goto ERROR;
2530                 }
2531
2532                 /* link it */
2533                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2534                 {
2535                         debug_error("failed to link autoplug element\n");
2536                         goto ERROR;
2537                 }
2538
2539                 gst_object_unref (sinkpad);
2540                 sinkpad = NULL;
2541
2542                 /* run. setting PLAYING here since streamming source is live source */
2543                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2544         }
2545
2546         MMPLAYER_FLEAVE();
2547
2548         return;
2549
2550 STATE_CHANGE_FAILED:
2551 ERROR:
2552         /* FIXIT : take care if new_element has already added to pipeline */
2553         if ( new_element )
2554                 gst_object_unref(GST_OBJECT(new_element));
2555
2556         if ( sinkpad )
2557                 gst_object_unref(GST_OBJECT(sinkpad));
2558
2559         if ( caps )
2560                 gst_object_unref(GST_OBJECT(caps));
2561
2562         /* FIXIT : how to inform this error to MSL ????? */
2563         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2564          * then post an error to application
2565          */
2566 }
2567
2568
2569
2570 /* FIXIT : check indent */
2571 #if 0
2572 static void
2573 __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2574 {
2575   GstPad *sinkpad = NULL;
2576   GstCaps* caps = NULL;
2577   GstElement* new_element = NULL;
2578   enum MainElementID element_id = MMPLAYER_M_NUM;
2579
2580   mm_player_t* player = (mm_player_t*) data;
2581
2582   MMPLAYER_FENTER();
2583
2584   return_if_fail( element && pad );
2585   return_if_fail(  player &&
2586           player->pipeline &&
2587           player->pipeline->mainbin );
2588
2589   debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2590
2591   {
2592     debug_log("using pad caps to autopluging instead of doing typefind\n");
2593     caps = gst_pad_query_caps( pad );
2594     MMPLAYER_CHECK_NULL( caps );
2595     /* clear  previous result*/
2596     player->have_dynamic_pad = FALSE;
2597     new_element = gst_element_factory_make("rtpmp2tdepay", "wfd_rtp_depay");
2598     if ( !new_element )
2599     {
2600       debug_error ( "failed to create wfd rtp depay element\n" );
2601       goto ERROR;
2602     }
2603     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2604     /* add new element to the pipeline */
2605     if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2606     {
2607       debug_log("failed to add autoplug element to bin\n");
2608       goto ERROR;
2609     }
2610     /* get pad from element */
2611     sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2612     if ( !sinkpad )
2613     {
2614       debug_log("failed to get sinkpad from autoplug element\n");
2615       goto ERROR;
2616     }
2617     /* link it */
2618     if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2619     {
2620       debug_log("failed to link autoplug element\n");
2621       goto ERROR;
2622     }
2623     gst_object_unref (sinkpad);
2624     sinkpad = NULL;
2625     pad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "src" );
2626     caps = gst_pad_query_caps( pad );
2627     MMPLAYER_CHECK_NULL( caps );
2628     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2629     /* create typefind */
2630     new_element = gst_element_factory_make( "typefind", NULL );
2631     if ( ! new_element )
2632     {
2633       debug_log("failed to create typefind\n");
2634       goto ERROR;
2635     }
2636
2637     MMPLAYER_SIGNAL_CONNECT(   player,
2638                 G_OBJECT(new_element),
2639                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2640                 "have-type",
2641                 G_CALLBACK(__mmplayer_typefind_have_type),
2642                 (gpointer)player);
2643
2644     player->have_dynamic_pad = FALSE;
2645   }
2646
2647   /* excute new_element if created*/
2648   if ( new_element )
2649   {
2650     debug_log("adding new element to pipeline\n");
2651
2652     /* set state to READY before add to bin */
2653     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2654
2655     /* add new element to the pipeline */
2656     if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2657     {
2658       debug_log("failed to add autoplug element to bin\n");
2659       goto ERROR;
2660     }
2661
2662     /* get pad from element */
2663     sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2664     if ( !sinkpad )
2665     {
2666       debug_log("failed to get sinkpad from autoplug element\n");
2667       goto ERROR;
2668     }
2669
2670     /* link it */
2671     if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2672     {
2673       debug_log("failed to link autoplug element\n");
2674       goto ERROR;
2675     }
2676
2677     gst_object_unref (sinkpad);
2678     sinkpad = NULL;
2679
2680     /* run. setting PLAYING here since streamming source is live source */
2681     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2682   }
2683
2684   /* store handle to futher manipulation */
2685   player->pipeline->mainbin[element_id].id = element_id;
2686   player->pipeline->mainbin[element_id].gst = new_element;
2687
2688   MMPLAYER_FLEAVE();
2689
2690   return;
2691
2692 STATE_CHANGE_FAILED:
2693 ERROR:
2694   /* FIXIT : take care if new_element has already added to pipeline */
2695   if ( new_element )
2696     gst_object_unref(GST_OBJECT(new_element));
2697
2698   if ( sinkpad )
2699     gst_object_unref(GST_OBJECT(sinkpad));
2700
2701   if ( caps )
2702     gst_object_unref(GST_OBJECT(caps));
2703
2704   /* FIXIT : how to inform this error to MSL ????? */
2705   /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2706    * then post an error to application
2707    */
2708 }
2709 #endif
2710
2711 static GstPadProbeReturn
2712 __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
2713 {
2714         debug_log ("pad(%s:%s) is blocked", GST_DEBUG_PAD_NAME(pad));
2715         return GST_PAD_PROBE_OK;
2716 }
2717
2718 static GstPadProbeReturn
2719 __mmplayer_audio_data_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
2720 {
2721         mm_player_t* player = (mm_player_t*) u_data;
2722         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
2723
2724         /* TO_CHECK: performance */
2725         return_val_if_fail (player && GST_IS_BUFFER(pad_buffer), GST_PAD_PROBE_OK);
2726
2727         if (GST_BUFFER_PTS_IS_VALID(pad_buffer) && GST_BUFFER_DURATION_IS_VALID(pad_buffer))
2728                 player->gapless.next_pts = GST_BUFFER_PTS(pad_buffer) + GST_BUFFER_DURATION(pad_buffer);
2729
2730         return GST_PAD_PROBE_OK;
2731 }
2732
2733 static GstPadProbeReturn
2734 __mmplayer_gst_selector_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
2735 {
2736         GstPadProbeReturn ret = GST_PAD_PROBE_OK;
2737         GstEvent *event = GST_PAD_PROBE_INFO_DATA (info);
2738         mm_player_t* player = (mm_player_t*)data;
2739
2740         switch (GST_EVENT_TYPE (event)) {
2741                 case GST_EVENT_STREAM_START:
2742                 break;
2743                 case GST_EVENT_SEGMENT: {
2744                         GstSegment segment;
2745                         GstEvent *tmpev;
2746
2747                         if (!player->gapless.running)
2748                                 break;
2749
2750                         if (player->gapless.stream_changed) {
2751                                 player->gapless.start_time += player->gapless.next_pts;
2752                                 player->gapless.stream_changed = FALSE;
2753                         }
2754
2755                         debug_log ("event: %" GST_PTR_FORMAT, event);
2756                         gst_event_copy_segment (event, &segment);
2757
2758                         if (segment.format == GST_FORMAT_TIME)
2759                         {
2760                                 segment.base = player->gapless.start_time;
2761                                 debug_log ("base of segment: %" GST_TIME_FORMAT, GST_TIME_ARGS (segment.base));
2762
2763                                 tmpev = gst_event_new_segment (&segment);
2764                                 gst_event_set_seqnum (tmpev, gst_event_get_seqnum (event));
2765                                 gst_event_unref (event);
2766                                 GST_PAD_PROBE_INFO_DATA(info) = tmpev;
2767                         }
2768                         break;
2769                 }
2770                 default:
2771                 break;
2772         }
2773         return ret;
2774 }
2775
2776 static void
2777 __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data)
2778 {
2779         mm_player_t* player = NULL;
2780         GstElement* pipeline = NULL;
2781         GstElement* selector = NULL;
2782         GstElement* fakesink = NULL;
2783         GstCaps* caps = NULL;
2784         GstStructure* str = NULL;
2785         const gchar* name = NULL;
2786         GstPad* sinkpad = NULL;
2787         GstPad* srcpad = NULL;
2788         gboolean first_track = FALSE;
2789
2790         enum MainElementID elemId = MMPLAYER_M_NUM;
2791         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2792
2793         /* check handles */
2794         player = (mm_player_t*)data;
2795
2796         return_if_fail (elem && pad);
2797         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
2798
2799         //debug_log ("pad-added signal handling\n");
2800
2801         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
2802
2803         /* get mimetype from caps */
2804         caps = gst_pad_query_caps (pad, NULL);
2805         if ( !caps )
2806         {
2807                 debug_error ("cannot get caps from pad.\n");
2808                 goto ERROR;
2809         }
2810
2811         str = gst_caps_get_structure (caps, 0);
2812         if ( ! str )
2813         {
2814                 debug_error ("cannot get structure from caps.\n");
2815                 goto ERROR;
2816         }
2817
2818         name = gst_structure_get_name (str);
2819         if ( ! name )
2820         {
2821                 debug_error ("cannot get mimetype from structure.\n");
2822                 goto ERROR;
2823         }
2824
2825         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
2826         //debug_log ("detected mimetype : %s\n", name);
2827
2828         if (strstr(name, "video"))
2829         {
2830                 gint stype = 0;
2831                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
2832
2833                 /* don't make video because of not required, and not support multiple track */
2834                 if (stype == MM_DISPLAY_SURFACE_NULL)
2835                 {
2836                         debug_log ("no video sink by null surface or multiple track");
2837                         gchar *caps_str = gst_caps_to_string(caps);
2838                         if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
2839                         {
2840                                 player->set_mode.video_zc = TRUE;
2841                         }
2842                         MMPLAYER_FREEIF( caps_str );
2843
2844                         if (player->v_stream_caps)
2845                         {
2846                                 gst_caps_unref(player->v_stream_caps);
2847                                 player->v_stream_caps = NULL;
2848                         }
2849
2850                         debug_log ("create fakesink instead of videobin");
2851
2852                         /* fake sink */
2853                         fakesink = gst_element_factory_make ("fakesink", NULL);
2854                         if (fakesink == NULL)
2855                         {
2856                                 debug_error ("ERROR : fakesink create error\n");
2857                                 goto ERROR;
2858                         }
2859
2860                         player->video_fakesink = fakesink;
2861
2862                         gst_bin_add (GST_BIN(pipeline), fakesink);
2863
2864                         // link
2865                         sinkpad = gst_element_get_static_pad (fakesink, "sink");
2866
2867                         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
2868                         {
2869                                 debug_warning ("failed to link fakesink\n");
2870                                 gst_object_unref (GST_OBJECT(fakesink));
2871                                 goto ERROR;
2872                         }
2873
2874                         if (player->set_mode.media_packet_video_stream)
2875                                 player->video_cb_probe_id = gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER, __mmplayer_video_stream_probe, player, NULL);
2876
2877                         g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
2878                         g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
2879                         gst_element_set_state (fakesink, GST_STATE_PAUSED);
2880
2881                         goto DONE;
2882                 }
2883                 __mmplayer_gst_decode_callback (elem, pad, player);
2884         }
2885         else
2886         {
2887                 if (strstr(name, "audio"))
2888                 {
2889                         gint samplerate = 0;
2890                         gint channels = 0;
2891
2892                         if (MMPLAYER_IS_ES_BUFF_SRC(player))
2893                         {
2894                                 __mmplayer_gst_decode_callback (elem, pad, player);
2895                                 return;
2896                         }
2897
2898                         debug_log ("audio selector \n");
2899                         elemId = MMPLAYER_M_A_INPUT_SELECTOR;
2900                         stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2901
2902                         gst_structure_get_int (str, "rate", &samplerate);
2903                         gst_structure_get_int (str, "channels", &channels);
2904
2905                         if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
2906                                 /* fake sink */
2907                                 fakesink = gst_element_factory_make ("fakesink", NULL);
2908                                 if (fakesink == NULL)
2909                                 {
2910                                         debug_error ("ERROR : fakesink create error\n");
2911                                         goto ERROR;
2912                                 }
2913
2914                                 gst_bin_add (GST_BIN(pipeline), fakesink);
2915
2916                                 /* link */
2917                                 sinkpad = gst_element_get_static_pad (fakesink, "sink");
2918
2919                                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
2920                                 {
2921                                         debug_warning ("failed to link fakesink\n");
2922                                         gst_object_unref (GST_OBJECT(fakesink));
2923                                         goto ERROR;
2924                                 }
2925
2926                                 g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
2927                                 g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
2928                                 gst_element_set_state (fakesink, GST_STATE_PAUSED);
2929
2930                                 goto DONE;
2931                         }
2932                 }
2933                 else if (strstr(name, "text"))
2934                 {
2935                         debug_log ("text selector \n");
2936                         elemId = MMPLAYER_M_T_INPUT_SELECTOR;
2937                         stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
2938                 }
2939                 else
2940                 {
2941                         debug_error ("wrong elem id \n");
2942                         goto ERROR;
2943                 }
2944         }
2945
2946         if(strstr(name, "video"))
2947                 return;
2948
2949         selector = player->pipeline->mainbin[elemId].gst;
2950
2951         if (selector == NULL)
2952         {
2953                 selector = gst_element_factory_make ("input-selector", NULL);
2954                 debug_log ("Creating input-selector\n");
2955                 if (selector == NULL)
2956                 {
2957                         debug_error ("ERROR : input-selector create error\n");
2958                         goto ERROR;
2959                 }
2960                 g_object_set (selector, "sync-streams", TRUE, NULL);
2961
2962                 player->pipeline->mainbin[elemId].id = elemId;
2963                 player->pipeline->mainbin[elemId].gst = selector;
2964
2965                 first_track = TRUE;
2966                 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK;      // default
2967
2968                 srcpad = gst_element_get_static_pad (selector, "src");
2969
2970                 debug_log ("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
2971                 player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
2972                         __mmplayer_gst_selector_blocked, NULL, NULL);
2973                 player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
2974                         __mmplayer_gst_selector_event_probe, player, NULL);
2975
2976                 gst_element_set_state (selector, GST_STATE_PAUSED);
2977                 gst_bin_add (GST_BIN(pipeline), selector);
2978         }
2979         else
2980         {
2981                 debug_log ("input-selector is already created.\n");
2982                 selector = player->pipeline->mainbin[elemId].gst;
2983         }
2984
2985         // link
2986         debug_log ("Calling request pad with selector %p \n", selector);
2987         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
2988
2989         debug_log ("got pad %s:%s from selector", GST_DEBUG_PAD_NAME (sinkpad));
2990
2991         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
2992         {
2993                 debug_warning ("failed to link selector\n");
2994                 gst_object_unref (GST_OBJECT(selector));
2995                 goto ERROR;
2996         }
2997
2998         if (first_track)
2999         {
3000                 debug_log ("this is first track --> active track \n");
3001                 g_object_set (selector, "active-pad", sinkpad, NULL);
3002         }
3003
3004         _mmplayer_track_update_info(player, stream_type, sinkpad);
3005
3006
3007 DONE:
3008 ERROR:
3009
3010         if (caps)
3011         {
3012                 gst_caps_unref (caps);
3013         }
3014
3015         if (sinkpad)
3016         {
3017                 gst_object_unref (GST_OBJECT(sinkpad));
3018                 sinkpad = NULL;
3019         }
3020
3021         if (srcpad)
3022         {
3023                 gst_object_unref (GST_OBJECT(srcpad));
3024                 srcpad = NULL;
3025         }
3026
3027         return;
3028 }
3029
3030 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
3031 {
3032         GstPad* srcpad = NULL;
3033         MMHandleType attrs = 0;
3034         gint active_index = 0;
3035
3036         // [link] input-selector :: textbin
3037         srcpad = gst_element_get_static_pad (text_selector, "src");
3038         if (!srcpad)
3039         {
3040                 debug_error("failed to get srcpad from selector\n");
3041                 return;
3042         }
3043
3044         debug_log ("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
3045
3046         active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
3047         if ((active_index != DEFAULT_TRACK) &&
3048                 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE))
3049         {
3050                 debug_warning("failed to change text track\n");
3051                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
3052         }
3053
3054         player->no_more_pad = TRUE;
3055         __mmplayer_gst_decode_callback (text_selector, srcpad, player);
3056
3057         debug_log ("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3058         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id)
3059         {
3060                 gst_pad_remove_probe (srcpad, player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id);
3061                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id = 0;
3062         }
3063
3064         debug_log("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3065
3066         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
3067                 player->has_closed_caption = TRUE;
3068
3069         attrs = MMPLAYER_GET_ATTRS(player);
3070         if ( attrs )
3071         {
3072                 mm_attrs_set_int_by_name(attrs, "content_text_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3073                 if (mmf_attrs_commit (attrs))
3074                         debug_error("failed to commit.\n");
3075         }
3076         else
3077         {
3078                 debug_error("cannot get content attribute");
3079         }
3080
3081         if (srcpad)
3082         {
3083                 gst_object_unref ( GST_OBJECT(srcpad) );
3084                 srcpad = NULL;
3085         }
3086 }
3087
3088 int _mmplayer_gst_set_audio_channel(MMHandleType hplayer, MMPlayerAudioChannel ch_idx)
3089 {
3090         int result = MM_ERROR_NONE;
3091
3092         mm_player_t* player = (mm_player_t*)hplayer;
3093         MMPlayerGstElement* mainbin = NULL;
3094         gchar* change_pad_name = NULL;
3095         GstPad* sinkpad = NULL;
3096         GstCaps* caps = NULL;
3097
3098         MMPLAYER_FENTER();
3099
3100         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3101
3102         debug_log ("Change Audio mode to %d\n", ch_idx);
3103         player->use_deinterleave = TRUE;
3104
3105         if ((!player->pipeline) || (!player->pipeline->mainbin))
3106         {
3107                 debug_log ("pre setting : %d\n", ch_idx);
3108
3109                 player->audio_mode.active_pad_index = ch_idx;
3110                 return result;
3111         }
3112
3113         mainbin = player->pipeline->mainbin;
3114
3115         if (mainbin[MMPLAYER_M_A_SELECTOR].gst == NULL)
3116         {
3117                 if (player->max_audio_channels < 2)
3118                 {
3119                         debug_log ("mono channel track only\n");
3120                         return result;
3121                 }
3122
3123                 debug_warning ("selector doesn't exist\n");
3124                 return result;  /* keep playing */
3125         }
3126
3127         debug_log ("total_ch_num : %d\n", player->audio_mode.total_track_num);
3128
3129         if (player->audio_mode.total_track_num < 2)
3130         {
3131                 debug_warning ("there is no another audio path\n");
3132                 return result;  /* keep playing */
3133         }
3134
3135         if ((ch_idx < 0) || (ch_idx >= player->audio_mode.total_track_num))
3136         {
3137                 debug_warning ("Not a proper ch_idx : %d \n", ch_idx);
3138                 return result;  /* keep playing */
3139         }
3140
3141         /*To get the new pad from the selector*/
3142         change_pad_name = g_strdup_printf ("sink%d", ch_idx);
3143         if (change_pad_name == NULL)
3144         {
3145                 debug_warning ("Pad does not exists\n");
3146                 goto ERROR;     /* keep playing */
3147         }
3148
3149         debug_log ("new active pad name: %s\n", change_pad_name);
3150
3151         sinkpad = gst_element_get_static_pad (mainbin[MMPLAYER_M_A_SELECTOR].gst, change_pad_name);
3152         if (sinkpad == NULL)
3153         {
3154                 //result = MM_ERROR_PLAYER_INTERNAL;
3155                 goto ERROR;     /* keep playing */
3156         }
3157
3158         debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3159         g_object_set (mainbin[MMPLAYER_M_A_SELECTOR].gst, "active-pad", sinkpad, NULL);
3160
3161         caps = gst_pad_get_current_caps(sinkpad);
3162         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3163
3164         __mmplayer_set_audio_attrs (player, caps);
3165         player->audio_mode.active_pad_index = ch_idx;
3166
3167 ERROR:
3168
3169         if (sinkpad)
3170                 gst_object_unref (sinkpad);
3171
3172         MMPLAYER_FREEIF(change_pad_name);
3173
3174         MMPLAYER_FLEAVE();
3175         return result;
3176 }
3177
3178
3179
3180 static void
3181 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
3182 {
3183         mm_player_t* player = (mm_player_t*)data;
3184         GstElement* selector = NULL;
3185         GstElement* queue = NULL;
3186
3187         GstPad* srcpad = NULL;
3188         GstPad* sinkpad = NULL;
3189         gchar* caps_str= NULL;
3190
3191         MMPLAYER_FENTER();
3192         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3193
3194         caps_str = gst_caps_to_string(gst_pad_get_current_caps(pad));
3195         debug_log ("deinterleave new caps : %s\n", caps_str);
3196         MMPLAYER_FREEIF(caps_str);
3197
3198         if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL)
3199         {
3200                 debug_error ("ERROR : queue create error\n");
3201                 goto ERROR;
3202         }
3203
3204         g_object_set(G_OBJECT(queue),
3205                                 "max-size-buffers", 10,
3206                                 "max-size-bytes", 0,
3207                                 "max-size-time", (guint64)0,
3208                                 NULL);
3209
3210         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3211
3212         if (!selector)
3213         {
3214                 debug_error("there is no audio channel selector.\n");
3215                 goto ERROR;
3216         }
3217
3218         srcpad = gst_element_get_static_pad (queue, "src");
3219         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3220
3221         debug_log ("link (%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
3222
3223         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3224         {
3225                 debug_warning ("failed to link deinterleave - selector\n");
3226                 goto ERROR;
3227         }
3228
3229         gst_element_set_state (queue, GST_STATE_PAUSED);
3230         player->audio_mode.total_track_num++;
3231
3232 ERROR:
3233
3234         if (srcpad)
3235         {
3236                 gst_object_unref ( GST_OBJECT(srcpad) );
3237                 srcpad = NULL;
3238         }
3239
3240         if (sinkpad)
3241         {
3242                 gst_object_unref ( GST_OBJECT(sinkpad) );
3243                 sinkpad = NULL;
3244         }
3245
3246         MMPLAYER_FLEAVE();
3247         return;
3248 }
3249
3250 static void
3251 __mmplayer_gst_deinterleave_no_more_pads (GstElement *elem, gpointer data)
3252 {
3253         mm_player_t* player = NULL;
3254         GstElement* selector = NULL;
3255         GstPad* sinkpad = NULL;
3256         gint active_index = 0;
3257         gchar* change_pad_name = NULL;
3258         GstCaps* caps = NULL;   // no need to unref
3259
3260         MMPLAYER_FENTER();
3261         player = (mm_player_t*) data;
3262
3263         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3264
3265         if (!selector)
3266         {
3267                 debug_error("there is no audio channel selector.\n");
3268                 goto ERROR;
3269         }
3270
3271         active_index = player->audio_mode.active_pad_index;
3272
3273         if (active_index != DEFAULT_AUDIO_CH)
3274         {
3275                 gint audio_ch = DEFAULT_AUDIO_CH;
3276
3277                 /*To get the new pad from the selector*/
3278                 change_pad_name = g_strdup_printf ("sink%d", active_index);
3279                 if (change_pad_name != NULL)
3280                 {
3281                         sinkpad = gst_element_get_static_pad (selector, change_pad_name);
3282                         if (sinkpad != NULL)
3283                         {
3284                                 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3285                                 g_object_set (selector, "active-pad", sinkpad, NULL);
3286
3287                                 audio_ch = active_index;
3288
3289                                 caps = gst_pad_get_current_caps(sinkpad);
3290                                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3291
3292                                 __mmplayer_set_audio_attrs (player, caps);
3293                         }
3294                 }
3295
3296                 player->audio_mode.active_pad_index = audio_ch;
3297                 debug_log("audio LR info (0:stereo) = %d\n", player->audio_mode.active_pad_index);
3298         }
3299
3300 ERROR:
3301
3302         if (sinkpad)
3303                 gst_object_unref (sinkpad);
3304
3305         MMPLAYER_FLEAVE();
3306         return;
3307 }
3308
3309 static void
3310 __mmplayer_gst_build_deinterleave_path (GstElement *elem, GstPad *pad, gpointer data)
3311 {
3312         mm_player_t* player = NULL;
3313         MMPlayerGstElement *mainbin = NULL;
3314
3315         GstElement* tee = NULL;
3316         GstElement* stereo_queue = NULL;
3317         GstElement* mono_queue = NULL;
3318         GstElement* conv = NULL;
3319         GstElement* filter = NULL;
3320         GstElement* deinterleave = NULL;
3321         GstElement* selector = NULL;
3322
3323         GstPad* srcpad = NULL;
3324         GstPad* selector_srcpad = NULL;
3325         GstPad* sinkpad = NULL;
3326         GstCaps* caps = NULL;
3327         gulong block_id = 0;
3328
3329         MMPLAYER_FENTER();
3330
3331         /* check handles */
3332         player = (mm_player_t*) data;
3333
3334         return_if_fail( elem && pad );
3335         return_if_fail( player && player->pipeline && player->pipeline->mainbin );
3336
3337         mainbin = player->pipeline->mainbin;
3338
3339         /* tee */
3340         if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL)
3341         {
3342                 debug_error ("ERROR : tee create error\n");
3343                 goto ERROR;
3344         }
3345
3346         mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
3347         mainbin[MMPLAYER_M_A_TEE].gst = tee;
3348
3349         gst_element_set_state (tee, GST_STATE_PAUSED);
3350
3351         /* queue */
3352         srcpad = gst_element_get_request_pad (tee, "src_%u");
3353         if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3354         {
3355                 debug_error ("ERROR : stereo queue create error\n");
3356                 goto ERROR;
3357         }
3358
3359         g_object_set(G_OBJECT(stereo_queue),
3360                                 "max-size-buffers", 10,
3361                                 "max-size-bytes", 0,
3362                                 "max-size-time", (guint64)0,
3363                                 NULL);
3364
3365         player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
3366         player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
3367
3368         if (srcpad)
3369         {
3370                 gst_object_unref (GST_OBJECT(srcpad));
3371                 srcpad = NULL;
3372         }
3373
3374         srcpad = gst_element_get_request_pad (tee, "src_%u");
3375
3376         if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3377         {
3378                 debug_error ("ERROR : mono queue create error\n");
3379                 goto ERROR;
3380         }
3381
3382         g_object_set(G_OBJECT(mono_queue),
3383                                 "max-size-buffers", 10,
3384                                 "max-size-bytes", 0,
3385                                 "max-size-time", (guint64)0,
3386                                 NULL);
3387
3388         player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3389         player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3390
3391         gst_element_set_state (stereo_queue, GST_STATE_PAUSED);
3392         gst_element_set_state (mono_queue, GST_STATE_PAUSED);
3393
3394         /* audioconvert */
3395         srcpad = gst_element_get_static_pad (mono_queue, "src");
3396         if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL)
3397         {
3398                 debug_error ("ERROR : audioconvert create error\n");
3399                 goto ERROR;
3400         }
3401
3402         player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3403         player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3404
3405         /* caps filter */
3406         if (srcpad)
3407         {
3408                 gst_object_unref (GST_OBJECT(srcpad));
3409                 srcpad = NULL;
3410         }
3411         srcpad = gst_element_get_static_pad (conv, "src");
3412
3413         if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL)
3414         {
3415                 debug_error ("ERROR : capsfilter create error\n");
3416                 goto ERROR;
3417         }
3418
3419         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3420         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3421
3422         caps = gst_caps_from_string( "audio/x-raw-int, "
3423                                 "width = (int) 16, "
3424                                 "depth = (int) 16, "
3425                                 "channels = (int) 2");
3426
3427         g_object_set (GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL );
3428         gst_caps_unref( caps );
3429
3430         gst_element_set_state (conv, GST_STATE_PAUSED);
3431         gst_element_set_state (filter, GST_STATE_PAUSED);
3432
3433         /* deinterleave */
3434         if (srcpad)
3435         {
3436                 gst_object_unref (GST_OBJECT(srcpad));
3437                 srcpad = NULL;
3438         }
3439         srcpad = gst_element_get_static_pad (filter, "src");
3440
3441         if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL)
3442         {
3443                 debug_error ("ERROR : deinterleave create error\n");
3444                 goto ERROR;
3445         }
3446
3447         g_object_set (deinterleave, "keep-positions", TRUE, NULL);
3448
3449         MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3450                                                         G_CALLBACK (__mmplayer_gst_deinterleave_pad_added), player);
3451
3452         MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3453                                                         G_CALLBACK (__mmplayer_gst_deinterleave_no_more_pads), player);
3454
3455         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3456         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3457
3458         /* selector */
3459         selector = gst_element_factory_make ("input-selector", "audio-channel-selector");
3460         if (selector == NULL)
3461         {
3462                 debug_error ("ERROR : audio-selector create error\n");
3463                 goto ERROR;
3464         }
3465
3466         g_object_set (selector, "sync-streams", TRUE, NULL);
3467         gst_bin_add (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3468
3469         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3470         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3471
3472         selector_srcpad = gst_element_get_static_pad (selector, "src");
3473
3474         debug_log ("blocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3475         block_id =
3476                 gst_pad_add_probe(selector_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3477                         __mmplayer_gst_selector_blocked, NULL, NULL);
3478
3479         if (srcpad)
3480         {
3481                 gst_object_unref (GST_OBJECT(srcpad));
3482                 srcpad = NULL;
3483         }
3484
3485         srcpad = gst_element_get_static_pad(stereo_queue, "src");
3486         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3487
3488         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3489         {
3490                 debug_warning ("failed to link queue_stereo - selector\n");
3491                 goto ERROR;
3492         }
3493
3494         player->audio_mode.total_track_num++;
3495
3496         g_object_set (selector, "active-pad", sinkpad, NULL);
3497         gst_element_set_state (deinterleave, GST_STATE_PAUSED);
3498         gst_element_set_state (selector, GST_STATE_PAUSED);
3499
3500         __mmplayer_gst_decode_callback (selector, selector_srcpad, player);
3501
3502 ERROR:
3503
3504         debug_log ("unblocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3505         if (block_id != 0)
3506         {
3507                 gst_pad_remove_probe (selector_srcpad, block_id);
3508                 block_id = 0;
3509         }
3510
3511         if (sinkpad)
3512         {
3513                 gst_object_unref (GST_OBJECT(sinkpad));
3514                 sinkpad = NULL;
3515         }
3516
3517         if (srcpad)
3518         {
3519                 gst_object_unref (GST_OBJECT(srcpad));
3520                 srcpad = NULL;
3521         }
3522
3523         if (selector_srcpad)
3524         {
3525                 gst_object_unref (GST_OBJECT(selector_srcpad));
3526                 selector_srcpad = NULL;
3527         }
3528
3529         MMPLAYER_FLEAVE();
3530         return;
3531 }
3532
3533 static void
3534 __mmplayer_gst_decode_no_more_pads (GstElement *elem, gpointer data)
3535 {
3536         mm_player_t* player = NULL;
3537         GstPad* srcpad = NULL;
3538         GstElement* audio_selector = NULL;
3539         GstElement* text_selector = NULL;
3540         MMHandleType attrs = 0;
3541         gint active_index = 0;
3542         gint64 dur_bytes = 0L;
3543
3544         player = (mm_player_t*) data;
3545
3546         debug_log("no-more-pad signal handling\n");
3547
3548         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3549                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
3550         {
3551                 debug_warning("no need to go more");
3552
3553                 if (player->gapless.reconfigure)
3554                 {
3555                         player->gapless.reconfigure = FALSE;
3556                         MMPLAYER_PLAYBACK_UNLOCK(player);
3557                 }
3558
3559                 return;
3560         }
3561
3562         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3563                 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3564                 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3565                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
3566         {
3567                 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
3568
3569                 if (NULL == player->streamer)
3570                 {
3571                         debug_warning("invalid state for buffering");
3572                         goto ERROR;
3573                 }
3574
3575                 gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
3576                 guint buffer_bytes = init_buffering_time * ESTIMATED_BUFFER_UNIT;
3577
3578                 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
3579                 debug_log("[Decodebin2] set use-buffering on Q2 (pre buffer time: %d sec, buffer size : %d)\n", (gint)init_buffering_time, buffer_bytes);
3580
3581                 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
3582
3583                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
3584                         debug_error("fail to get duration.\n");
3585
3586                 // enable use-buffering on queue2 instead of multiqueue (ex)audio only streaming
3587                 // use file information was already set on Q2 when it was created.
3588                 __mm_player_streaming_set_queue2(player->streamer,
3589                                                 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
3590                                                 TRUE,                                                           // use_buffering
3591                                                 buffer_bytes,
3592                                                 init_buffering_time,
3593                                                 1.0,                                                            // low percent
3594                                                 player->ini.http_buffering_limit,       // high percent
3595                                                 FALSE,
3596                                                 NULL,
3597                                                 ((dur_bytes>0)?((guint64)dur_bytes):0));
3598         }
3599         audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
3600         text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3601         if (audio_selector)
3602         {
3603                 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
3604                 if ((active_index != DEFAULT_TRACK) &&
3605                         (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE))
3606                 {
3607                         debug_warning("failed to change audio track\n");
3608                         player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
3609                 }
3610
3611                 // [link] input-selector :: audiobin
3612                 srcpad = gst_element_get_static_pad (audio_selector, "src");
3613                 if (!srcpad)
3614                 {
3615                         debug_error("failed to get srcpad from selector\n");
3616                         goto ERROR;
3617                 }
3618
3619                 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3620                 if (!text_selector)
3621                         player->no_more_pad = TRUE;
3622
3623                 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2))
3624                 {
3625                         debug_log ("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3626                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id)
3627                         {
3628                                 gst_pad_remove_probe (srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3629                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3630                         }
3631
3632                         __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
3633                 }
3634                 else
3635                 {
3636                         __mmplayer_gst_decode_callback (audio_selector, srcpad, player);
3637
3638                         debug_log ("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3639                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id)
3640                         {
3641                                 gst_pad_remove_probe (srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3642                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3643                         }
3644                 }
3645
3646                 debug_log("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3647
3648                 attrs = MMPLAYER_GET_ATTRS(player);
3649                 if ( attrs )
3650                 {
3651                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3652                         if (mmf_attrs_commit (attrs))
3653                                 debug_error("failed to commit.\n");
3654                 }
3655                 else
3656                 {
3657                         debug_error("cannot get content attribute");
3658                 }
3659         }
3660         else
3661         {
3662                 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst))
3663                 {
3664                         debug_log ("There is no audio track : remove audiobin");
3665
3666                         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN );
3667                         __mmplayer_del_sink ( player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst );
3668
3669                         MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->audiobin, MMPLAYER_A_BIN );
3670                         MMPLAYER_FREEIF ( player->pipeline->audiobin )
3671                 }
3672
3673                 if (player->num_dynamic_pad == 0)
3674                 {
3675                         __mmplayer_pipeline_complete (NULL, player);
3676                 }
3677         }
3678
3679
3680         if (!MMPLAYER_IS_ES_BUFF_SRC(player))
3681         {
3682                 if (text_selector)
3683                 {
3684                         __mmplayer_handle_text_decode_path(player, text_selector);
3685                 }
3686         }
3687
3688         MMPLAYER_FLEAVE();
3689
3690 ERROR:
3691         if (srcpad)
3692         {
3693                 gst_object_unref ( GST_OBJECT(srcpad) );
3694                 srcpad = NULL;
3695         }
3696
3697         if (player->gapless.reconfigure)
3698         {
3699                 player->gapless.reconfigure = FALSE;
3700                 MMPLAYER_PLAYBACK_UNLOCK(player);
3701         }
3702 }
3703
3704 static void
3705 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // @
3706 {
3707         mm_player_t* player = NULL;
3708         MMHandleType attrs = 0;
3709         GstElement* pipeline = NULL;
3710         GstCaps* caps = NULL;
3711         gchar* caps_str = NULL;
3712         GstStructure* str = NULL;
3713         const gchar* name = NULL;
3714         GstPad* sinkpad = NULL;
3715         GstElement* sinkbin = NULL;
3716         gboolean reusing = FALSE;
3717         GstElement *text_selector = NULL;
3718
3719         /* check handles */
3720         player = (mm_player_t*) data;
3721
3722         return_if_fail( elem && pad );
3723         return_if_fail(player && player->pipeline && player->pipeline->mainbin);
3724
3725         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3726
3727         attrs = MMPLAYER_GET_ATTRS(player);
3728         if ( !attrs )
3729         {
3730                 debug_error("cannot get content attribute\n");
3731                 goto ERROR;
3732         }
3733
3734         /* get mimetype from caps */
3735         caps = gst_pad_query_caps( pad, NULL );
3736         if ( !caps )
3737         {
3738                 debug_error("cannot get caps from pad.\n");
3739                 goto ERROR;
3740         }
3741         caps_str = gst_caps_to_string(caps);
3742
3743         str = gst_caps_get_structure( caps, 0 );
3744         if ( ! str )
3745         {
3746                 debug_error("cannot get structure from caps.\n");
3747                 goto ERROR;
3748         }
3749
3750         name = gst_structure_get_name(str);
3751         if ( ! name )
3752         {
3753                 debug_error("cannot get mimetype from structure.\n");
3754                 goto ERROR;
3755         }
3756
3757         //debug_log("detected mimetype : %s\n", name);
3758
3759         if (strstr(name, "audio"))
3760         {
3761                 if (player->pipeline->audiobin == NULL)
3762                 {
3763                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player))
3764                         {
3765                                 debug_error("failed to create audiobin. continuing without audio\n");
3766                                 goto ERROR;
3767                         }
3768
3769                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3770                         debug_log("creating audiosink bin success\n");
3771                 }
3772                 else
3773                 {
3774                         reusing = TRUE;
3775                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3776                         debug_log("reusing audiobin\n");
3777                         _mmplayer_update_content_attrs( player, ATTR_AUDIO);
3778                 }
3779
3780                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
3781                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
3782
3783                 player->audiosink_linked  = 1;
3784
3785                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
3786                 if ( !sinkpad )
3787                 {
3788                         debug_error("failed to get pad from sinkbin\n");
3789                         goto ERROR;
3790                 }
3791         }
3792         else if (strstr(name, "video"))
3793         {
3794                 if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
3795                 {
3796                         player->set_mode.video_zc = TRUE;
3797                 }
3798
3799                 if (player->pipeline->videobin == NULL)
3800                 {
3801                         /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
3802                         /* get video surface type */
3803                         int surface_type = 0;
3804                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
3805
3806                         if (surface_type == MM_DISPLAY_SURFACE_NULL)
3807                         {
3808                                 debug_log("not make videobin because it dose not want\n");
3809                                 goto ERROR;
3810                         }
3811
3812                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type) )
3813                         {
3814                                 debug_error("failed to create videobin. continuing without video\n");
3815                                 goto ERROR;
3816                         }
3817
3818                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3819                         debug_log("creating videosink bin success\n");
3820                 }
3821                 else
3822                 {
3823                         reusing = TRUE;
3824                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3825                         debug_log("re-using videobin\n");
3826                         _mmplayer_update_content_attrs( player, ATTR_VIDEO);
3827                 }
3828
3829                 /* FIXIT : track number shouldn't be hardcoded */
3830                 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 1);
3831                 player->videosink_linked  = 1;
3832
3833                 /* NOTE : intermediate code before doing H/W subtitle compositon */
3834                 if ( player->use_textoverlay && player->play_subtitle )
3835                 {
3836                         debug_log("using textoverlay for external subtitle");
3837                         /* check text bin has created well */
3838                         if ( player->pipeline && player->pipeline->textbin )
3839                         {
3840                                 /* get sinkpad from textoverlay */
3841                                 sinkpad = gst_element_get_static_pad(
3842                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
3843                                         "video_sink" );
3844                                 if ( ! sinkpad )
3845                                 {
3846                                         debug_error("failed to get sink pad from textoverlay");
3847                                         goto ERROR;
3848                                 }
3849
3850                                 /* link new pad with textoverlay first */
3851                                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
3852                                 {
3853                                         debug_error("failed to get pad from sinkbin\n");
3854                                         goto ERROR;
3855                                 }
3856
3857                                 gst_object_unref(sinkpad);
3858                                 sinkpad = NULL;
3859
3860                                 /* alright, override pad to textbin.src for futher link */
3861                                 pad = gst_element_get_static_pad(
3862                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
3863                                         "src" );
3864                                 if ( ! pad )
3865                                 {
3866                                         debug_error("failed to get sink pad from textoverlay");
3867                                         goto ERROR;
3868                                 }
3869                         }
3870                         else
3871                         {
3872                                 debug_error("should not reach here.");
3873                                 goto ERROR;
3874                         }
3875                 }
3876
3877                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
3878                 if ( !sinkpad )
3879                 {
3880                         debug_error("failed to get pad from sinkbin\n");
3881                         goto ERROR;
3882                 }
3883         }
3884         else if (strstr(name, "text"))
3885         {
3886                 if (player->pipeline->textbin == NULL)
3887                 {
3888                         MMPlayerGstElement* mainbin = NULL;
3889
3890                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
3891                         {
3892                                 debug_error("failed to create textbin. continuing without text\n");
3893                                 goto ERROR;
3894                         }
3895
3896                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3897                         debug_log("creating textsink bin success\n");
3898
3899                         /* FIXIT : track number shouldn't be hardcoded */
3900                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
3901
3902                         player->textsink_linked  = 1;
3903                         debug_msg("player->textsink_linked set to 1\n");
3904
3905                         sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "text_sink" );
3906                         if ( !sinkpad )
3907                         {
3908                                 debug_error("failed to get pad from sinkbin\n");
3909                                 goto ERROR;
3910                         }
3911
3912                         mainbin = player->pipeline->mainbin;
3913
3914                         if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst)
3915                         {
3916                           /* input selector */
3917                           text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
3918                           if ( !text_selector )
3919                           {
3920                             debug_error ( "failed to create subtitle input selector element\n" );
3921                             goto ERROR;
3922                           }
3923                           g_object_set (text_selector, "sync-streams", TRUE, NULL);
3924
3925                           mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
3926                           mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
3927
3928                           /* warm up */
3929                           if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_READY))
3930                           {
3931                             debug_error("failed to set state(READY) to sinkbin\n");
3932                             goto ERROR;
3933                           }
3934
3935                           if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector))
3936                           {
3937                             debug_warning("failed to add subtitle input selector\n");
3938                             goto ERROR;
3939                           }
3940
3941                           debug_log ("created element input-selector");
3942
3943                         }
3944                         else
3945                         {
3946                           debug_log ("already having subtitle input selector");
3947                           text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3948                         }
3949                 }
3950
3951                 else
3952                 {
3953                         if (!player->textsink_linked)
3954                         {
3955                                 debug_log("re-using textbin\n");
3956
3957                                 reusing = TRUE;
3958                                 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3959
3960                                 player->textsink_linked  = 1;
3961                                 debug_msg("player->textsink_linked set to 1\n");
3962                         }
3963                         else
3964                         {
3965                                 debug_log("ignoring internal subtutle since external subtitle is available");
3966                         }
3967                 }
3968         }
3969         else
3970         {
3971                 debug_warning("unknown type of elementary stream! ignoring it...\n");
3972                 goto ERROR;
3973         }
3974
3975         if ( sinkbin )
3976         {
3977                 if(!reusing)
3978                 {
3979                         /* warm up */
3980                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_READY ) )
3981                         {
3982                                 debug_error("failed to set state(READY) to sinkbin\n");
3983                                 goto ERROR;
3984                         }
3985
3986                         /* Added for multi audio support to avoid adding audio bin again*/
3987                         /* add */
3988                         if ( FALSE == gst_bin_add( GST_BIN(pipeline), sinkbin ) )
3989                         {
3990                                 debug_error("failed to add sinkbin to pipeline\n");
3991                                 goto ERROR;
3992                         }
3993                 }
3994
3995                 /* link */
3996                 if (GST_PAD_LINK_OK != GST_PAD_LINK (pad, sinkpad))
3997                 {
3998                         debug_error("failed to get pad from sinkbin\n");
3999                         goto ERROR;
4000                 }
4001
4002                 if (!reusing)
4003                 {
4004                         /* run */
4005                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (sinkbin, GST_STATE_PAUSED))
4006                         {
4007                                 debug_error("failed to set state(PAUSED) to sinkbin\n");
4008                                 goto ERROR;
4009                         }
4010
4011                         if (text_selector)
4012                         {
4013                           if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_PAUSED))
4014                           {
4015                             debug_error("failed to set state(PAUSED) to sinkbin\n");
4016                             goto ERROR;
4017                           }
4018                         }
4019                 }
4020
4021                 gst_object_unref (sinkpad);
4022                 sinkpad = NULL;
4023         }
4024
4025         debug_log ("linking sink bin success\n");
4026
4027         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
4028          * streaming task. if the task blocked, then buffer will not flow to the next element
4029          * ( autoplugging element ). so this is special hack for streaming. please try to remove it
4030          */
4031         /* dec stream count. we can remove fakesink if it's zero */
4032         if (player->num_dynamic_pad)
4033                 player->num_dynamic_pad--;
4034
4035         debug_log ("no more pads: %d stream count dec : %d (num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
4036
4037         if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
4038         {
4039                 __mmplayer_pipeline_complete (NULL, player);
4040         }
4041
4042         /* FIXIT : please leave a note why this code is needed */
4043         if(MMPLAYER_IS_WFD_STREAMING( player ))
4044         {
4045                 player->no_more_pad = TRUE;
4046         }
4047
4048 ERROR:
4049
4050         MMPLAYER_FREEIF(caps_str);
4051
4052         if ( caps )
4053                 gst_caps_unref( caps );
4054
4055         if ( sinkpad )
4056                 gst_object_unref(GST_OBJECT(sinkpad));
4057
4058         /* flusing out new attributes */
4059         if (  mmf_attrs_commit ( attrs ) )
4060         {
4061                 debug_error("failed to comit attributes\n");
4062         }
4063
4064         return;
4065 }
4066
4067 static int
4068 __mmplayer_gst_element_link_bucket(GList* element_bucket) // @
4069 {
4070         GList* bucket = element_bucket;
4071         MMPlayerGstElement* element = NULL;
4072         MMPlayerGstElement* prv_element = NULL;
4073         gint successful_link_count = 0;
4074
4075         MMPLAYER_FENTER();
4076
4077         return_val_if_fail(element_bucket, -1);
4078
4079         prv_element = (MMPlayerGstElement*)bucket->data;
4080         bucket = bucket->next;
4081
4082         for ( ; bucket; bucket = bucket->next )
4083         {
4084                 element = (MMPlayerGstElement*)bucket->data;
4085
4086                 if ( element && element->gst )
4087                 {
4088                         /* If next element is audio appsrc then make a seprate audio pipeline */
4089                         if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),"audio_appsrc") ||
4090                                 !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),"subtitle_appsrc"))
4091                         {
4092                                 prv_element = element;
4093                                 continue;
4094                         }
4095
4096                         if ( GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst)) )
4097                         {
4098                                 debug_log("linking [%s] to [%s] success\n",
4099                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4100                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
4101                                 successful_link_count ++;
4102                         }
4103                         else
4104                         {
4105                                 debug_log("linking [%s] to [%s] failed\n",
4106                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4107                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
4108                                 return -1;
4109                         }
4110                 }
4111
4112                 prv_element = element;
4113         }
4114
4115         MMPLAYER_FLEAVE();
4116
4117         return successful_link_count;
4118 }
4119
4120 static int
4121 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket) // @
4122 {
4123         GList* bucket = element_bucket;
4124         MMPlayerGstElement* element = NULL;
4125         int successful_add_count = 0;
4126
4127         MMPLAYER_FENTER();
4128
4129         return_val_if_fail(element_bucket, 0);
4130         return_val_if_fail(bin, 0);
4131
4132         for ( ; bucket; bucket = bucket->next )
4133         {
4134                 element = (MMPlayerGstElement*)bucket->data;
4135
4136                 if ( element && element->gst )
4137                 {
4138                         if( !gst_bin_add(bin, GST_ELEMENT(element->gst)) )
4139                         {
4140                                 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
4141                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
4142                                         GST_ELEMENT_NAME(GST_ELEMENT(bin) ) );
4143                                 return 0;
4144                         }
4145                         successful_add_count ++;
4146                 }
4147         }
4148
4149         MMPLAYER_FLEAVE();
4150
4151         return successful_add_count;
4152 }
4153
4154 static void __mmplayer_gst_caps_notify_cb (GstPad * pad, GParamSpec * unused, gpointer data)
4155 {
4156         mm_player_t* player = (mm_player_t*) data;
4157         GstCaps *caps = NULL;
4158         GstStructure *str = NULL;
4159         const char *name;
4160
4161         MMPLAYER_FENTER();
4162
4163         return_if_fail ( pad )
4164         return_if_fail ( unused )
4165         return_if_fail ( data )
4166
4167         caps = gst_pad_get_current_caps( pad );
4168         if ( !caps )
4169         {
4170                 return;
4171         }
4172
4173         str = gst_caps_get_structure(caps, 0);
4174         if ( !str )
4175         {
4176                 goto ERROR;
4177         }
4178
4179         name = gst_structure_get_name(str);
4180         if ( !name )
4181         {
4182                 goto ERROR;
4183         }
4184
4185         debug_log("name = %s\n", name);
4186
4187         if (strstr(name, "audio"))
4188         {
4189                 _mmplayer_update_content_attrs (player, ATTR_AUDIO);
4190
4191                 if (player->audio_stream_changed_cb)
4192                 {
4193                         debug_error("call the audio stream changed cb\n");
4194                         player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
4195                 }
4196         }
4197         else if (strstr(name, "video"))
4198         {
4199                 _mmplayer_update_content_attrs (player, ATTR_VIDEO);
4200
4201                 if (player->video_stream_changed_cb)
4202                 {
4203                         debug_error("call the video stream changed cb\n");
4204                         player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
4205                 }
4206         }
4207         else
4208         {
4209                 goto ERROR;
4210         }
4211
4212 ERROR:
4213
4214         gst_caps_unref(caps);
4215
4216         MMPLAYER_FLEAVE();
4217
4218         return;
4219 }
4220
4221
4222
4223 /**
4224  * This function is to create audio pipeline for playing.
4225  *
4226  * @param       player          [in]    handle of player
4227  *
4228  * @return      This function returns zero on success.
4229  * @remark
4230  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
4231  */
4232 #define MMPLAYER_CREATEONLY_ELEMENT(x_bin, x_id, x_factory, x_name) \
4233 x_bin[x_id].id = x_id;\
4234 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4235 if ( ! x_bin[x_id].gst )\
4236 {\
4237         debug_error("failed to create %s \n", x_factory);\
4238         goto ERROR;\
4239 }\
4240
4241 #define MMPLAYER_CREATE_ELEMENT_ADD_BIN(x_bin, x_id, x_factory, x_name, y_bin, x_player) \
4242 x_bin[x_id].id = x_id;\
4243 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4244 if ( ! x_bin[x_id].gst )\
4245 {\
4246         debug_error("failed to create %s \n", x_factory);\
4247         goto ERROR;\
4248 }\
4249 else\
4250 {\
4251         if (x_player->ini.set_dump_element_flag)\
4252                 __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
4253 }\
4254 if( !gst_bin_add(GST_BIN(y_bin), GST_ELEMENT(x_bin[x_id].gst)))\
4255 {\
4256         debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",\
4257                 GST_ELEMENT_NAME(GST_ELEMENT(x_bin[x_id].gst)),\
4258                 GST_ELEMENT_NAME(GST_ELEMENT(y_bin) ) );\
4259         goto ERROR;\
4260 }\
4261
4262 /* macro for code readability. just for sinkbin-creation functions */
4263 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
4264 do \
4265 { \
4266         x_bin[x_id].id = x_id;\
4267         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4268         if ( ! x_bin[x_id].gst )\
4269         {\
4270                 debug_error("failed to create %s \n", x_factory);\
4271                 goto ERROR;\
4272         }\
4273         else\
4274         {\
4275                 if (x_player->ini.set_dump_element_flag)\
4276                         __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
4277         }\
4278         if ( x_add_bucket )\
4279                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
4280 } while(0);
4281
4282 static void
4283 __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
4284 {
4285         mm_player_t* player = (mm_player_t*) data;
4286
4287         gint channel = 0;
4288         gint rate = 0;
4289         gint depth = 0;
4290         gint endianness = 0;
4291         guint64 channel_mask = 0;
4292
4293         MMPlayerAudioStreamDataType audio_stream = { 0, };
4294         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
4295
4296         MMPLAYER_FENTER();
4297         return_if_fail(player->audio_stream_render_cb_ex);
4298
4299         debug_log ("__mmplayer_audio_stream_decoded_render_cb new pad: %s", GST_PAD_NAME (pad));
4300
4301         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
4302         audio_stream.data = mapinfo.data;
4303         audio_stream.data_size = mapinfo.size;
4304
4305         GstCaps *caps = gst_pad_get_current_caps( pad );
4306         GstStructure *structure = gst_caps_get_structure (caps, 0);
4307
4308         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
4309         gst_structure_get_int (structure, "rate", &rate);
4310         gst_structure_get_int (structure, "channels", &channel);
4311         gst_structure_get_int (structure, "depth", &depth);
4312         gst_structure_get_int (structure, "endianness", &endianness);
4313         gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
4314
4315         gst_caps_unref(GST_CAPS(caps));
4316
4317         audio_stream.bitrate = rate;
4318         audio_stream.channel = channel;
4319         audio_stream.depth = depth;
4320         audio_stream.is_little_endian = (endianness == 1234 ? 1 : 0);
4321         audio_stream.channel_mask = channel_mask;
4322         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);
4323         player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param);
4324         gst_buffer_unmap(buffer, &mapinfo);
4325
4326         MMPLAYER_FLEAVE();
4327 }
4328
4329 static void
4330 __mmplayer_gst_audio_deinterleave_pad_added (GstElement *elem, GstPad *pad, gpointer data)
4331 {
4332         mm_player_t* player = (mm_player_t*)data;
4333         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
4334         GstPad* sinkpad = NULL;
4335         GstElement *queue = NULL, *sink = NULL;
4336
4337         MMPLAYER_FENTER();
4338         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
4339
4340         queue = gst_element_factory_make ("queue", NULL);
4341         if (queue == NULL)
4342         {
4343                 debug_log ("fail make queue\n");
4344                 goto ERROR;
4345         }
4346
4347         sink = gst_element_factory_make ("fakesink", NULL);
4348         if (sink == NULL)
4349         {
4350                 debug_log ("fail make fakesink\n");
4351                 goto ERROR;
4352         }
4353
4354         gst_bin_add_many (GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
4355
4356         if (!gst_element_link_pads_full (queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING))
4357         {
4358                 debug_warning("failed to link queue & sink\n");
4359                 goto ERROR;
4360         }
4361
4362         sinkpad = gst_element_get_static_pad (queue, "sink");
4363
4364         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
4365         {
4366                 debug_warning ("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
4367                 goto ERROR;
4368         }
4369
4370         debug_error("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
4371
4372         gst_object_unref (sinkpad);
4373         g_object_set (sink, "sync", player->audio_stream_sink_sync, NULL);
4374         g_object_set (sink, "signal-handoffs", TRUE, NULL);
4375
4376         gst_element_set_state (sink, GST_STATE_PAUSED);
4377         gst_element_set_state (queue, GST_STATE_PAUSED);
4378
4379         MMPLAYER_SIGNAL_CONNECT( player,
4380                 G_OBJECT(sink),
4381                 MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4382                 "handoff",
4383                 G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
4384                 (gpointer)player );
4385
4386         MMPLAYER_FLEAVE();
4387         return ;
4388
4389 ERROR:
4390         debug_error("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
4391         if (queue)
4392         {
4393                 gst_object_unref(GST_OBJECT(queue));
4394                 queue = NULL;
4395         }
4396         if (sink)
4397         {
4398                 gst_object_unref(GST_OBJECT(sink));
4399                 sink = NULL;
4400         }
4401         if (sinkpad)
4402         {
4403                 gst_object_unref ( GST_OBJECT(sinkpad) );
4404                 sinkpad = NULL;
4405         }
4406
4407         return;
4408 }
4409
4410 void __mmplayer_gst_set_audiosink_property(mm_player_t* player, MMHandleType attrs)
4411 {
4412         #define MAX_PROPS_LEN 64
4413         gint volume_type = 0;
4414         gint latency_mode = 0;
4415         gchar *stream_type = NULL;
4416         gchar *latency = NULL;
4417         gint stream_id = 0;
4418         gchar stream_props[MAX_PROPS_LEN] = {0,};
4419         GstStructure *props = NULL;
4420
4421         /* set volume table
4422          * It should be set after player creation through attribute.
4423          * But, it can not be changed during playing.
4424          */
4425         MMPLAYER_FENTER();
4426         mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
4427         mm_attrs_get_string_by_name (attrs, "sound_stream_type", &stream_type );
4428
4429         if (!stream_type)
4430         {
4431                 debug_error("stream_type is null.\n");
4432         }
4433         else
4434         {
4435                 snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d", stream_type, stream_id);
4436                 props = gst_structure_from_string(stream_props, NULL);
4437                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
4438                 debug_log("stream_id[%d], stream_type[%s], result[%s].\n", stream_id, stream_type, stream_props);
4439         }
4440
4441         mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
4442         mm_attrs_get_int_by_name(attrs, "sound_volume_type", &volume_type);
4443
4444         switch (latency_mode)
4445         {
4446                 case AUDIO_LATENCY_MODE_LOW:
4447                         latency = g_strndup("low", 3);
4448                         break;
4449                 case AUDIO_LATENCY_MODE_MID:
4450                         latency = g_strndup("mid", 3);
4451                         break;
4452                 case AUDIO_LATENCY_MODE_HIGH:
4453                         latency = g_strndup("high", 4);
4454                         break;
4455         };
4456
4457         /* hook sound_type if emergency case */
4458         if (player->sound_focus.focus_changed_msg == MM_PLAYER_FOCUS_CHANGED_BY_EMERGENCY)
4459         {
4460                 debug_log ("emergency session, hook sound_type from [%d] to [%d]\n", volume_type, MM_SOUND_VOLUME_TYPE_EMERGENCY);
4461                 volume_type = MM_SOUND_VOLUME_TYPE_EMERGENCY;
4462         }
4463 #if 0 //need to check
4464         if (player->sound_focus.user_route_policy != 0)
4465         {
4466                 route_path = player->sound_focus.user_route_policy;
4467         }
4468
4469         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
4470                         "latency", latency_mode,
4471                         NULL);
4472
4473         debug_log("audiosink property status...volume type:%d, user-route=%d, latency=%d \n",
4474                 volume_type, route_path, latency_mode);
4475         MMPLAYER_FLEAVE();
4476
4477 #endif
4478
4479         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
4480                         "latency", latency,
4481                         NULL);
4482
4483         debug_log("audiosink property - volume type=%d, latency=%s \n",
4484                 volume_type, latency);
4485
4486         g_free(latency);
4487
4488         MMPLAYER_FLEAVE();
4489 }
4490
4491 static int
4492 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
4493 {
4494         MMPlayerGstElement* first_element = NULL;
4495         MMPlayerGstElement* audiobin = NULL;
4496         MMHandleType attrs = 0;
4497         GstPad *pad = NULL;
4498         GstPad *ghostpad = NULL;
4499         GList* element_bucket = NULL;
4500         gboolean link_audio_sink_now = TRUE;
4501         int i =0;
4502
4503         MMPLAYER_FENTER();
4504
4505         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
4506
4507         /* alloc handles */
4508         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
4509         if ( ! audiobin )
4510         {
4511                 debug_error("failed to allocate memory for audiobin\n");
4512                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
4513         }
4514
4515         attrs = MMPLAYER_GET_ATTRS(player);
4516
4517         /* create bin */
4518         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
4519         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
4520         if ( !audiobin[MMPLAYER_A_BIN].gst )
4521         {
4522                 debug_error("failed to create audiobin\n");
4523                 goto ERROR;
4524         }
4525
4526         /* take it */
4527         player->pipeline->audiobin = audiobin;
4528
4529         player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
4530
4531         /* Adding audiotp plugin for reverse trickplay feature */
4532 //      MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
4533
4534         /* converter */
4535         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
4536
4537         /* resampler */
4538         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER,  player->ini.audioresampler_element, "audio resampler", TRUE, player);
4539
4540         if (player->set_mode.pcm_extraction) // pcm extraction only and no sound output
4541         {
4542                 if(player->audio_stream_render_cb_ex)
4543                 {
4544                         char *caps_str = NULL;
4545                         GstCaps* caps = NULL;
4546                         gchar *format = NULL;
4547
4548                         /* capsfilter */
4549                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4550
4551                         mm_attrs_get_string_by_name (player->attrs, "pcm_audioformat", &format );
4552
4553                         debug_log("contents : format: %s samplerate : %d pcm_channel: %d", format, player->pcm_samplerate, player->pcm_channel);
4554
4555                         caps = gst_caps_new_simple ("audio/x-raw",
4556                                         "format", G_TYPE_STRING, format,
4557                                         "rate", G_TYPE_INT, player->pcm_samplerate,
4558                                         "channels", G_TYPE_INT, player->pcm_channel,
4559                                         NULL);
4560                         caps_str = gst_caps_to_string(caps);
4561                         debug_log("new caps : %s\n", caps_str);
4562
4563                         g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
4564
4565                         /* clean */
4566                         gst_caps_unref( caps );
4567                         MMPLAYER_FREEIF( caps_str );
4568
4569                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
4570
4571                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
4572                         /* raw pad handling signal */
4573                         MMPLAYER_SIGNAL_CONNECT( player,
4574                                 (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
4575                                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
4576                                                                                                 G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
4577                 }
4578                 else
4579                 {
4580                         int dst_samplerate = 0;
4581                         int dst_channels = 0;
4582                         int dst_depth = 0;
4583                         char *caps_str = NULL;
4584                         GstCaps* caps = NULL;
4585
4586                         /* get conf. values */
4587                         mm_attrs_multiple_get(player->attrs,
4588                                                 NULL,
4589                                                 "pcm_extraction_samplerate", &dst_samplerate,
4590                                                 "pcm_extraction_channels", &dst_channels,
4591                                                 "pcm_extraction_depth", &dst_depth,
4592                                                 NULL);
4593
4594                         /* capsfilter */
4595                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4596                         caps = gst_caps_new_simple ("audio/x-raw",
4597                                         "rate", G_TYPE_INT, dst_samplerate,
4598                                         "channels", G_TYPE_INT, dst_channels,
4599                                         "depth", G_TYPE_INT, dst_depth,
4600                                         NULL);
4601                         caps_str = gst_caps_to_string(caps);
4602                         debug_log("new caps : %s\n", caps_str);
4603
4604                         g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
4605
4606                         /* clean */
4607                         gst_caps_unref( caps );
4608                         MMPLAYER_FREEIF( caps_str );
4609
4610                         /* fake sink */
4611                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
4612
4613                         /* set sync */
4614                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
4615                 }
4616         }
4617         else // normal playback
4618         {
4619                 //GstCaps* caps = NULL;
4620                 gint channels = 0;
4621
4622                 /* for logical volume control */
4623                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
4624                 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
4625
4626                 if (player->sound.mute)
4627                 {
4628                         debug_log("mute enabled\n");
4629                         g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
4630                 }
4631
4632 #if 0
4633                 /*capsfilter */
4634                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
4635                 caps = gst_caps_from_string( "audio/x-raw-int, "
4636                                         "endianness = (int) LITTLE_ENDIAN, "
4637                                         "signed = (boolean) true, "
4638                                         "width = (int) 16, "
4639                                         "depth = (int) 16" );
4640                 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
4641                 gst_caps_unref( caps );
4642 #endif
4643
4644                 /* chech if multi-chennels */
4645                 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)
4646                 {
4647                         GstPad *srcpad = NULL;
4648                         GstCaps *caps = NULL;
4649
4650                         if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src")))
4651                         {
4652                                 if ((caps = gst_pad_query_caps(srcpad, NULL)))
4653                                 {
4654                                         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
4655                                         GstStructure *str = gst_caps_get_structure(caps, 0);
4656                                         if (str)
4657                                                 gst_structure_get_int (str, "channels", &channels);
4658                                         gst_caps_unref(caps);
4659                                 }
4660                                 gst_object_unref(srcpad);
4661                         }
4662                 }
4663
4664                 /* audio effect element. if audio effect is enabled */
4665                 if ( (strcmp(player->ini.audioeffect_element, ""))
4666                         && (channels <= 2)
4667                         && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom))
4668                 {
4669                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.audioeffect_element, "audio effect filter", TRUE, player);
4670
4671                         debug_log("audio effect config. bypass = %d, effect type  = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
4672
4673                         if ( (!player->bypass_audio_effect)
4674                                 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom) )
4675                         {
4676                                 if ( MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type )
4677                                 {
4678                                         if (!_mmplayer_audio_effect_custom_apply(player))
4679                                         {
4680                                                 debug_msg("apply audio effect(custom) setting success\n");
4681                                         }
4682                                 }
4683                         }
4684
4685                         if ( (strcmp(player->ini.audioeffect_element_custom, ""))
4686                                 && (player->set_mode.rich_audio) )
4687                         {
4688                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.audioeffect_element_custom, "audio effect filter custom", TRUE, player);
4689                         }
4690                 }
4691                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
4692                 {
4693                         if (player->set_mode.rich_audio && channels <= 2)
4694                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VSP, "audiovsp", "x-speed", TRUE, player);
4695                 }
4696
4697                 /* create audio sink */
4698                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", link_audio_sink_now, player);
4699
4700                 /* qos on */
4701                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);     /* qos on */
4702                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
4703
4704                 if (player->videodec_linked && player->ini.use_system_clock)
4705                 {
4706                         debug_log("system clock will be used.\n");
4707                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE,  NULL);
4708                 }
4709
4710                 if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
4711                         __mmplayer_gst_set_audiosink_property(player, attrs);
4712         }
4713
4714         if (audiobin[MMPLAYER_A_SINK].gst)
4715         {
4716                 GstPad *sink_pad = NULL;
4717                 sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
4718                 MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4719                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
4720                 gst_object_unref (GST_OBJECT(sink_pad));
4721         }
4722
4723         __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
4724
4725         /* adding created elements to bin */
4726         debug_log("adding created elements to bin\n");
4727         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket ))
4728         {
4729                 debug_error("failed to add elements\n");
4730                 goto ERROR;
4731         }
4732
4733         /* linking elements in the bucket by added order. */
4734         debug_log("Linking elements in the bucket by added order.\n");
4735         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
4736         {
4737                 debug_error("failed to link elements\n");
4738                 goto ERROR;
4739         }
4740
4741         /* get first element's sinkpad for creating ghostpad */
4742         first_element = (MMPlayerGstElement *)element_bucket->data;
4743
4744         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
4745         if ( ! pad )
4746         {
4747                 debug_error("failed to get pad from first element of audiobin\n");
4748                 goto ERROR;
4749         }
4750
4751         ghostpad = gst_ghost_pad_new("sink", pad);
4752         if ( ! ghostpad )
4753         {
4754                 debug_error("failed to create ghostpad\n");
4755                 goto ERROR;
4756         }
4757
4758         if ( FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad) )
4759         {
4760                 debug_error("failed to add ghostpad to audiobin\n");
4761                 goto ERROR;
4762         }
4763
4764         player->gapless.audio_data_probe_id = gst_pad_add_probe(ghostpad, GST_PAD_PROBE_TYPE_BUFFER,
4765                         __mmplayer_audio_data_probe, player, NULL);
4766
4767         gst_object_unref(pad);
4768
4769         g_list_free(element_bucket);
4770
4771         mm_attrs_set_int_by_name(attrs, "content_audio_found", TRUE);
4772
4773         MMPLAYER_FLEAVE();
4774
4775         return MM_ERROR_NONE;
4776
4777 ERROR:
4778
4779         debug_log("ERROR : releasing audiobin\n");
4780
4781         if ( pad )
4782                 gst_object_unref(GST_OBJECT(pad));
4783
4784         if ( ghostpad )
4785                 gst_object_unref(GST_OBJECT(ghostpad));
4786
4787         g_list_free( element_bucket );
4788
4789         /* release element which are not added to bin */
4790         for ( i = 1; i < MMPLAYER_A_NUM; i++ )  /* NOTE : skip bin */
4791         {
4792                 if ( audiobin[i].gst )
4793                 {
4794                         GstObject* parent = NULL;
4795                         parent = gst_element_get_parent( audiobin[i].gst );
4796
4797                         if ( !parent )
4798                         {
4799                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
4800                                 audiobin[i].gst = NULL;
4801                         }
4802                         else
4803                         {
4804                                 gst_object_unref(GST_OBJECT(parent));
4805                         }
4806                 }
4807         }
4808
4809         /* release audiobin with it's childs */
4810         if ( audiobin[MMPLAYER_A_BIN].gst )
4811         {
4812                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
4813         }
4814
4815         MMPLAYER_FREEIF( audiobin );
4816
4817         player->pipeline->audiobin = NULL;
4818
4819         return MM_ERROR_PLAYER_INTERNAL;
4820 }
4821
4822 static GstPadProbeReturn
4823 __mmplayer_audio_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
4824 {
4825         mm_player_t* player = (mm_player_t*) u_data;
4826         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
4827         GstMapInfo probe_info = GST_MAP_INFO_INIT;
4828
4829         gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
4830
4831         if (player->audio_stream_cb && probe_info.size && probe_info.data)
4832                 player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
4833
4834         return GST_PAD_PROBE_OK;
4835 }
4836
4837 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
4838 {
4839     return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
4840 }
4841
4842 static GstPadProbeReturn
4843 __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
4844 {
4845         GstCaps *caps = NULL;
4846         MMPlayerVideoStreamDataType stream;
4847         MMVideoBuffer *video_buffer = NULL;
4848         GstMemory *dataBlock = NULL;
4849         GstMemory *metaBlock = NULL;
4850         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
4851         GstStructure *structure = NULL;
4852         const gchar *string_format = NULL;
4853         unsigned int fourcc = 0;
4854         mm_player_t* player = (mm_player_t*)user_data;
4855         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
4856
4857         return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
4858         return_val_if_fail(gst_buffer_n_memory(buffer)  , GST_PAD_PROBE_DROP);
4859
4860         caps = gst_pad_get_current_caps(pad);
4861         if (caps == NULL) {
4862                 debug_error( "Caps is NULL." );
4863                 return GST_PAD_PROBE_OK;
4864         }
4865
4866         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
4867
4868         /* clear stream data structure */
4869         memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
4870
4871         structure = gst_caps_get_structure( caps, 0 );
4872         gst_structure_get_int(structure, "width", &(stream.width));
4873         gst_structure_get_int(structure, "height", &(stream.height));
4874         string_format = gst_structure_get_string(structure, "format");
4875         if(string_format) {
4876                 fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
4877         }
4878         stream.format = util_get_pixtype(fourcc);
4879         gst_caps_unref( caps );
4880         caps = NULL;
4881
4882     /*
4883         debug_log( "Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
4884                         GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format );
4885     */
4886
4887         if (stream.width == 0 || stream.height == 0 || stream.format == MM_PIXEL_FORMAT_INVALID) {
4888                 debug_error("Wrong condition!!");
4889                 return TRUE;
4890         }
4891
4892         /* set size and timestamp */
4893         dataBlock = gst_buffer_peek_memory(buffer, 0);
4894         stream.length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
4895         stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano sec -> mili sec */
4896
4897         /* check zero-copy */
4898         if (player->set_mode.video_zc &&
4899                 player->set_mode.media_packet_video_stream &&
4900                 gst_buffer_n_memory(buffer) > 1) {
4901                 metaBlock = gst_buffer_peek_memory(buffer, 1);
4902                 gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
4903                 video_buffer = (MMVideoBuffer *)mapinfo.data;
4904         }
4905
4906         if (video_buffer) {
4907                 /* set tbm bo */
4908                 if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
4909                         /* copy pointer of tbm bo, stride, elevation */
4910                         memcpy(stream.bo, video_buffer->handle.bo,
4911                                         sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
4912                 }
4913                 else if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
4914                         memcpy(stream.data, video_buffer->data,
4915                                         sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
4916                 }
4917                 memcpy(stream.stride, video_buffer->stride_width,
4918                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
4919                 memcpy(stream.elevation, video_buffer->stride_height,
4920                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
4921                 /* set gst buffer */
4922                 stream.internal_buffer = buffer;
4923         } else {
4924                 tbm_bo_handle thandle;
4925                 int stride = ((stream.width + 3) & (~3));
4926                 int elevation = stream.height;
4927                 int size = stride * elevation * 3 / 2;
4928                 gboolean gst_ret;
4929                 gst_ret = gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
4930                 if(!gst_ret) {
4931                         debug_error("fail to gst_memory_map");
4932                         return GST_PAD_PROBE_OK;
4933                 }
4934
4935                 stream.stride[0] = stride;
4936                 stream.elevation[0] = elevation;
4937                 if(stream.format == MM_PIXEL_FORMAT_I420) {
4938                         stream.stride[1] = stream.stride[2] = stride / 2;
4939                         stream.elevation[1] = stream.elevation[2] = elevation / 2;
4940                 }
4941                 else {
4942                         debug_error("Not support format %d", stream.format);
4943                         gst_memory_unmap(dataBlock, &mapinfo);
4944                         return GST_PAD_PROBE_OK;
4945                 }
4946
4947                 stream.bo[0] = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
4948                 if(!stream.bo[0]) {
4949                         debug_error("Fail to tbm_bo_alloc!!");
4950                         gst_memory_unmap(dataBlock, &mapinfo);
4951                         return GST_PAD_PROBE_OK;
4952                 }
4953                 thandle = tbm_bo_map(stream.bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
4954                 if(thandle.ptr && mapinfo.data)
4955                         memcpy(thandle.ptr, mapinfo.data, size);
4956                 else
4957                         debug_error("data pointer is wrong. dest : %p, src : %p",
4958                                         thandle.ptr, mapinfo.data);
4959
4960                 tbm_bo_unmap(stream.bo[0]);
4961         }
4962
4963         if (player->video_stream_cb) {
4964                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
4965         }
4966
4967         if (metaBlock) {
4968                 gst_memory_unmap(metaBlock, &mapinfo);
4969         }else {
4970                 gst_memory_unmap(dataBlock, &mapinfo);
4971                 tbm_bo_unref(stream.bo[0]);
4972         }
4973
4974         return GST_PAD_PROBE_OK;
4975 }
4976
4977 static int
4978 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket, gboolean use_video_stream)
4979 {
4980         gchar* video_csc = "videoconvert"; // default colorspace converter
4981         GList* element_bucket = *bucket;
4982
4983         return_val_if_fail(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
4984
4985         MMPLAYER_FENTER();
4986
4987         if (!player->set_mode.media_packet_video_stream && use_video_stream)
4988         {
4989                 if (player->set_mode.video_zc && strlen(player->ini.videoconverter_element) > 0)
4990                 {
4991                         video_csc = player->ini.videoconverter_element;
4992                 }
4993
4994                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
4995                 debug_log("using video converter: %s", video_csc);
4996
4997                 if ( !player->set_mode.video_zc)
4998                 {
4999                         gint width = 0;         //width of video
5000                         gint height = 0;                //height of video
5001                         GstCaps* video_caps = NULL;
5002                         GstStructure *structure = NULL;
5003
5004                         /* rotator, scaler and capsfilter */
5005                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5006                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "video scaler", TRUE, player);
5007                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CAPS, "capsfilter", "videocapsfilter", TRUE, player);
5008
5009                         /* get video stream caps parsed by demuxer */
5010
5011                         mm_attrs_get_int_by_name(player->attrs, "display_width", &width);
5012
5013                         if(width)
5014                                 structure = gst_structure_new("video/x-raw", "width", G_TYPE_INT, width, NULL);
5015
5016                         mm_attrs_get_int_by_name(player->attrs, "display_height", &height);
5017
5018                         if(structure && height) {
5019                                 gst_structure_set (structure, "height", G_TYPE_INT, height, NULL);
5020
5021                                 video_caps = gst_caps_new_full(structure, NULL);
5022                                 g_object_set (GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_CAPS].gst), "caps", video_caps, NULL );
5023                                 MMPLAYER_LOG_GST_CAPS_TYPE(video_caps);
5024                                 gst_caps_unref(video_caps);
5025                         }
5026                         else
5027                                 debug_error("fail to set capsfilter %p, width %d, height %d", structure, width, height);
5028
5029                         if(structure)
5030                                 gst_structure_free(structure);
5031
5032                 }
5033         }
5034         else
5035         {
5036                 MMDisplaySurfaceType surface_type = MM_DISPLAY_SURFACE_NULL;
5037                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", (int *)&surface_type);
5038
5039                 if (player->set_mode.video_zc)
5040                 {
5041                         if ( (surface_type == MM_DISPLAY_SURFACE_EVAS) && ( !strcmp(player->ini.videosink_element_evas, "evasimagesink")) )
5042                         {
5043                                 video_csc = player->ini.videoconverter_element;
5044                         }
5045                         else
5046                         {
5047                                 video_csc = "";
5048                         }
5049                 }
5050
5051                 if (video_csc && (strcmp(video_csc, "")))
5052                 {
5053                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5054                         debug_log("using video converter: %s", video_csc);
5055                 }
5056
5057                 /* set video rotator */
5058                 if ( !player->set_mode.video_zc )
5059                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5060
5061                 /* videoscaler */
5062                 #if !defined(__arm__)
5063                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "videoscaler", TRUE, player);
5064                 #endif
5065         }
5066
5067         *bucket = element_bucket;
5068         MMPLAYER_FLEAVE();
5069         return MM_ERROR_NONE;
5070
5071 ERROR:
5072         *bucket = NULL;
5073         MMPLAYER_FLEAVE();
5074         return MM_ERROR_PLAYER_INTERNAL;
5075 }
5076
5077 /**
5078  * This function is to create video pipeline.
5079  *
5080  * @param       player          [in]    handle of player
5081  *              caps            [in]    src caps of decoder
5082  *              surface_type    [in]    surface type for video rendering
5083  *
5084  * @return      This function returns zero on success.
5085  * @remark
5086  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5087  */
5088 /**
5089   * VIDEO PIPELINE
5090   * - x surface (arm/x86) : xvimagesink
5091   * - evas surface  (arm) : evaspixmapsink
5092   *                         fimcconvert ! evasimagesink
5093   * - evas surface  (x86) : videoconvertor ! videoflip ! evasimagesink
5094   */
5095 static int
5096 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5097 {
5098         GstPad *pad = NULL;
5099         MMHandleType attrs;
5100         GList*element_bucket = NULL;
5101         MMPlayerGstElement* first_element = NULL;
5102         MMPlayerGstElement* videobin = NULL;
5103         gchar *videosink_element = NULL;
5104
5105         MMPLAYER_FENTER();
5106
5107         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5108
5109         /* alloc handles */
5110         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5111         if ( !videobin )
5112         {
5113                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5114         }
5115
5116         player->pipeline->videobin = videobin;
5117
5118         attrs = MMPLAYER_GET_ATTRS(player);
5119         if ( !attrs )
5120         {
5121                 debug_error("cannot get content attribute");
5122                 return MM_ERROR_PLAYER_INTERNAL;
5123         }
5124
5125         /* create bin */
5126         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
5127         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
5128         if ( !videobin[MMPLAYER_V_BIN].gst )
5129         {
5130                 debug_error("failed to create videobin");
5131                 goto ERROR;
5132         }
5133
5134         if( player->use_video_stream ) // video stream callback, so send raw video data to application
5135         {
5136                 debug_log("using memsink\n");
5137
5138                 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, TRUE) != MM_ERROR_NONE)
5139                         goto ERROR;
5140
5141                 /* finally, create video sink. output will be BGRA8888. */
5142                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, "avsysmemsink", "videosink", TRUE, player);
5143
5144                 MMPLAYER_SIGNAL_CONNECT( player,
5145                                                                          videobin[MMPLAYER_V_SINK].gst,
5146                                                                          MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5147                                                                          "video-stream",
5148                                                                          G_CALLBACK(__mmplayer_videostream_cb),
5149                                                                          player );
5150         }
5151         else // render video data using sink plugin like xvimagesink
5152         {
5153                 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, FALSE) != MM_ERROR_NONE)
5154                         goto ERROR;
5155
5156                 /* set video sink */
5157                 switch (surface_type)
5158                 {
5159                         case MM_DISPLAY_SURFACE_X:
5160                                 if (strlen(player->ini.videosink_element_x) > 0)
5161                                         videosink_element = player->ini.videosink_element_x;
5162                                 else
5163                                         goto ERROR;
5164                                 break;
5165                         case MM_DISPLAY_SURFACE_EVAS:
5166                                 if (strlen(player->ini.videosink_element_evas) > 0)
5167                                         videosink_element = player->ini.videosink_element_evas;
5168                                 else
5169                                         goto ERROR;
5170                                 break;
5171                         case MM_DISPLAY_SURFACE_X_EXT:
5172                         {
5173                                 void *pixmap_id_cb = NULL;
5174                                 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
5175                                 if (pixmap_id_cb) /* this is used for the videoTextue(canvasTexture) overlay */
5176                                 {
5177                                         videosink_element = player->ini.videosink_element_x;
5178                                 }
5179                                 else
5180                                 {
5181                                         debug_error("something wrong.. callback function for getting pixmap id is null");
5182                                         goto ERROR;
5183                                 }
5184                                 break;
5185                         }
5186                         case MM_DISPLAY_SURFACE_NULL:
5187                                 if (strlen(player->ini.videosink_element_fake) > 0)
5188                                         videosink_element = player->ini.videosink_element_fake;
5189                                 else
5190                                         goto ERROR;
5191                                 break;
5192                         case MM_DISPLAY_SURFACE_REMOTE:
5193                                 if (strlen(player->ini.videosink_element_remote) > 0)
5194                                         videosink_element = player->ini.videosink_element_remote;
5195                                 else
5196                                         goto ERROR;
5197                                 break;
5198                         default:
5199                                 debug_error("unidentified surface type");
5200                                 goto ERROR;
5201                 }
5202
5203                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, videosink_element, TRUE, player);
5204                 debug_log("selected videosink name: %s", videosink_element);
5205
5206                 /* additional setting for sink plug-in */
5207                 switch (surface_type) {
5208                         case MM_DISPLAY_SURFACE_X_EXT:
5209                                 MMPLAYER_SIGNAL_CONNECT( player,
5210                                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5211                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5212                                                                                 "frame-render-error",
5213                                                                                 G_CALLBACK(__mmplayer_videoframe_render_error_cb),
5214                                                                                 player );
5215                                 debug_log("videoTexture usage, connect a signal handler for pixmap rendering error");
5216                                 break;
5217                         case MM_DISPLAY_SURFACE_REMOTE:
5218                         {
5219                                 char *stream_path = NULL;
5220                                 /* viceo_zc is the result of check ST12/SN12 */
5221                                 bool use_tbm = player->set_mode.video_zc;
5222                                 int attr_ret = mm_attrs_get_string_by_name (
5223                                                 attrs, "shm_stream_path", &stream_path );
5224                                 if(attr_ret == MM_ERROR_NONE && stream_path) {
5225                                         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5226                                                         "socket-path", stream_path,
5227                                                         "wait-for-connection", FALSE,
5228                                                         "sync", TRUE,
5229                                                         "perms", 0777,
5230                                                         "use-tbm", use_tbm,
5231                                                         NULL);
5232                                         debug_log("set path \"%s\" for shmsink", stream_path);
5233                                 } else {
5234                                         debug_error("Not set attribute of shm_stream_path");
5235                                         goto ERROR;
5236                                 }
5237                                 break;
5238                         }
5239                         default:
5240                                 break;
5241                 }
5242         }
5243
5244         if (_mmplayer_update_video_param(player) != MM_ERROR_NONE)
5245                 goto ERROR;
5246
5247         if (videobin[MMPLAYER_V_SINK].gst)
5248         {
5249                 GstPad *sink_pad = NULL;
5250                 sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
5251                 if (sink_pad)
5252                 {
5253                         MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5254                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
5255                         gst_object_unref (GST_OBJECT(sink_pad));
5256                 }
5257                 else
5258                 {
5259                         debug_warning("failed to get sink pad from videosink\n");
5260                 }
5261         }
5262
5263         /* store it as it's sink element */
5264         __mmplayer_add_sink( player, videobin[MMPLAYER_V_SINK].gst );
5265
5266         /* adding created elements to bin */
5267         if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket) )
5268         {
5269                 debug_error("failed to add elements\n");
5270                 goto ERROR;
5271         }
5272
5273         /* Linking elements in the bucket by added order */
5274         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5275         {
5276                 debug_error("failed to link elements\n");
5277                 goto ERROR;
5278         }
5279
5280         /* get first element's sinkpad for creating ghostpad */
5281         first_element = (MMPlayerGstElement *)element_bucket->data;
5282         if ( !first_element )
5283         {
5284                 debug_error("failed to get first element from bucket\n");
5285                 goto ERROR;
5286         }
5287
5288         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5289         if ( !pad )
5290         {
5291                 debug_error("failed to get pad from first element\n");
5292                 goto ERROR;
5293         }
5294
5295         /* create ghostpad */
5296         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
5297         if ( FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
5298         {
5299                 debug_error("failed to add ghostpad to videobin\n");
5300                 goto ERROR;
5301         }
5302         gst_object_unref(pad);
5303
5304         /* done. free allocated variables */
5305         g_list_free(element_bucket);
5306
5307         mm_attrs_set_int_by_name(attrs, "content_video_found", TRUE);
5308
5309         if(surface_type == MM_DISPLAY_SURFACE_REMOTE &&
5310                         MMPLAYER_IS_HTTP_PD(player) )
5311         {
5312                 MMMessageParamType msg = {0, };
5313                 msg.data = gst_caps_to_string(caps);
5314                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_VIDEO_BIN_CREATED, &msg );
5315         }
5316
5317         MMPLAYER_FLEAVE();
5318
5319         return MM_ERROR_NONE;
5320
5321 ERROR:
5322         debug_error("ERROR : releasing videobin\n");
5323
5324         g_list_free( element_bucket );
5325
5326         if (pad)
5327                 gst_object_unref(GST_OBJECT(pad));
5328
5329         /* release videobin with it's childs */
5330         if ( videobin[MMPLAYER_V_BIN].gst )
5331         {
5332                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
5333         }
5334
5335
5336         MMPLAYER_FREEIF( videobin );
5337
5338         player->pipeline->videobin = NULL;
5339
5340         return MM_ERROR_PLAYER_INTERNAL;
5341 }
5342
5343 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
5344 {
5345         GList *element_bucket = NULL;
5346         MMPlayerGstElement *textbin = player->pipeline->textbin;
5347
5348         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", TRUE, player);
5349         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", TRUE, player);
5350         g_object_set (G_OBJECT (textbin[MMPLAYER_T_IDENTITY].gst),
5351                                                         "signal-handoffs", FALSE,
5352                                                         NULL);
5353
5354         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
5355         MMPLAYER_SIGNAL_CONNECT( player,
5356                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
5357                                                         MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
5358                                                         "handoff",
5359                                                         G_CALLBACK(__mmplayer_update_subtitle),
5360                                                         (gpointer)player );
5361
5362         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
5363         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
5364         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
5365
5366         if (!player->play_subtitle)
5367         {
5368                 debug_log ("add textbin sink as sink element of whole pipeline.\n");
5369                 __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
5370         }
5371
5372         /* adding created elements to bin */
5373         debug_log("adding created elements to bin\n");
5374         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
5375         {
5376                 debug_error("failed to add elements\n");
5377                 goto ERROR;
5378         }
5379
5380         /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
5381         GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
5382         GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
5383
5384         /* linking elements in the bucket by added order. */
5385         debug_log("Linking elements in the bucket by added order.\n");
5386         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5387         {
5388                 debug_error("failed to link elements\n");
5389                 goto ERROR;
5390         }
5391
5392         /* done. free allocated variables */
5393         g_list_free(element_bucket);
5394
5395         if (textbin[MMPLAYER_T_QUEUE].gst)
5396         {
5397                 GstPad *pad = NULL;
5398                 GstPad *ghostpad = NULL;
5399
5400                 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_QUEUE].gst), "sink");
5401                 if (!pad)
5402                 {
5403                         debug_error("failed to get video pad of textbin\n");
5404                         return MM_ERROR_PLAYER_INTERNAL;
5405                 }
5406
5407                 ghostpad = gst_ghost_pad_new("text_sink", pad);
5408                 gst_object_unref(pad);
5409
5410                 if (!ghostpad)
5411                 {
5412                         debug_error("failed to create ghostpad of textbin\n");
5413                         goto ERROR;
5414                 }
5415
5416                 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad))
5417                 {
5418                         debug_error("failed to add ghostpad to textbin\n");
5419                         goto ERROR;
5420                 }
5421         }
5422
5423         return MM_ERROR_NONE;
5424
5425 ERROR:
5426         g_list_free(element_bucket);
5427
5428         return MM_ERROR_PLAYER_INTERNAL;
5429 }
5430
5431 static int __mmplayer_gst_create_text_pipeline(mm_player_t* player)
5432 {
5433         MMPlayerGstElement *textbin = NULL;
5434         GList *element_bucket = NULL;
5435         gint i = 0;
5436
5437         MMPLAYER_FENTER();
5438
5439         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5440
5441         /* alloc handles */
5442         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
5443         if ( ! textbin )
5444         {
5445                 debug_error("failed to allocate memory for textbin\n");
5446                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5447         }
5448
5449         /* create bin */
5450         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
5451         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
5452         if ( !textbin[MMPLAYER_T_BIN].gst )
5453         {
5454                 debug_error("failed to create textbin\n");
5455                 goto ERROR;
5456         }
5457
5458         /* take it */
5459         player->pipeline->textbin = textbin;
5460
5461         /* fakesink */
5462         if (player->use_textoverlay)
5463         {
5464                 debug_log ("use textoverlay for displaying \n");
5465
5466                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_QUEUE, "queue", "text_t_queue", textbin[MMPLAYER_T_BIN].gst, player);
5467
5468                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_QUEUE, "queue", "text_v_queue", textbin[MMPLAYER_T_BIN].gst, player);
5469
5470                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_CONVERTER, "fimcconvert", "text_v_converter", textbin[MMPLAYER_T_BIN].gst, player);
5471
5472                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_OVERLAY, "textoverlay", "text_overlay", textbin[MMPLAYER_T_BIN].gst, player);
5473
5474                 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_QUEUE].gst, "src", textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "sink"))
5475                 {
5476                         debug_error("failed to link queue and converter\n");
5477                         goto ERROR;
5478                 }
5479
5480                 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "video_sink"))
5481                 {
5482                         debug_error("failed to link queue and textoverlay\n");
5483                         goto ERROR;
5484                 }
5485
5486                 if (!gst_element_link_pads (textbin[MMPLAYER_T_QUEUE].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "text_sink"))
5487                 {
5488                         debug_error("failed to link queue and textoverlay\n");
5489                         goto ERROR;
5490                 }
5491         }
5492         else
5493         {
5494                 int surface_type = 0;
5495
5496                 debug_log ("use subtitle message for displaying \n");
5497
5498                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
5499
5500                 switch(surface_type)
5501                 {
5502                         case MM_DISPLAY_SURFACE_X:
5503                         case MM_DISPLAY_SURFACE_EVAS:
5504                         case MM_DISPLAY_SURFACE_GL:
5505                         case MM_DISPLAY_SURFACE_NULL:
5506                         case MM_DISPLAY_SURFACE_X_EXT:
5507                         case MM_DISPLAY_SURFACE_REMOTE:
5508                                 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE)
5509                                 {
5510                                         debug_error("failed to make plain text elements\n");
5511                                         goto ERROR;
5512                                 }
5513                                 break;
5514
5515                         default:
5516                                 break;
5517                 }
5518         }
5519
5520         MMPLAYER_FLEAVE();
5521
5522         return MM_ERROR_NONE;
5523
5524 ERROR:
5525
5526         debug_log("ERROR : releasing textbin\n");
5527
5528         g_list_free( element_bucket );
5529
5530         /* release element which are not added to bin */
5531         for ( i = 1; i < MMPLAYER_T_NUM; i++ )  /* NOTE : skip bin */
5532         {
5533                 if ( textbin[i].gst )
5534                 {
5535                         GstObject* parent = NULL;
5536                         parent = gst_element_get_parent( textbin[i].gst );
5537
5538                         if ( !parent )
5539                         {
5540                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
5541                                 textbin[i].gst = NULL;
5542                         }
5543                         else
5544                         {
5545                                 gst_object_unref(GST_OBJECT(parent));
5546                         }
5547                 }
5548         }
5549
5550         /* release textbin with it's childs */
5551         if ( textbin[MMPLAYER_T_BIN].gst )
5552         {
5553                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
5554         }
5555
5556         MMPLAYER_FREEIF( textbin );
5557
5558         player->pipeline->textbin = NULL;
5559
5560         return MM_ERROR_PLAYER_INTERNAL;
5561 }
5562
5563
5564 static int
5565 __mmplayer_gst_create_subtitle_src(mm_player_t* player)
5566 {
5567         MMPlayerGstElement* mainbin = NULL;
5568         MMHandleType attrs = 0;
5569         GstElement *subsrc = NULL;
5570         GstElement *subparse = NULL;
5571         gchar *subtitle_uri =NULL;
5572         const gchar *charset = NULL;
5573         GstPad *pad = NULL;
5574
5575         MMPLAYER_FENTER();
5576
5577         /* get mainbin */
5578         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5579
5580         mainbin = player->pipeline->mainbin;
5581
5582         attrs = MMPLAYER_GET_ATTRS(player);
5583         if ( !attrs )
5584         {
5585                 debug_error("cannot get content attribute\n");
5586                 return MM_ERROR_PLAYER_INTERNAL;
5587         }
5588
5589         mm_attrs_get_string_by_name ( attrs, "subtitle_uri", &subtitle_uri );
5590         if ( !subtitle_uri || strlen(subtitle_uri) < 1)
5591         {
5592                 debug_error("subtitle uri is not proper filepath.\n");
5593                 return MM_ERROR_PLAYER_INVALID_URI;
5594         }
5595         debug_log("subtitle file path is [%s].\n", subtitle_uri);
5596
5597
5598         /* create the subtitle source */
5599         subsrc = gst_element_factory_make("filesrc", "subtitle_source");
5600         if ( !subsrc )
5601         {
5602                 debug_error ( "failed to create filesrc element\n" );
5603                 goto ERROR;
5604         }
5605         g_object_set(G_OBJECT (subsrc), "location", subtitle_uri, NULL);
5606
5607         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
5608         mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
5609
5610         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc))
5611         {
5612                 debug_warning("failed to add queue\n");
5613                 goto ERROR;
5614         }
5615
5616         /* subparse */
5617         subparse = gst_element_factory_make("subparse", "subtitle_parser");
5618         if ( !subparse )
5619         {
5620                 debug_error ( "failed to create subparse element\n" );
5621                 goto ERROR;
5622         }
5623
5624         charset = util_get_charset(subtitle_uri);
5625         if (charset)
5626         {
5627                 debug_log ("detected charset is %s\n", charset );
5628                 g_object_set (G_OBJECT (subparse), "subtitle-encoding", charset, NULL);
5629         }
5630
5631         mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE;
5632         mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
5633
5634         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse))
5635         {
5636                 debug_warning("failed to add subparse\n");
5637                 goto ERROR;
5638         }
5639
5640         if (!gst_element_link_pads (subsrc, "src", subparse, "sink"))
5641         {
5642                 debug_warning("failed to link subsrc and subparse\n");
5643                 goto ERROR;
5644         }
5645
5646         player->play_subtitle = TRUE;
5647         player->adjust_subtitle_pos = 0;
5648
5649         debug_log ("play subtitle using subtitle file\n");
5650
5651         if (player->pipeline->textbin == NULL)
5652         {
5653                 if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
5654                 {
5655                         debug_error("failed to create textbin. continuing without text\n");
5656                         goto ERROR;
5657                 }
5658
5659                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst)))
5660                 {
5661                         debug_warning("failed to add textbin\n");
5662                         goto ERROR;
5663                 }
5664
5665                 debug_log ("link text input selector and textbin ghost pad");
5666
5667                 player->textsink_linked = 1;
5668                 player->external_text_idx = 0;
5669                 debug_msg("player->textsink_linked set to 1\n");
5670         }
5671         else
5672         {
5673                 debug_log("text bin has been created. reuse it.");
5674                 player->external_text_idx = 1;
5675         }
5676
5677         if (!gst_element_link_pads (subparse, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink"))
5678         {
5679                 debug_warning("failed to link subparse and textbin\n");
5680                 goto ERROR;
5681         }
5682
5683         pad = gst_element_get_static_pad (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
5684
5685         if (!pad)
5686         {
5687                 debug_error("failed to get sink pad from textsink to probe data");
5688                 return MM_ERROR_PLAYER_INTERNAL;
5689         }
5690
5691         gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
5692                                 __mmplayer_subtitle_adjust_position_probe, player, NULL);
5693
5694         gst_object_unref(pad);
5695         pad=NULL;
5696
5697         /* create dot. for debugging */
5698         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-with-subtitle" );
5699         MMPLAYER_FLEAVE();
5700
5701         return MM_ERROR_NONE;
5702
5703 ERROR:
5704         player->textsink_linked = 0;
5705         return MM_ERROR_PLAYER_INTERNAL;
5706 }
5707
5708 gboolean
5709 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5710 {
5711         mm_player_t* player = (mm_player_t*) data;
5712         MMMessageParamType msg = {0, };
5713         GstClockTime duration = 0;
5714         gpointer text = NULL;
5715         guint text_size = 0;
5716         gboolean ret = TRUE;
5717         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5718
5719         MMPLAYER_FENTER();
5720
5721         return_val_if_fail ( player, FALSE );
5722         return_val_if_fail ( buffer, FALSE );
5723
5724         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
5725         text = g_memdup(mapinfo.data, mapinfo.size);
5726         text_size = mapinfo.size;
5727         duration = GST_BUFFER_DURATION(buffer);
5728
5729
5730         if ( player->set_mode.subtitle_off )
5731         {
5732                 debug_log("subtitle is OFF.\n" );
5733                 return TRUE;
5734         }
5735
5736         if ( !text || (text_size == 0))
5737         {
5738                 debug_log("There is no subtitle to be displayed.\n" );
5739                 return TRUE;
5740         }
5741
5742         msg.data = (void *) text;
5743         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
5744
5745         debug_log("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
5746
5747         MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
5748         gst_buffer_unmap(buffer, &mapinfo);
5749
5750         MMPLAYER_FLEAVE();
5751
5752         return ret;
5753 }
5754
5755 static GstPadProbeReturn
5756 __mmplayer_subtitle_adjust_position_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
5757
5758 {
5759         mm_player_t *player = (mm_player_t *) u_data;
5760         GstClockTime cur_timestamp = 0;
5761         gint64 adjusted_timestamp = 0;
5762         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
5763
5764         return_val_if_fail ( player, FALSE );
5765
5766         if ( player->set_mode.subtitle_off )
5767         {
5768                 debug_log("subtitle is OFF.\n" );
5769                 return TRUE;
5770         }
5771
5772         if (player->adjust_subtitle_pos == 0 )
5773         {
5774                 debug_log("nothing to do");
5775                 return TRUE;
5776         }
5777
5778         cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
5779         adjusted_timestamp = (gint64) cur_timestamp + ((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
5780
5781         if ( adjusted_timestamp < 0)
5782         {
5783                 debug_log("adjusted_timestamp under zero");
5784                 MMPLAYER_FLEAVE();
5785                 return FALSE;
5786         }
5787
5788         GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
5789         debug_log("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
5790                                 GST_TIME_ARGS(cur_timestamp),
5791                                 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
5792
5793         return GST_PAD_PROBE_OK;
5794 }
5795 static int      __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
5796 {
5797         MMPLAYER_FENTER();
5798
5799         /* check player and subtitlebin are created */
5800         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5801         return_val_if_fail ( player->play_subtitle, MM_ERROR_NOT_SUPPORT_API );
5802
5803         if (position == 0)
5804         {
5805                 debug_log ("nothing to do\n");
5806                 MMPLAYER_FLEAVE();
5807                 return MM_ERROR_NONE;
5808         }
5809
5810         switch (format)
5811         {
5812                 case MM_PLAYER_POS_FORMAT_TIME:
5813                 {
5814                         /* check current postion */
5815                         player->adjust_subtitle_pos = position;
5816
5817                         debug_log("save adjust_subtitle_pos in player") ;
5818                 }
5819                 break;
5820
5821                 default:
5822                 {
5823                         debug_warning("invalid format.\n");
5824                         MMPLAYER_FLEAVE();
5825                         return MM_ERROR_INVALID_ARGUMENT;
5826                 }
5827         }
5828
5829         MMPLAYER_FLEAVE();
5830
5831         return MM_ERROR_NONE;
5832 }
5833 static int __gst_adjust_video_position(mm_player_t* player, int offset)
5834 {
5835         MMPLAYER_FENTER();
5836         debug_log("adjusting video_pos in player") ;
5837         int current_pos = 0;
5838         /* check player and videobin are created */
5839         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5840         if ( !player->pipeline->videobin ||
5841                         !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
5842         {
5843                 debug_log("no video pipeline or sink is there");
5844                 return MM_ERROR_PLAYER_INVALID_STATE ;
5845         }
5846         if (offset == 0)
5847         {
5848                 debug_log ("nothing to do\n");
5849                 MMPLAYER_FLEAVE();
5850                 return MM_ERROR_NONE;
5851         }
5852         if(__gst_get_position ( player, MM_PLAYER_POS_FORMAT_TIME, (unsigned long*)&current_pos ) != MM_ERROR_NONE )
5853         {
5854                 debug_log("failed to get current position");
5855                 return MM_ERROR_PLAYER_INTERNAL;
5856         }
5857         if ( (current_pos - offset ) < GST_TIME_AS_MSECONDS(player->duration) )
5858         {
5859                 debug_log("enter video delay is valid");
5860         }
5861         else {
5862                 debug_log("enter video delay is crossing content boundary");
5863                 return MM_ERROR_INVALID_ARGUMENT ;
5864         }
5865         g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst),"ts-offset",((gint64) offset * G_GINT64_CONSTANT(1000000)),NULL);
5866         debug_log("video delay has been done");
5867         MMPLAYER_FLEAVE();
5868
5869         return MM_ERROR_NONE;
5870 }
5871
5872 static void
5873 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data) // @
5874 {
5875         GstElement *appsrc = element;
5876         tBuffer *buf = (tBuffer *)user_data;
5877         GstBuffer *buffer = NULL;
5878         GstFlowReturn ret = GST_FLOW_OK;
5879         gint len = size;
5880
5881         return_if_fail ( element );
5882         return_if_fail ( buf );
5883
5884         buffer = gst_buffer_new ();
5885
5886         if (buf->offset >= buf->len)
5887         {
5888                 debug_log("call eos appsrc\n");
5889                 g_signal_emit_by_name (appsrc, "end-of-stream", &ret);
5890                 return;
5891         }
5892
5893         if ( buf->len - buf->offset < size)
5894         {
5895                 len = buf->len - buf->offset + buf->offset;
5896         }
5897
5898         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));
5899         GST_BUFFER_OFFSET(buffer) = buf->offset;
5900         GST_BUFFER_OFFSET_END(buffer) = buf->offset + len;
5901
5902         //debug_log("feed buffer %p, offset %u-%u length %u\n", buffer, buf->offset, buf->len,len);
5903         g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
5904
5905         buf->offset += len;
5906 }
5907
5908 static gboolean
5909 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data) // @
5910 {
5911         tBuffer *buf = (tBuffer *)user_data;
5912
5913         return_val_if_fail ( buf, FALSE );
5914
5915         buf->offset  = (int)size;
5916
5917         return TRUE;
5918 }
5919
5920 static void
5921 __gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data) // @
5922 {
5923         mm_player_t *player  = (mm_player_t*)user_data;
5924         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
5925
5926         return_if_fail ( player );
5927
5928         debug_msg("app-src: feed data\n");
5929
5930         if (player->media_stream_buffer_status_cb[type])
5931                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
5932 }
5933
5934 static gboolean
5935 __gst_appsrc_seek_data(GstElement *element, guint64 offset, gpointer user_data) // @
5936 {
5937         mm_player_t *player  = (mm_player_t*)user_data;
5938         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
5939
5940         return_val_if_fail ( player, FALSE );
5941
5942         debug_msg("app-src: seek data\n");
5943
5944         if(player->media_stream_seek_data_cb[type])
5945                 player->media_stream_seek_data_cb[type](type, offset, player->buffer_cb_user_param);
5946
5947         return TRUE;
5948 }
5949
5950
5951 static gboolean
5952 __gst_appsrc_enough_data(GstElement *element, gpointer user_data) // @
5953 {
5954         mm_player_t *player  = (mm_player_t*)user_data;
5955         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
5956
5957         return_val_if_fail ( player, FALSE );
5958
5959         debug_msg("app-src: enough data:%p\n", player->media_stream_buffer_status_cb[type]);
5960
5961         if (player->media_stream_buffer_status_cb[type])
5962                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
5963
5964         return TRUE;
5965 }
5966
5967 int
5968 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
5969 {
5970         mm_player_t* player = (mm_player_t*)hplayer;
5971         GstBuffer *buffer = NULL;
5972         GstFlowReturn gst_ret = GST_FLOW_OK;
5973         int ret = MM_ERROR_NONE;
5974 //      gint len = size;
5975
5976         MMPLAYER_FENTER();
5977
5978         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5979
5980         /* check current state */
5981 //      MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
5982
5983
5984         /* NOTE : we should check and create pipeline again if not created as we destroy
5985          * whole pipeline when stopping in streamming playback
5986          */
5987         if ( ! player->pipeline )
5988         {
5989                 if ( MM_ERROR_NONE != __gst_realize( player ) )
5990                 {
5991                         debug_error("failed to realize before starting. only in streamming\n");
5992                         return MM_ERROR_PLAYER_INTERNAL;
5993                 }
5994         }
5995
5996         debug_msg("app-src: pushing data\n");
5997
5998         if ( buf == NULL )
5999         {
6000                 debug_error("buf is null\n");
6001                 return MM_ERROR_NONE;
6002         }
6003
6004         buffer = gst_buffer_new ();
6005
6006         if (size <= 0)
6007         {
6008                 debug_log("call eos appsrc\n");
6009                 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
6010                 return MM_ERROR_NONE;
6011         }
6012
6013         //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));
6014
6015         debug_log("feed buffer %p, length %u\n", buf, size);
6016         g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
6017
6018         MMPLAYER_FLEAVE();
6019
6020         return ret;
6021 }
6022
6023 static GstBusSyncReply
6024 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
6025 {
6026         mm_player_t *player = (mm_player_t *)data;
6027         GstBusSyncReply reply = GST_BUS_DROP;
6028
6029         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
6030         {
6031                 debug_error("player pipeline handle is null");
6032                 return GST_BUS_PASS;
6033         }
6034
6035         if (!__mmplayer_check_useful_message(player, message))
6036         {
6037                 gst_message_unref (message);
6038                 return GST_BUS_DROP;
6039         }
6040
6041         switch (GST_MESSAGE_TYPE (message))
6042         {
6043                 case GST_MESSAGE_STATE_CHANGED:
6044                         /* post directly for fast launch */
6045                         if (player->sync_handler) {
6046                                 __mmplayer_gst_callback(NULL, message, player);
6047                                 reply = GST_BUS_DROP;
6048                         }
6049                         else {
6050                                 reply = GST_BUS_PASS;
6051                         }
6052                         break;
6053                 case GST_MESSAGE_TAG:
6054                         __mmplayer_gst_extract_tag_from_msg(player, message);
6055
6056                         #if 0 // debug
6057                         {
6058                                 GstTagList *tags = NULL;
6059
6060                                 gst_message_parse_tag (message, &tags);
6061                                 if (tags) {
6062                                         debug_error("TAGS received from element \"%s\".\n",
6063                                         GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
6064
6065                                         gst_tag_list_foreach (tags, print_tag, NULL);
6066                                         gst_tag_list_free (tags);
6067                                         tags = NULL;
6068                                 }
6069                                 break;
6070                         }
6071                         #endif
6072                         break;
6073
6074                 case GST_MESSAGE_DURATION_CHANGED:
6075                         __mmplayer_gst_handle_duration(player, message);
6076                         break;
6077                 case GST_MESSAGE_ASYNC_DONE:
6078                         /* NOTE:Don't call gst_callback directly
6079                          * because previous frame can be showed even though this message is received for seek.
6080                          */
6081                 default:
6082                         reply = GST_BUS_PASS;
6083                         break;
6084         }
6085
6086         if (reply == GST_BUS_DROP)
6087                 gst_message_unref (message);
6088
6089         return reply;
6090 }
6091
6092 static gboolean
6093 __mmplayer_gst_create_decoder ( mm_player_t *player,
6094                                                                 MMPlayerTrackType track,
6095                                                                 GstPad* srcpad,
6096                                                                 enum MainElementID elemId,
6097                                                                 const gchar* name)
6098 {
6099         gboolean ret = TRUE;
6100         GstPad *sinkpad = NULL;
6101
6102         MMPLAYER_FENTER();
6103
6104         return_val_if_fail( player &&
6105                                                 player->pipeline &&
6106                                                 player->pipeline->mainbin, FALSE);
6107         return_val_if_fail((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE);
6108         return_val_if_fail(srcpad, FALSE);
6109         return_val_if_fail((player->pipeline->mainbin[elemId].gst == NULL), FALSE);
6110
6111         GstElement *decodebin = NULL;
6112         GstCaps *dec_caps = NULL;
6113
6114         /* create decodebin */
6115         decodebin = gst_element_factory_make("decodebin", name);
6116
6117         if (!decodebin)
6118         {
6119                 debug_error("error : fail to create decodebin for %d decoder\n", track);
6120                 ret = FALSE;
6121                 goto ERROR;
6122         }
6123
6124         /* raw pad handling signal */
6125         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6126                                                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
6127
6128         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
6129         before looking for any elements that can handle that stream.*/
6130         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
6131                                                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
6132
6133         /* This signal is emitted when a element is added to the bin.*/
6134         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
6135                                                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
6136
6137         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), decodebin))
6138         {
6139                 debug_error("failed to add new decodebin\n");
6140                 ret = FALSE;
6141                 goto ERROR;
6142         }
6143
6144         dec_caps = gst_pad_query_caps (srcpad, NULL);
6145         if (dec_caps)
6146         {
6147                 //debug_log ("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
6148                 g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
6149                 gst_caps_unref(dec_caps);
6150         }
6151
6152         player->pipeline->mainbin[elemId].id = elemId;
6153         player->pipeline->mainbin[elemId].gst = decodebin;
6154
6155         sinkpad = gst_element_get_static_pad (decodebin, "sink");
6156
6157         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
6158         {
6159                 debug_warning ("failed to link [%s:%s] to decoder\n", GST_DEBUG_PAD_NAME(srcpad));
6160                 gst_object_unref (GST_OBJECT(decodebin));
6161         }
6162
6163         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (decodebin))
6164         {
6165                 debug_error("failed to sync second level decodebin state with parent\n");
6166         }
6167
6168         debug_log("Total num of %d tracks = %d \n", track, player->selector[track].total_track_num);
6169
6170 ERROR:
6171         if (sinkpad)
6172         {
6173                 gst_object_unref ( GST_OBJECT(sinkpad) );
6174                 sinkpad = NULL;
6175         }
6176         MMPLAYER_FLEAVE();
6177
6178         return ret;
6179 }
6180
6181 /**
6182  * This function is to create  audio or video pipeline for playing.
6183  *
6184  * @param       player          [in]    handle of player
6185  *
6186  * @return      This function returns zero on success.
6187  * @remark
6188  * @see
6189  */
6190 static int
6191 __mmplayer_gst_create_pipeline(mm_player_t* player) // @
6192 {
6193         GstBus  *bus = NULL;
6194         MMPlayerGstElement *mainbin = NULL;
6195         MMHandleType attrs = 0;
6196         GstElement* element = NULL;
6197         GstElement* elem_src_audio = NULL;
6198         GstElement* elem_src_subtitle = NULL;
6199         GstElement* es_video_queue = NULL;
6200         GstElement* es_audio_queue = NULL;
6201         GstElement* es_subtitle_queue = NULL;
6202         GList* element_bucket = NULL;
6203         gboolean need_state_holder = TRUE;
6204         gint i = 0;
6205 #ifdef SW_CODEC_ONLY
6206         int surface_type = 0;
6207 #endif
6208         MMPLAYER_FENTER();
6209
6210         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6211
6212         /* get profile attribute */
6213         attrs = MMPLAYER_GET_ATTRS(player);
6214         if ( !attrs )
6215         {
6216                 debug_error("cannot get content attribute\n");
6217                 goto INIT_ERROR;
6218         }
6219
6220         /* create pipeline handles */
6221         if ( player->pipeline )
6222         {
6223                 debug_warning("pipeline should be released before create new one\n");
6224                 goto INIT_ERROR;
6225         }
6226
6227         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0( sizeof(MMPlayerGstPipelineInfo) );
6228         if (player->pipeline == NULL)
6229                 goto INIT_ERROR;
6230
6231         memset( player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo) );
6232
6233
6234         /* create mainbin */
6235         mainbin = (MMPlayerGstElement*) g_malloc0( sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM );
6236         if (mainbin == NULL)
6237                 goto INIT_ERROR;
6238
6239         memset( mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
6240
6241         /* create pipeline */
6242         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
6243         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
6244         if ( ! mainbin[MMPLAYER_M_PIPE].gst )
6245         {
6246                 debug_error("failed to create pipeline\n");
6247                 goto INIT_ERROR;
6248         }
6249         player->demux_pad_index = 0;
6250         player->subtitle_language_list = NULL;
6251
6252         player->is_subtitle_force_drop = FALSE;
6253         player->last_multiwin_status = FALSE;
6254
6255         _mmplayer_track_initialize(player);
6256
6257         /* create source element */
6258         switch ( player->profile.uri_type )
6259         {
6260                 /* rtsp streamming */
6261                 case MM_PLAYER_URI_TYPE_URL_RTSP:
6262                 {
6263                         gint network_bandwidth;
6264                         gchar *user_agent, *wap_profile;
6265
6266                         element = gst_element_factory_make("rtspsrc", "rtsp source");
6267
6268                         if ( !element )
6269                         {
6270                                 debug_error("failed to create streaming source element\n");
6271                                 break;
6272                         }
6273
6274                         /* make it zero */
6275                         network_bandwidth = 0;
6276                         user_agent = wap_profile = NULL;
6277
6278                         /* get attribute */
6279                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
6280                         mm_attrs_get_string_by_name ( attrs,"streaming_wap_profile", &wap_profile );
6281                         mm_attrs_get_int_by_name ( attrs, "streaming_network_bandwidth", &network_bandwidth );
6282
6283                         secure_debug_log("user_agent : %s\n", user_agent);
6284                         secure_debug_log("wap_profile : %s\n", wap_profile);
6285
6286                         /* setting property to streaming source */
6287                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6288                         if ( user_agent )
6289                                 g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6290                         if ( wap_profile )
6291                                 g_object_set(G_OBJECT(element), "wap_profile", wap_profile, NULL);
6292
6293                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6294                                 G_CALLBACK (__mmplayer_gst_rtp_dynamic_pad), player );
6295                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
6296                                 G_CALLBACK (__mmplayer_gst_rtp_no_more_pads), player );
6297
6298                         player->use_decodebin = FALSE;
6299                 }
6300                 break;
6301
6302                 /* http streaming*/
6303                 case MM_PLAYER_URI_TYPE_URL_HTTP:
6304                 {
6305                         gchar *user_agent, *proxy, *cookies, **cookie_list;
6306                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6307                         user_agent = proxy = cookies = NULL;
6308                         cookie_list = NULL;
6309                         gint mode = MM_PLAYER_PD_MODE_NONE;
6310
6311                         mm_attrs_get_int_by_name ( attrs, "pd_mode", &mode );
6312
6313                         player->pd_mode = mode;
6314
6315                         debug_log("http playback, PD mode : %d\n", player->pd_mode);
6316
6317                         if ( ! MMPLAYER_IS_HTTP_PD(player) )
6318                         {
6319                                 element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
6320                                 if ( !element )
6321                                 {
6322                                         debug_error("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
6323                                         break;
6324                                 }
6325                                 debug_log("using http streamming source [%s].\n", player->ini.httpsrc_element);
6326
6327                                 /* get attribute */
6328                                 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
6329                                 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
6330                                 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
6331                                 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
6332
6333                                 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
6334                                         (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
6335                                 {
6336                                         debug_log("get timeout from ini\n");
6337                                         http_timeout = player->ini.http_timeout;
6338                                 }
6339
6340                                 /* get attribute */
6341                                 secure_debug_log("location : %s\n", player->profile.uri);
6342                                 secure_debug_log("cookies : %s\n", cookies);
6343                                 secure_debug_log("proxy : %s\n", proxy);
6344                                 secure_debug_log("user_agent :  %s\n",  user_agent);
6345                                 debug_log("timeout : %d\n",  http_timeout);
6346
6347                                 /* setting property to streaming source */
6348                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6349                                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6350                                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
6351
6352                                 /* check if prosy is vailid or not */
6353                                 if ( util_check_valid_url ( proxy ) )
6354                                         g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
6355                                 /* parsing cookies */
6356                                 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
6357                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
6358                                 if ( user_agent )
6359                                         g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6360
6361                                 if ( MMPLAYER_URL_HAS_DASH_SUFFIX(player) )
6362                                 {
6363                                         debug_warning("it's dash. and it's still experimental feature.");
6364                                 }
6365                         }
6366                         else // progressive download
6367                         {
6368                                 gchar* location = NULL;
6369
6370                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
6371                                 {
6372                                         gchar *path = NULL;
6373
6374                                         mm_attrs_get_string_by_name ( attrs, "pd_location", &path );
6375
6376                                         MMPLAYER_FREEIF(player->pd_file_save_path);
6377
6378                                         debug_log("PD Location : %s\n", path);
6379
6380                                         if ( path )
6381                                         {
6382                                                 player->pd_file_save_path = g_strdup(path);
6383                                         }
6384                                         else
6385                                         {
6386                                                 debug_error("can't find pd location so, it should be set \n");
6387                                                 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
6388                                         }
6389                                 }
6390
6391                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
6392                                 if ( !element )
6393                                 {
6394                                         debug_error("failed to create PD push source element[%s].\n", "pdpushsrc");
6395                                         break;
6396                                 }
6397
6398                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
6399                                         g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
6400                                 else
6401                                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6402
6403                                 g_object_get(element, "location", &location, NULL);
6404                                 debug_log("PD_LOCATION [%s].\n", location);
6405                                 if (location)
6406                                         g_free (location);
6407                         }
6408                 }
6409                 break;
6410
6411                 /* file source */
6412                 case MM_PLAYER_URI_TYPE_FILE:
6413                 {
6414
6415                         debug_log("using filesrc for 'file://' handler.\n");
6416
6417                         element = gst_element_factory_make("filesrc", "source");
6418
6419                         if ( !element )
6420                         {
6421                                 debug_error("failed to create filesrc\n");
6422                                 break;
6423                         }
6424
6425                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
6426                         //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL);
6427                 }
6428                 break;
6429
6430                 case MM_PLAYER_URI_TYPE_SS:
6431                 {
6432                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6433                         element = gst_element_factory_make("souphttpsrc", "http streaming source");
6434                         if ( !element )
6435                         {
6436                                 debug_error("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
6437                                 break;
6438                         }
6439
6440                         mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
6441
6442                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
6443                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
6444                         {
6445                                 debug_log("get timeout from ini\n");
6446                                 http_timeout = player->ini.http_timeout;
6447                         }
6448
6449                         /* setting property to streaming source */
6450                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6451                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6452                 }
6453                 break;
6454
6455                 /* appsrc */
6456                 case MM_PLAYER_URI_TYPE_BUFF:
6457                 {
6458                         guint64 stream_type = GST_APP_STREAM_TYPE_STREAM;
6459
6460                         debug_log("mem src is selected\n");
6461
6462                         element = gst_element_factory_make("appsrc", "buff-source");
6463                         if ( !element )
6464                         {
6465                                 debug_error("failed to create appsrc element\n");
6466                                 break;
6467                         }
6468
6469                         g_object_set( element, "stream-type", stream_type, NULL );
6470                         //g_object_set( element, "size", player->mem_buf.len, NULL );
6471                         //g_object_set( element, "blocksize", (guint64)20480, NULL );
6472
6473                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6474                                 G_CALLBACK(__gst_appsrc_seek_data), player);
6475                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6476                                 G_CALLBACK(__gst_appsrc_feed_data), player);
6477                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6478                                 G_CALLBACK(__gst_appsrc_enough_data), player);
6479                 }
6480                 break;
6481                 case MM_PLAYER_URI_TYPE_ES_BUFF:
6482                 {
6483                         debug_log("es buff src is selected\n");
6484
6485                         if (player->v_stream_caps)
6486                         {
6487                                 element = gst_element_factory_make("appsrc", "video_appsrc");
6488                                 if ( !element )
6489                                 {
6490                                         debug_critical("failed to create video app source element[appsrc].\n" );
6491                                         break;
6492                                 }
6493
6494                                 if ( player->a_stream_caps )
6495                                 {
6496                                         elem_src_audio = gst_element_factory_make("appsrc", "audio_appsrc");
6497                                         if ( !elem_src_audio )
6498                                         {
6499                                                 debug_critical("failed to create audio app source element[appsrc].\n" );
6500                                                 break;
6501                                         }
6502                                 }
6503                         }
6504                         else if ( player->a_stream_caps )
6505                         {
6506                                 /* no video, only audio pipeline*/
6507                                 element = gst_element_factory_make("appsrc", "audio_appsrc");
6508                                 if ( !element )
6509                                 {
6510                                         debug_critical("failed to create audio app source element[appsrc].\n" );
6511                                         break;
6512                                 }
6513                         }
6514
6515                         if ( player->s_stream_caps )
6516                         {
6517                                 elem_src_subtitle = gst_element_factory_make("appsrc", "subtitle_appsrc");
6518                                 if ( !elem_src_subtitle )
6519                                 {
6520                                         debug_critical("failed to create subtitle app source element[appsrc].\n" );
6521                                         break;
6522                                 }
6523                         }
6524
6525                         debug_log("setting app sources properties.\n");
6526                         debug_log("location : %s\n", player->profile.uri);
6527
6528                         if ( player->v_stream_caps && element )
6529                         {
6530                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6531                                                                                             "blocksize", (guint)1048576,        /* size of many video frames are larger than default blocksize as 4096 */
6532                                                                                                 "caps", player->v_stream_caps, NULL);
6533
6534                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6535                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6536                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6537                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6538
6539                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6540                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6541                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6542                                                                                                                 G_CALLBACK(__gst_seek_video_data), player);
6543
6544                                 if (player->a_stream_caps && elem_src_audio)
6545                                 {
6546                                         g_object_set(G_OBJECT(elem_src_audio), "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(elem_src_audio), "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(elem_src_audio), "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(elem_src_audio), GST_APP_STREAM_TYPE_SEEKABLE);
6556                                         MMPLAYER_SIGNAL_CONNECT( player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6557                                                                                                                 G_CALLBACK(__gst_seek_audio_data), player);
6558                                 }
6559                         }
6560                         else if (player->a_stream_caps && element)
6561                         {
6562                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6563                                                                                                 "caps", player->a_stream_caps, NULL);
6564
6565                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6566                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6567                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6568                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6569
6570                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6571                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6572                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6573                                                                                                                         G_CALLBACK(__gst_seek_audio_data), player);
6574                         }
6575
6576                         if (player->s_stream_caps && elem_src_subtitle)
6577                         {
6578                                 g_object_set(G_OBJECT(elem_src_subtitle), "format", GST_FORMAT_TIME,
6579                                                                                                                  "caps", player->s_stream_caps, NULL);
6580
6581                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6582                                         g_object_set(G_OBJECT(elem_src_subtitle), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6583                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6584                                         g_object_set(G_OBJECT(elem_src_subtitle), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6585
6586                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_subtitle), GST_APP_STREAM_TYPE_SEEKABLE);
6587
6588                                 MMPLAYER_SIGNAL_CONNECT( player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6589                                                                                                                                 G_CALLBACK(__gst_seek_subtitle_data), player);
6590                         }
6591
6592                         if (player->v_stream_caps && element)
6593                         {
6594                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6595                                                                                                                 G_CALLBACK(__gst_appsrc_feed_video_data), player);
6596                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6597                                                                                                                 G_CALLBACK(__gst_appsrc_enough_video_data), player);
6598
6599                                 if (player->a_stream_caps && elem_src_audio)
6600                                 {
6601                                         MMPLAYER_SIGNAL_CONNECT( player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6602                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6603                                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6604                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6605                                 }
6606                         }
6607                         else if (player->a_stream_caps && element)
6608                         {
6609                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6610                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6611                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6612                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6613                         }
6614
6615                         if (player->s_stream_caps && elem_src_subtitle)
6616                         {
6617                                 MMPLAYER_SIGNAL_CONNECT( player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6618                                                                                                                 G_CALLBACK(__gst_appsrc_feed_subtitle_data), player);
6619                         }
6620
6621                         need_state_holder = FALSE;
6622                 }
6623                 break;
6624                 /* appsrc */
6625                 case MM_PLAYER_URI_TYPE_MEM:
6626                 {
6627                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
6628
6629                         debug_log("mem src is selected\n");
6630
6631                         element = gst_element_factory_make("appsrc", "mem-source");
6632                         if ( !element )
6633                         {
6634                                 debug_error("failed to create appsrc element\n");
6635                                 break;
6636                         }
6637
6638                         g_object_set( element, "stream-type", stream_type, NULL );
6639                         g_object_set( element, "size", player->mem_buf.len, NULL );
6640                         g_object_set( element, "blocksize", (guint64)20480, NULL );
6641
6642                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6643                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->mem_buf );
6644                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6645                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->mem_buf );
6646                 }
6647                 break;
6648                 case MM_PLAYER_URI_TYPE_URL:
6649                 break;
6650
6651                 case MM_PLAYER_URI_TYPE_TEMP:
6652                 break;
6653
6654                 case MM_PLAYER_URI_TYPE_NONE:
6655                 default:
6656                 break;
6657         }
6658
6659         /* check source element is OK */
6660         if ( ! element )
6661         {
6662                 debug_error("no source element was created.\n");
6663                 goto INIT_ERROR;
6664         }
6665
6666         /* take source element */
6667         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
6668         mainbin[MMPLAYER_M_SRC].gst = element;
6669         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
6670
6671         if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL))
6672         {
6673                 player->streamer = __mm_player_streaming_create();
6674                 __mm_player_streaming_initialize(player->streamer);
6675         }
6676
6677         if ( MMPLAYER_IS_HTTP_PD(player) )
6678         {
6679                 gdouble pre_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
6680
6681                 debug_log ("Picked queue2 element(pre buffer : %d sec)....\n", pre_buffering_time);
6682                 element = gst_element_factory_make("queue2", "queue2");
6683                 if ( !element )
6684                 {
6685                         debug_error ( "failed to create http streaming buffer element\n" );
6686                         goto INIT_ERROR;
6687                 }
6688
6689                 /* take it */
6690                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
6691                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
6692                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
6693
6694                 pre_buffering_time = (pre_buffering_time > 0)?(pre_buffering_time):(player->ini.http_buffering_time);
6695
6696                 __mm_player_streaming_set_queue2(player->streamer,
6697                                 element,
6698                                 TRUE,
6699                                 player->ini.http_max_size_bytes,
6700                                 pre_buffering_time,
6701                                 1.0,
6702                                 player->ini.http_buffering_limit,
6703                                 FALSE,
6704                                 NULL,
6705                                 0);
6706         }
6707         if (MMPLAYER_IS_ES_BUFF_SRC(player))
6708         {
6709                 if (player->v_stream_caps)
6710                 {
6711                         es_video_queue = gst_element_factory_make("queue2", "video_queue");
6712                         if (!es_video_queue)
6713                         {
6714                                 debug_error ("create es_video_queue for es player failed\n");
6715                                 goto INIT_ERROR;
6716                         }
6717                         mainbin[MMPLAYER_M_V_BUFFER].id = MMPLAYER_M_V_BUFFER;
6718                         mainbin[MMPLAYER_M_V_BUFFER].gst = es_video_queue;
6719                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_V_BUFFER]);
6720
6721                         /* Adding audio appsrc to bucket */
6722                         if (player->a_stream_caps && elem_src_audio)
6723                         {
6724                                 mainbin[MMPLAYER_M_2ND_SRC].id = MMPLAYER_M_2ND_SRC;
6725                                 mainbin[MMPLAYER_M_2ND_SRC].gst = elem_src_audio;
6726                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_2ND_SRC]);
6727
6728                                 es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6729                                 if (!es_audio_queue)
6730                                 {
6731                                         debug_error ("create es_audio_queue for es player failed\n");
6732                                         goto INIT_ERROR;
6733                                 }
6734                                 mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6735                                 mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6736                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6737                         }
6738                 }
6739                 /* Only audio stream, no video */
6740                 else if (player->a_stream_caps)
6741                 {
6742                         es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6743                         if (!es_audio_queue)
6744                         {
6745                                 debug_error ("create es_audio_queue for es player failed\n");
6746                                 goto INIT_ERROR;
6747                         }
6748                         mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6749                         mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6750                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6751                 }
6752
6753                 if (player->s_stream_caps && elem_src_subtitle)
6754                 {
6755                         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6756                         mainbin[MMPLAYER_M_SUBSRC].gst = elem_src_subtitle;
6757                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SUBSRC]);
6758
6759                         es_subtitle_queue = gst_element_factory_make("queue2", "subtitle_queue");
6760                         if (!es_subtitle_queue)
6761                         {
6762                                 debug_error ("create es_subtitle_queue for es player failed\n");
6763                                 goto INIT_ERROR;
6764                         }
6765                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_V_BUFFER;
6766                         mainbin[MMPLAYER_M_S_BUFFER].gst = es_subtitle_queue;
6767                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
6768                 }
6769         }
6770
6771         /* create autoplugging element if src element is not a rtsp src */
6772         if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
6773                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_WFD) &&
6774                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_ES_BUFF))
6775         {
6776                 element = NULL;
6777                 enum MainElementID elemId = MMPLAYER_M_NUM;
6778
6779                 if ((player->use_decodebin) &&
6780                         ((MMPLAYER_IS_HTTP_PD(player)) ||
6781                          (!MMPLAYER_IS_HTTP_STREAMING(player))))
6782                 {
6783                         elemId = MMPLAYER_M_AUTOPLUG;
6784                         element = __mmplayer_create_decodebin(player);
6785                         need_state_holder = FALSE;
6786                 }
6787                 else
6788                 {
6789                         elemId = MMPLAYER_M_TYPEFIND;
6790                         element = gst_element_factory_make("typefind", "typefinder");
6791                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
6792                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
6793                 }
6794
6795
6796                 /* check autoplug element is OK */
6797                 if ( ! element )
6798                 {
6799                         debug_error("can not create element (%d)\n", elemId);
6800                         goto INIT_ERROR;
6801                 }
6802
6803                 mainbin[elemId].id = elemId;
6804                 mainbin[elemId].gst = element;
6805
6806                 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
6807         }
6808
6809         /* add elements to pipeline */
6810         if( !__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket))
6811         {
6812                 debug_error("Failed to add elements to pipeline\n");
6813                 goto INIT_ERROR;
6814         }
6815
6816
6817         /* linking elements in the bucket by added order. */
6818         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
6819         {
6820                 debug_error("Failed to link some elements\n");
6821                 goto INIT_ERROR;
6822         }
6823
6824
6825         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
6826         if ( need_state_holder )
6827         {
6828                 /* create */
6829                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
6830                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make ("fakesink", "state-holder");
6831
6832                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
6833                 {
6834                         debug_error ("fakesink element could not be created\n");
6835                         goto INIT_ERROR;
6836                 }
6837                 GST_OBJECT_FLAG_UNSET (mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
6838
6839                 /* take ownership of fakesink. we are reusing it */
6840                 gst_object_ref( mainbin[MMPLAYER_M_SRC_FAKESINK].gst );
6841
6842                 /* add */
6843                 if ( FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
6844                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst) )
6845                 {
6846                         debug_error("failed to add fakesink to bin\n");
6847                         goto INIT_ERROR;
6848                 }
6849         }
6850
6851         /* now we have completed mainbin. take it */
6852         player->pipeline->mainbin = mainbin;
6853
6854         if (MMPLAYER_IS_ES_BUFF_SRC(player))
6855         {
6856                 GstPad *srcpad = NULL;
6857
6858                 if (mainbin[MMPLAYER_M_V_BUFFER].gst)
6859                 {
6860                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_V_BUFFER].gst, "src");
6861                         if (srcpad)
6862                         {
6863                                 __mmplayer_gst_create_decoder ( player,
6864                                                                                                 MM_PLAYER_TRACK_TYPE_VIDEO,
6865                                                                                                 srcpad,
6866                                                                                                 MMPLAYER_M_AUTOPLUG_V_DEC,
6867                                                                                                 "video_decodebin");
6868
6869                                 gst_object_unref ( GST_OBJECT(srcpad) );
6870                                 srcpad = NULL;
6871                         }
6872                 }
6873
6874                 if ((player->a_stream_caps) && (mainbin[MMPLAYER_M_A_BUFFER].gst))
6875                 {
6876                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_BUFFER].gst, "src");
6877                         if (srcpad)
6878                         {
6879                                 __mmplayer_gst_create_decoder ( player,
6880                                                                                                 MM_PLAYER_TRACK_TYPE_AUDIO,
6881                                                                                                 srcpad,
6882                                                                                                 MMPLAYER_M_AUTOPLUG_A_DEC,
6883                                                                                                 "audio_decodebin");
6884
6885                                 gst_object_unref ( GST_OBJECT(srcpad) );
6886                                 srcpad = NULL;
6887                         } // else error
6888                 } //  else error
6889
6890                 if (mainbin[MMPLAYER_M_S_BUFFER].gst)
6891                 {
6892                         __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
6893                 }
6894         }
6895
6896         /* connect bus callback */
6897         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
6898         if ( !bus )
6899         {
6900                 debug_error ("cannot get bus from pipeline.\n");
6901                 goto INIT_ERROR;
6902         }
6903
6904         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
6905
6906         player->context.thread_default = g_main_context_get_thread_default();
6907
6908         if (NULL == player->context.thread_default)
6909         {
6910                 player->context.thread_default = g_main_context_default();
6911                 debug_log("thread-default context is the global default context");
6912         }
6913         debug_warning("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
6914
6915         /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
6916         if ( __mmplayer_check_subtitle ( player ) )
6917         {
6918                 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
6919                         debug_error("fail to create subtitle src\n");
6920         }
6921
6922         /* set sync handler to get tag synchronously */
6923         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL);
6924
6925         /* finished */
6926         gst_object_unref(GST_OBJECT(bus));
6927         g_list_free(element_bucket);
6928
6929         MMPLAYER_FLEAVE();
6930
6931         return MM_ERROR_NONE;
6932
6933 INIT_ERROR:
6934
6935         __mmplayer_gst_destroy_pipeline(player);
6936         g_list_free(element_bucket);
6937
6938         /* release element which are not added to bin */
6939         for ( i = 1; i < MMPLAYER_M_NUM; i++ )  /* NOTE : skip pipeline */
6940         {
6941                 if ( mainbin[i].gst )
6942                 {
6943                         GstObject* parent = NULL;
6944                         parent = gst_element_get_parent( mainbin[i].gst );
6945
6946                         if ( !parent )
6947                         {
6948                                 gst_object_unref(GST_OBJECT(mainbin[i].gst));
6949                                 mainbin[i].gst = NULL;
6950                         }
6951                         else
6952                         {
6953                                 gst_object_unref(GST_OBJECT(parent));
6954                         }
6955                 }
6956         }
6957
6958         /* release pipeline with it's childs */
6959         if ( mainbin[MMPLAYER_M_PIPE].gst )
6960         {
6961                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
6962         }
6963
6964         MMPLAYER_FREEIF( player->pipeline );
6965         MMPLAYER_FREEIF( mainbin );
6966
6967         return MM_ERROR_PLAYER_INTERNAL;
6968 }
6969
6970 static void
6971 __mmplayer_reset_gapless_state(mm_player_t* player)
6972 {
6973         MMPLAYER_FENTER();
6974         return_if_fail(player
6975                 && player->pipeline
6976                 && player->pipeline->audiobin
6977                 && player->pipeline->audiobin[MMPLAYER_A_BIN].gst);
6978
6979         if (player->gapless.audio_data_probe_id != 0)
6980         {
6981                 GstPad *sinkpad;
6982                 sinkpad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_BIN].gst, "sink");
6983                 gst_pad_remove_probe (sinkpad, player->gapless.audio_data_probe_id);
6984                 gst_object_unref (sinkpad);
6985         }
6986         memset(&player->gapless, 0, sizeof(mm_player_gapless_t));
6987
6988         MMPLAYER_FLEAVE();
6989         return;
6990 }
6991
6992 static int
6993 __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
6994 {
6995         gint timeout = 0;
6996         int ret = MM_ERROR_NONE;
6997
6998         MMPLAYER_FENTER();
6999
7000         return_val_if_fail ( player, MM_ERROR_INVALID_HANDLE );
7001
7002         /* cleanup stuffs */
7003         MMPLAYER_FREEIF(player->type);
7004         player->have_dynamic_pad = FALSE;
7005         player->no_more_pad = FALSE;
7006         player->num_dynamic_pad = 0;
7007         player->demux_pad_index = 0;
7008         player->subtitle_language_list = NULL;
7009         player->use_deinterleave = FALSE;
7010         player->max_audio_channels = 0;
7011         player->video_share_api_delta = 0;
7012         player->video_share_clock_delta = 0;
7013         player->video_hub_download_mode = 0;
7014         __mmplayer_reset_gapless_state(player);
7015         __mmplayer_post_proc_reset(player);
7016
7017         if (player->streamer)
7018         {
7019                 __mm_player_streaming_deinitialize (player->streamer);
7020                 __mm_player_streaming_destroy(player->streamer);
7021                 player->streamer = NULL;
7022         }
7023
7024         /* cleanup unlinked mime type */
7025         MMPLAYER_FREEIF(player->unlinked_audio_mime);
7026         MMPLAYER_FREEIF(player->unlinked_video_mime);
7027         MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
7028
7029         /* cleanup running stuffs */
7030         __mmplayer_cancel_eos_timer( player );
7031 #if 0 //need to change and test
7032         /* remove sound cb */
7033         if ( MM_ERROR_NONE != mm_sound_remove_device_information_changed_callback())
7034         {
7035                 debug_error("failed to mm_sound_remove_device_information_changed_callback()");
7036         }
7037 #endif
7038         /* cleanup gst stuffs */
7039         if ( player->pipeline )
7040         {
7041                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
7042                 GstTagList* tag_list = player->pipeline->tag_list;
7043
7044                 /* first we need to disconnect all signal hander */
7045                 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_ALL );
7046
7047                 /* disconnecting bus watch */
7048                 if ( player->bus_watcher )
7049                         __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
7050                 player->bus_watcher = 0;
7051
7052                 if ( mainbin )
7053                 {
7054                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
7055                         MMPlayerGstElement* videobin = player->pipeline->videobin;
7056                         MMPlayerGstElement* textbin = player->pipeline->textbin;
7057                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mainbin[MMPLAYER_M_PIPE].gst));
7058                         gst_bus_set_sync_handler (bus, NULL, NULL, NULL);
7059                         gst_object_unref(bus);
7060
7061                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7062                         ret = __mmplayer_gst_set_state ( player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout );
7063                         if ( ret != MM_ERROR_NONE )
7064                         {
7065                                 debug_error("fail to change state to NULL\n");
7066                                 return MM_ERROR_PLAYER_INTERNAL;
7067                         }
7068
7069                         debug_warning("succeeded in chaning state to NULL\n");
7070
7071                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7072
7073                         /* free fakesink */
7074                         if ( mainbin[MMPLAYER_M_SRC_FAKESINK].gst )
7075                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
7076
7077                         /* free avsysaudiosink
7078                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
7079                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
7080                         */
7081                         MMPLAYER_FREEIF( audiobin );
7082                         MMPLAYER_FREEIF( videobin );
7083                         MMPLAYER_FREEIF( textbin );
7084                         MMPLAYER_FREEIF( mainbin );
7085                 }
7086
7087                 if ( tag_list )
7088                         gst_tag_list_free(tag_list);
7089
7090                 MMPLAYER_FREEIF( player->pipeline );
7091         }
7092         MMPLAYER_FREEIF(player->album_art);
7093
7094         if (player->v_stream_caps)
7095         {
7096                 gst_caps_unref(player->v_stream_caps);
7097                 player->v_stream_caps = NULL;
7098         }
7099         if (player->a_stream_caps)
7100         {
7101                 gst_caps_unref(player->a_stream_caps);
7102                 player->a_stream_caps = NULL;
7103         }
7104         if (player->s_stream_caps)
7105         {
7106                 gst_caps_unref(player->s_stream_caps);
7107                 player->s_stream_caps = NULL;
7108         }
7109         _mmplayer_track_destroy(player);
7110
7111         if ( player->sink_elements )
7112                 g_list_free ( player->sink_elements );
7113         player->sink_elements = NULL;
7114
7115         debug_warning("finished destroy pipeline\n");
7116
7117         MMPLAYER_FLEAVE();
7118
7119         return ret;
7120 }
7121
7122 static int __gst_realize(mm_player_t* player) // @
7123 {
7124         gint timeout = 0;
7125         int ret = MM_ERROR_NONE;
7126
7127         MMPLAYER_FENTER();
7128
7129         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7130
7131         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7132
7133         ret = __mmplayer_gst_create_pipeline(player);
7134         if ( ret )
7135         {
7136                 debug_error("failed to create pipeline\n");
7137                 return ret;
7138         }
7139
7140         /* set pipeline state to READY */
7141         /* NOTE : state change to READY must be performed sync. */
7142         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7143         ret = __mmplayer_gst_set_state(player,
7144                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
7145
7146         if ( ret != MM_ERROR_NONE )
7147         {
7148                 /* return error if failed to set state */
7149                 debug_error("failed to set READY state");
7150                 return ret;
7151         }
7152         else
7153         {
7154                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
7155         }
7156
7157         /* create dot before error-return. for debugging */
7158         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-realize" );
7159
7160         MMPLAYER_FLEAVE();
7161
7162         return ret;
7163 }
7164
7165 static int __gst_unrealize(mm_player_t* player) // @
7166 {
7167         int ret = MM_ERROR_NONE;
7168
7169         MMPLAYER_FENTER();
7170
7171         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7172
7173         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
7174         MMPLAYER_PRINT_STATE(player);
7175
7176         /* release miscellaneous information */
7177         __mmplayer_release_misc( player );
7178
7179         /* destroy pipeline */
7180         ret = __mmplayer_gst_destroy_pipeline( player );
7181         if ( ret != MM_ERROR_NONE )
7182         {
7183                 debug_error("failed to destory pipeline\n");
7184                 return ret;
7185         }
7186
7187         /* release miscellaneous information.
7188            these info needs to be released after pipeline is destroyed. */
7189         __mmplayer_release_misc_post( player );
7190
7191         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
7192
7193         MMPLAYER_FLEAVE();
7194
7195         return ret;
7196 }
7197
7198 static int __gst_pending_seek ( mm_player_t* player )
7199 {
7200         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7201         int ret = MM_ERROR_NONE;
7202
7203         MMPLAYER_FENTER();
7204
7205         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7206
7207         if ( !player->pending_seek.is_pending )
7208         {
7209                 debug_log("pending seek is not reserved. nothing to do.\n" );
7210                 return ret;
7211         }
7212
7213         /* check player state if player could pending seek or not. */
7214         current_state = MMPLAYER_CURRENT_STATE(player);
7215
7216         if ( current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING  )
7217         {
7218                 debug_warning("try to pending seek in %s state, try next time. \n",
7219                         MMPLAYER_STATE_GET_NAME(current_state));
7220                 return ret;
7221         }
7222
7223         debug_log("trying to play from (%lu) pending position\n", player->pending_seek.pos);
7224
7225         ret = __gst_set_position ( player, player->pending_seek.format, player->pending_seek.pos, FALSE );
7226
7227         if ( MM_ERROR_NONE != ret )
7228                 debug_error("failed to seek pending postion. just keep staying current position.\n");
7229
7230         player->pending_seek.is_pending = FALSE;
7231
7232         MMPLAYER_FLEAVE();
7233
7234         return ret;
7235 }
7236
7237 static int __gst_start(mm_player_t* player) // @
7238 {
7239         gboolean sound_extraction = 0;
7240         int ret = MM_ERROR_NONE;
7241         gboolean async = FALSE;
7242
7243         MMPLAYER_FENTER();
7244
7245         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7246
7247         /* get sound_extraction property */
7248         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
7249
7250         /* NOTE : if SetPosition was called before Start. do it now */
7251         /* streaming doesn't support it. so it should be always sync */
7252         /* !! create one more api to check if there is pending seek rather than checking variables */
7253         if ( (player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player))
7254         {
7255                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
7256                 ret = __gst_pause(player, FALSE);
7257                 if ( ret != MM_ERROR_NONE )
7258                 {
7259                         debug_error("failed to set state to PAUSED for pending seek\n");
7260                         return ret;
7261                 }
7262
7263                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
7264
7265                 if ( sound_extraction )
7266                 {
7267                         debug_log("setting pcm extraction\n");
7268
7269                         ret = __mmplayer_set_pcm_extraction(player);
7270                         if ( MM_ERROR_NONE != ret )
7271                         {
7272                                 debug_warning("failed to set pcm extraction\n");
7273                                 return ret;
7274                         }
7275                 }
7276                 else
7277                 {
7278                         if ( MM_ERROR_NONE != __gst_pending_seek(player) )
7279                         {
7280                                 debug_warning("failed to seek pending postion. starting from the begin of content.\n");
7281                         }
7282                 }
7283         }
7284
7285         debug_log("current state before doing transition");
7286         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7287         MMPLAYER_PRINT_STATE(player);
7288
7289         /* set pipeline state to PLAYING  */
7290         if (player->es_player_push_mode)
7291         {
7292                 async = TRUE;
7293         }
7294         /* set pipeline state to PLAYING  */
7295         ret = __mmplayer_gst_set_state(player,
7296                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
7297
7298         if (ret == MM_ERROR_NONE)
7299         {
7300                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7301         }
7302         else
7303         {
7304                 debug_error("failed to set state to PLAYING");
7305                 return ret;
7306         }
7307
7308         /* generating debug info before returning error */
7309         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-start" );
7310
7311         MMPLAYER_FLEAVE();
7312
7313         return ret;
7314 }
7315
7316 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
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", 2, NULL);
7326
7327         usleep(time);
7328
7329         MMPLAYER_FLEAVE();
7330 }
7331
7332 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
7333 {
7334         MMPLAYER_FENTER();
7335
7336         return_if_fail(player
7337                 && player->pipeline
7338                 && player->pipeline->audiobin
7339                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
7340
7341         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
7342
7343         MMPLAYER_FLEAVE();
7344 }
7345
7346 static int __gst_stop(mm_player_t* player) // @
7347 {
7348         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
7349         MMHandleType attrs = 0;
7350         gboolean fadedown = FALSE;
7351         gboolean rewind = FALSE;
7352         gint timeout = 0;
7353         int ret = MM_ERROR_NONE;
7354         GstState state;
7355         gboolean async = FALSE;
7356
7357         MMPLAYER_FENTER();
7358
7359         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7360         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7361
7362         debug_log("current state before doing transition");
7363         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7364         MMPLAYER_PRINT_STATE(player);
7365
7366         attrs = MMPLAYER_GET_ATTRS(player);
7367         if ( !attrs )
7368         {
7369                 debug_error("cannot get content attribute\n");
7370                 return MM_ERROR_PLAYER_INTERNAL;
7371         }
7372
7373         mm_attrs_get_int_by_name(attrs, "sound_fadedown", &fadedown);
7374
7375         /* enable fadedown */
7376         if (fadedown || player->sound_focus.by_asm_cb)
7377                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
7378
7379         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
7380         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
7381
7382         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_BUFF ||
7383                 player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS)
7384         {
7385                 state = GST_STATE_READY;
7386         }
7387         else
7388         {
7389                 state = GST_STATE_PAUSED;
7390
7391                 if ( ! MMPLAYER_IS_STREAMING(player) ||
7392                         (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked)) {
7393                         rewind = TRUE;
7394                 }
7395         }
7396
7397         if (player->es_player_push_mode)
7398         {
7399                 async = TRUE;
7400         }
7401         /* set gst state */
7402         ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, async, timeout );
7403
7404         /* disable fadeout */
7405         if (fadedown || player->sound_focus.by_asm_cb)
7406                 __mmplayer_undo_sound_fadedown(player);
7407
7408         /* return if set_state has failed */
7409         if ( ret != MM_ERROR_NONE )
7410         {
7411                 debug_error("failed to set state.\n");
7412                 return ret;
7413         }
7414
7415         /* rewind */
7416         if ( rewind )
7417         {
7418                 if ( ! __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7419                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
7420                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE) )
7421                 {
7422                         debug_warning("failed to rewind\n");
7423                         ret = MM_ERROR_PLAYER_SEEK;
7424                 }
7425         }
7426
7427         /* initialize */
7428         player->sent_bos = FALSE;
7429
7430         if (player->es_player_push_mode) //for cloudgame
7431         {
7432                 timeout = 0;
7433         }
7434
7435         /* wait for seek to complete */
7436         change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
7437         if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL )
7438         {
7439                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
7440         }
7441         else
7442         {
7443                 debug_error("fail to stop player.\n");
7444                 ret = MM_ERROR_PLAYER_INTERNAL;
7445                 __mmplayer_dump_pipeline_state(player);
7446         }
7447
7448         /* generate dot file if enabled */
7449         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-stop" );
7450
7451         MMPLAYER_FLEAVE();
7452
7453         return ret;
7454 }
7455
7456 int __gst_pause(mm_player_t* player, gboolean async) // @
7457 {
7458         int ret = MM_ERROR_NONE;
7459
7460         MMPLAYER_FENTER();
7461
7462         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7463         return_val_if_fail(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7464
7465         debug_log("current state before doing transition");
7466         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
7467         MMPLAYER_PRINT_STATE(player);
7468
7469         /* set pipeline status to PAUSED */
7470         player->ignore_asyncdone = TRUE;
7471
7472         ret = __mmplayer_gst_set_state(player,
7473                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
7474
7475         player->ignore_asyncdone = FALSE;
7476
7477         if ( FALSE == async )
7478         {
7479                 if ( ret != MM_ERROR_NONE )
7480                 {
7481                         GstMessage *msg = NULL;
7482                         GTimer *timer = NULL;
7483                         gdouble MAX_TIMEOUT_SEC = 3;
7484
7485                         debug_error("failed to set state to PAUSED");
7486
7487                         timer = g_timer_new();
7488                         g_timer_start(timer);
7489
7490                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
7491                         gboolean got_msg = FALSE;
7492                         /* check if gst error posted or not */
7493                         do
7494                         {
7495                                 msg = gst_bus_timed_pop(bus, GST_SECOND /2);
7496                                 if (msg)
7497                                 {
7498                                         if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR)
7499                                         {
7500                                                 GError *error = NULL;
7501
7502                                                 /* parse error code */
7503                                                 gst_message_parse_error(msg, &error, NULL);
7504
7505                                                 if ( gst_structure_has_name ( gst_message_get_structure(msg), "streaming_error" ) )
7506                                                 {
7507                                                         /* Note : the streaming error from the streaming source is handled
7508                                                          *   using __mmplayer_handle_streaming_error.
7509                                                          */
7510                                                         __mmplayer_handle_streaming_error ( player, msg );
7511
7512                                                 }
7513                                                 else if (error)
7514                                                 {
7515                                                         debug_error("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
7516
7517                                                         if (error->domain == GST_STREAM_ERROR)
7518                                                         {
7519                                                                 ret = __gst_handle_stream_error( player, error, msg );
7520                                                         }
7521                                                         else if (error->domain == GST_RESOURCE_ERROR)
7522                                                         {
7523                                                                 ret = __gst_handle_resource_error( player, error->code );
7524                                                         }
7525                                                         else if (error->domain == GST_LIBRARY_ERROR)
7526                                                         {
7527                                                                 ret = __gst_handle_library_error( player, error->code );
7528                                                         }
7529                                                         else if (error->domain == GST_CORE_ERROR)
7530                                                         {
7531                                                                 ret = __gst_handle_core_error( player, error->code );
7532                                                         }
7533                                                 }
7534
7535                                                 got_msg = TRUE;
7536                                                 player->msg_posted = TRUE;
7537                                         }
7538                                         gst_message_unref(msg);
7539                                 }
7540                         } while (!got_msg && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
7541                         /* clean */
7542                         gst_object_unref(bus);
7543                         g_timer_stop (timer);
7544                         g_timer_destroy (timer);
7545
7546                         return ret;
7547                 }
7548                 else if ( (!player->pipeline->videobin) && (!player->pipeline->audiobin) )
7549                 {
7550                         if (MMPLAYER_IS_RTSP_STREAMING(player))
7551                                 return ret;
7552                         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
7553                 }
7554                 else if ( ret== MM_ERROR_NONE)
7555                 {
7556                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
7557                 }
7558         }
7559
7560         /* generate dot file before returning error */
7561         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-pause" );
7562
7563         MMPLAYER_FLEAVE();
7564
7565         return ret;
7566 }
7567
7568 int __gst_resume(mm_player_t* player, gboolean async) // @
7569 {
7570         int ret = MM_ERROR_NONE;
7571         gint timeout = 0;
7572
7573         MMPLAYER_FENTER();
7574
7575         return_val_if_fail(player && player->pipeline,
7576                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7577
7578         debug_log("current state before doing transition");
7579         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7580         MMPLAYER_PRINT_STATE(player);
7581
7582         /* generate dot file before returning error */
7583         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
7584
7585         if ( async )
7586                 debug_log("do async state transition to PLAYING.\n");
7587
7588         /* set pipeline state to PLAYING */
7589         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7590
7591         ret = __mmplayer_gst_set_state(player,
7592                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout );
7593         if (ret != MM_ERROR_NONE)
7594         {
7595                 debug_error("failed to set state to PLAYING\n");
7596                 return ret;
7597         }
7598         else
7599         {
7600                 if (async == FALSE)
7601                 {
7602                         // MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING );
7603                         debug_log("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
7604                         ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
7605                 }
7606         }
7607
7608         /* generate dot file before returning error */
7609         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
7610
7611         MMPLAYER_FLEAVE();
7612
7613         return ret;
7614 }
7615
7616 static int
7617 __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called) // @
7618 {
7619         unsigned long dur_msec = 0;
7620         gint64 dur_nsec = 0;
7621         gint64 pos_nsec = 0;
7622         gboolean ret = TRUE;
7623         gboolean accurated = FALSE;
7624         GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
7625
7626         MMPLAYER_FENTER();
7627         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7628         return_val_if_fail ( !MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP );
7629
7630         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
7631                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED )
7632                 goto PENDING;
7633
7634         if( !MMPLAYER_IS_ES_BUFF_SRC(player) )
7635         {
7636                 /* check duration */
7637                 /* NOTE : duration cannot be zero except live streaming.
7638                  *              Since some element could have some timing problemn with quering duration, try again.
7639                  */
7640                 if ( !player->duration )
7641                 {
7642                         if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
7643                         {
7644                                 goto SEEK_ERROR;
7645                         }
7646                         player->duration = dur_nsec;
7647                 }
7648
7649                 if ( player->duration )
7650                 {
7651                         dur_msec = GST_TIME_AS_MSECONDS(player->duration);
7652                 }
7653                 else
7654                 {
7655                         debug_error("could not get the duration. fail to seek.\n");
7656                         goto SEEK_ERROR;
7657                 }
7658         }
7659         debug_log("playback rate: %f\n", player->playback_rate);
7660
7661         mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
7662         if (accurated)
7663         {
7664                 seek_flags |= GST_SEEK_FLAG_ACCURATE;
7665         }
7666         else
7667         {
7668                 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
7669         }
7670
7671         /* do seek */
7672         switch ( format )
7673         {
7674                 case MM_PLAYER_POS_FORMAT_TIME:
7675                 {
7676                         if( !MMPLAYER_IS_ES_BUFF_SRC(player) )
7677                         {
7678                                 /* check position is valid or not */
7679                                 if ( position > dur_msec )
7680                                         goto INVALID_ARGS;
7681
7682                                 debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec);
7683
7684                                 if ( player->doing_seek )
7685                                 {
7686                                         debug_log("not completed seek");
7687                                         return MM_ERROR_PLAYER_DOING_SEEK;
7688                                 }
7689                         }
7690
7691                         if ( !internal_called )
7692                                 player->doing_seek = TRUE;
7693
7694                         pos_nsec = position * G_GINT64_CONSTANT(1000000);
7695
7696                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked))
7697                         {
7698                                 gint64 cur_time = 0;
7699
7700                                 /* get current position */
7701                                 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
7702
7703                                 /* flush */
7704                                 GstEvent *event = gst_event_new_seek (1.0,
7705                                                                 GST_FORMAT_TIME,
7706                                                                 (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
7707                                                                 GST_SEEK_TYPE_SET, cur_time,
7708                                                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7709                                 if(event) {
7710                                         __gst_send_event_to_sink(player, event);
7711                                 }
7712
7713                                 __gst_pause( player, FALSE );
7714                         }
7715
7716                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7717                                                         GST_FORMAT_TIME, seek_flags,
7718                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
7719                         if ( !ret  )
7720                         {
7721                                 debug_error("failed to set position. dur[%lu]  pos[%lu]  pos_msec[%llu]\n", dur_msec, position, pos_nsec);
7722                                 goto SEEK_ERROR;
7723                         }
7724                 }
7725                 break;
7726
7727                 case MM_PLAYER_POS_FORMAT_PERCENT:
7728                 {
7729                         debug_log("seeking to (%lu)%% \n", position);
7730
7731                         if (player->doing_seek)
7732                         {
7733                                 debug_log("not completed seek");
7734                                 return MM_ERROR_PLAYER_DOING_SEEK;
7735                         }
7736
7737                         if ( !internal_called)
7738                                 player->doing_seek = TRUE;
7739
7740                         /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
7741                         pos_nsec = (gint64) ( ( position * player->duration ) / 100 );
7742                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7743                                                         GST_FORMAT_TIME, seek_flags,
7744                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
7745                         if ( !ret  )
7746                         {
7747                                 debug_error("failed to set position. dur[%lud]  pos[%lud]  pos_msec[%"G_GUINT64_FORMAT"]\n", dur_msec, position, pos_nsec);
7748                                 goto SEEK_ERROR;
7749                         }
7750                 }
7751                 break;
7752
7753                 default:
7754                         goto INVALID_ARGS;
7755
7756         }
7757
7758         /* NOTE : store last seeking point to overcome some bad operation
7759           *      ( returning zero when getting current position ) of some elements
7760           */
7761         player->last_position = pos_nsec;
7762
7763         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
7764         if ( player->playback_rate > 1.0 )
7765                 _mmplayer_set_playspeed ( (MMHandleType)player, player->playback_rate );
7766
7767         MMPLAYER_FLEAVE();
7768         return MM_ERROR_NONE;
7769
7770 PENDING:
7771         player->pending_seek.is_pending = TRUE;
7772         player->pending_seek.format = format;
7773         player->pending_seek.pos = position;
7774
7775         debug_warning("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n",
7776                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
7777
7778         return MM_ERROR_NONE;
7779
7780 INVALID_ARGS:
7781         debug_error("invalid arguments, position : %ld  dur : %ld format : %d \n", position, dur_msec, format);
7782         return MM_ERROR_INVALID_ARGUMENT;
7783
7784 SEEK_ERROR:
7785         player->doing_seek = FALSE;
7786         return MM_ERROR_PLAYER_SEEK;
7787 }
7788
7789 #define TRICKPLAY_OFFSET GST_MSECOND
7790
7791 static int
7792 __gst_get_position(mm_player_t* player, int format, unsigned long* position) // @
7793 {
7794         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7795         gint64 pos_msec = 0;
7796         gboolean ret = TRUE;
7797
7798         return_val_if_fail( player && position && player->pipeline && player->pipeline->mainbin,
7799                 MM_ERROR_PLAYER_NOT_INITIALIZED );
7800
7801         current_state = MMPLAYER_CURRENT_STATE(player);
7802
7803         /* NOTE : query position except paused state to overcome some bad operation
7804          * please refer to below comments in details
7805          */
7806         if ( current_state != MM_PLAYER_STATE_PAUSED )
7807         {
7808                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
7809         }
7810
7811         /* NOTE : get last point to overcome some bad operation of some elements
7812          * ( returning zero when getting current position in paused state
7813          * and when failed to get postion during seeking
7814          */
7815         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
7816                 || ( ! ret ))
7817                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
7818         {
7819                 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
7820
7821                 if(player->playback_rate < 0.0)
7822                         pos_msec = player->last_position - TRICKPLAY_OFFSET;
7823                 else
7824                         pos_msec = player->last_position;
7825
7826                 if (!ret)
7827                         pos_msec = player->last_position;
7828                 else
7829                         player->last_position = pos_msec;
7830
7831                 debug_log("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
7832
7833         }
7834         else
7835         {
7836                 if (player->duration > 0 && pos_msec > player->duration) {
7837                         pos_msec = player->duration;
7838                 }
7839
7840                 if (player->sound_focus.keep_last_pos) {
7841                         debug_log("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position));
7842                         pos_msec = player->last_position;
7843                 }
7844                 else {
7845                         player->last_position = pos_msec;
7846                 }
7847         }
7848
7849         switch (format) {
7850                 case MM_PLAYER_POS_FORMAT_TIME:
7851                         *position = GST_TIME_AS_MSECONDS(pos_msec);
7852                         break;
7853
7854                 case MM_PLAYER_POS_FORMAT_PERCENT:
7855                 {
7856                         gint64 dur = 0;
7857                         gint64 pos = 0;
7858
7859                         dur = player->duration / GST_SECOND;
7860                         if (dur <= 0)
7861                         {
7862                                 debug_log ("duration is [%d], so returning position 0\n",dur);
7863                                 *position = 0;
7864                         }
7865                         else
7866                         {
7867                                 pos = pos_msec / GST_SECOND;
7868                                 *position = pos * 100 / dur;
7869                         }
7870                         break;
7871                 }
7872                 default:
7873                         return MM_ERROR_PLAYER_INTERNAL;
7874         }
7875
7876         return MM_ERROR_NONE;
7877 }
7878
7879
7880 static int      __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
7881 {
7882 #define STREAMING_IS_FINISHED   0
7883 #define BUFFERING_MAX_PER       100
7884
7885         GstQuery *query = NULL;
7886
7887         return_val_if_fail( player &&
7888                                                 player->pipeline &&
7889                                                 player->pipeline->mainbin,
7890                                                 MM_ERROR_PLAYER_NOT_INITIALIZED );
7891
7892         return_val_if_fail( start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT );
7893
7894         if (!MMPLAYER_IS_HTTP_STREAMING ( player ))
7895         {
7896                 /* and rtsp is not ready yet. */
7897                 debug_warning ( "it's only used for http streaming case.\n" );
7898                 return MM_ERROR_NONE;
7899         }
7900
7901         *start_pos = 0;
7902         *stop_pos = 0;
7903
7904         switch ( format )
7905         {
7906                 case MM_PLAYER_POS_FORMAT_PERCENT :
7907                 {
7908                         gint start_per = -1, stop_per = -1;
7909                         gint64 buffered_total = 0;
7910
7911                         unsigned long position = 0;
7912                         guint curr_size_bytes = 0;
7913                         gint64 buffering_left = -1;
7914                         gint buffered_sec = -1;
7915
7916                         gint64 content_duration = player->duration;
7917                         guint64 content_size = player->http_content_size;
7918
7919                         if (content_duration > 0)
7920                         {
7921                                 if (!__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position))
7922                                 {
7923                                         debug_log ("[Time] pos %d ms / dur %d sec / %lld bytes", position, (guint)(content_duration/GST_SECOND), content_size);
7924                                         start_per = 100 * (position*GST_MSECOND) / content_duration;
7925
7926                                         /* buffered size info from multiqueue */
7927                                         if (player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst)
7928                                         {
7929                                                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst), "curr-size-bytes", &curr_size_bytes, NULL);
7930                                                 debug_log ("[MQ] curr_size_bytes = %d", curr_size_bytes);
7931
7932                                                 buffered_total += curr_size_bytes;
7933                                         }
7934
7935                                         /* buffered size info from queue2 */
7936                                         if (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
7937                                         {
7938                                                 query = gst_query_new_buffering ( GST_FORMAT_BYTES );
7939                                                 if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query))
7940                                                 {
7941                                                         GstBufferingMode mode;
7942                                                         gint byte_in_rate = 0, byte_out_rate = 0;
7943                                                         gint64 start_byte = 0, stop_byte = 0;
7944                                                         guint num_of_ranges = 0;
7945                                                         guint idx = 0;
7946
7947                                                         num_of_ranges = gst_query_get_n_buffering_ranges(query);
7948                                                         for ( idx=0 ; idx<num_of_ranges ; idx++ )
7949                                                         {
7950                                                                 gst_query_parse_nth_buffering_range (query, idx, &start_byte, &stop_byte);
7951                                                                 debug_log ("[Q2][range %d] %lld ~ %lld\n", idx, start_byte, stop_byte);
7952
7953                                                                 buffered_total += (stop_byte - start_byte);
7954                                                         }
7955
7956                                                         gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, &buffering_left);
7957                                                         debug_log ("[Q2] in_rate %d, out_rate %d, left %lld\n", byte_in_rate, byte_out_rate, buffering_left);
7958                                                 }
7959                                                 gst_query_unref (query);
7960                                         }
7961
7962                                         if (buffering_left == STREAMING_IS_FINISHED)
7963                                         {
7964                                                 stop_per = BUFFERING_MAX_PER;
7965                                         }
7966                                         else
7967                                         {
7968                                                 guint dur_sec = (guint)(content_duration/GST_SECOND);
7969                                                 guint avg_byterate = (dur_sec>0)?((guint)(content_size/dur_sec)):(0);
7970
7971                                                 if (avg_byterate > 0)
7972                                                         buffered_sec = (gint)(buffered_total/avg_byterate);
7973                                                 else if (player->total_maximum_bitrate > 0)
7974                                                         buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_maximum_bitrate);
7975                                                 else if (player->total_bitrate > 0)
7976                                                         buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_bitrate);
7977
7978                                                 if ((buffered_sec >= 0) && (dur_sec > 0))
7979                                                         stop_per = start_per + (100 * buffered_sec / dur_sec);
7980                                         }
7981
7982                                         debug_log ("[Buffered Total] %lld bytes, %d sec, per %d~%d\n", buffered_total, buffered_sec, start_per, stop_per);
7983                                 }
7984                         }
7985
7986                         if (((buffered_total == 0) || (start_per < 0) || (stop_per < 0)) &&
7987                                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
7988                         {
7989                                 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
7990                                 if ( gst_element_query ( player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query ) )
7991                                 {
7992                                         GstFormat format;
7993                                         gint64 range_start_per = -1, range_stop_per = -1;
7994
7995                                         gst_query_parse_buffering_range ( query, &format, &range_start_per, &range_stop_per, NULL );
7996
7997                                         debug_log ("[Q2] range start %" G_GINT64_FORMAT " ~ stop %" G_GINT64_FORMAT "\n",  range_start_per , range_stop_per);
7998
7999                                         if (range_start_per != -1)
8000                                                 start_per = (gint)(100 * range_start_per / GST_FORMAT_PERCENT_MAX);
8001
8002                                         if (range_stop_per != -1)
8003                                                 stop_per = (gint)(100 * range_stop_per / GST_FORMAT_PERCENT_MAX);
8004                                 }
8005                                 gst_query_unref (query);
8006                         }
8007
8008                         if ( start_per > 0)
8009                                 *start_pos = (start_per < 100)?(start_per):(100);
8010                         else
8011                                 *start_pos = 0;
8012
8013                         if ( stop_per > 0)
8014                                 *stop_pos = (stop_per < 100)?(stop_per):(100);
8015                         else
8016                                 *stop_pos = 0;
8017
8018                         break;
8019                 }
8020                 case MM_PLAYER_POS_FORMAT_TIME :
8021                         debug_warning ( "Time format is not supported yet.\n" );
8022                         break;
8023
8024                 default :
8025                         break;
8026         }
8027
8028         debug_log("current buffer position : %lu~%lu \n", *start_pos, *stop_pos );
8029
8030         return MM_ERROR_NONE;
8031 }
8032
8033 static int
8034 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param) // @
8035 {
8036         MMPLAYER_FENTER();
8037
8038         if ( !player )
8039         {
8040                 debug_warning("set_message_callback is called with invalid player handle\n");
8041                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
8042         }
8043
8044         player->msg_cb = callback;
8045         player->msg_cb_param = user_param;
8046
8047         debug_log("msg_cb : %p     msg_cb_param : %p\n", callback, user_param);
8048
8049         MMPLAYER_FLEAVE();
8050
8051         return MM_ERROR_NONE;
8052 }
8053
8054 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
8055 {
8056         int ret = MM_ERROR_PLAYER_INVALID_URI;
8057         char *path = NULL;
8058
8059         MMPLAYER_FENTER();
8060
8061         return_val_if_fail ( uri , FALSE);
8062         return_val_if_fail ( data , FALSE);
8063         return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
8064
8065         memset(data, 0, sizeof(MMPlayerParseProfile));
8066
8067         if ((path = strstr(uri, "file://")))
8068         {
8069                 int file_stat = MM_ERROR_NONE;
8070
8071                 file_stat = util_exist_file_path(path + 7);
8072
8073                 if (file_stat == MM_ERROR_NONE)
8074                 {
8075                         strncpy(data->uri, path, MM_MAX_URL_LEN-1);
8076
8077                         if ( util_is_sdp_file ( path ) )
8078                         {
8079                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8080                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8081                         }
8082                         else
8083                         {
8084                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8085                         }
8086                         ret = MM_ERROR_NONE;
8087                 }
8088                 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
8089                 {
8090                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8091                 }
8092                 else
8093                 {
8094                         debug_warning("could  access %s.\n", path);
8095                 }
8096         }
8097         else if ((path = strstr(uri, "es_buff://")))
8098         {
8099                 if (strlen(path))
8100                 {
8101                         strcpy(data->uri, uri);
8102                         data->uri_type = MM_PLAYER_URI_TYPE_ES_BUFF;
8103                         ret = MM_ERROR_NONE;
8104                 }
8105         }
8106         else if ((path = strstr(uri, "buff://")))
8107         {
8108                         data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
8109                         ret = MM_ERROR_NONE;
8110         }
8111         else if ((path = strstr(uri, "rtsp://")))
8112         {
8113                 if (strlen(path)) {
8114                         if((path = strstr(uri, "/wfd1.0/"))) {
8115                                 strcpy(data->uri, uri);
8116                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_WFD;
8117                                 ret = MM_ERROR_NONE;
8118                                 debug_log("uri is actually a wfd client path. giving it to wfdrtspsrc\n");
8119                         }
8120                         else {
8121                                 strcpy(data->uri, uri);
8122                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8123                                 ret = MM_ERROR_NONE;
8124                         }
8125                 }
8126         }
8127         else if ((path = strstr(uri, "http://")))
8128         {
8129                 if (strlen(path)) {
8130                         strcpy(data->uri, uri);
8131 #ifdef MM_SMOOTH_STREAMING
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                         else
8138 #endif
8139                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
8140
8141                         ret = MM_ERROR_NONE;
8142                 }
8143         }
8144         else if ((path = strstr(uri, "https://")))
8145         {
8146                 if (strlen(path)) {
8147                         strcpy(data->uri, uri);
8148 #ifdef MM_SMOOTH_STREAMING
8149                 if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
8150                                 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
8151                         {
8152                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
8153                         }
8154 #endif
8155                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
8156
8157                         ret = MM_ERROR_NONE;
8158                 }
8159         }
8160         else if ((path = strstr(uri, "rtspu://")))
8161         {
8162                 if (strlen(path)) {
8163                         strcpy(data->uri, uri);
8164                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8165                         ret = MM_ERROR_NONE;
8166                 }
8167         }
8168         else if ((path = strstr(uri, "rtspr://")))
8169         {
8170                 strcpy(data->uri, path);
8171                 char *separater =strstr(path, "*");
8172
8173                 if (separater) {
8174                         int urgent_len = 0;
8175                         char *urgent = separater + strlen("*");
8176
8177                         if ((urgent_len = strlen(urgent))) {
8178                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
8179                                 strcpy(data->urgent, urgent);
8180                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8181                                 ret = MM_ERROR_NONE;
8182                         }
8183                 }
8184         }
8185         else if ((path = strstr(uri, "mms://")))
8186         {
8187                 if (strlen(path)) {
8188                         strcpy(data->uri, uri);
8189                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
8190                         ret = MM_ERROR_NONE;
8191                 }
8192         }
8193         else if ((path = strstr(uri, "mem://")))
8194         {
8195                 if (strlen(path)) {
8196                         int mem_size = 0;
8197                         char *buffer = NULL;
8198                         char *seperator = strchr(path, ',');
8199                         char ext[100] = {0,}, size[100] = {0,};
8200
8201                         if (seperator) {
8202                                 if ((buffer = strstr(path, "ext="))) {
8203                                         buffer += strlen("ext=");
8204
8205                                         if (strlen(buffer)) {
8206                                                 strcpy(ext, buffer);
8207
8208                                                 if ((seperator = strchr(ext, ','))
8209                                                         || (seperator = strchr(ext, ' '))
8210                                                         || (seperator = strchr(ext, '\0'))) {
8211                                                         seperator[0] = '\0';
8212                                                 }
8213                                         }
8214                                 }
8215
8216                                 if ((buffer = strstr(path, "size="))) {
8217                                         buffer += strlen("size=");
8218
8219                                         if (strlen(buffer) > 0) {
8220                                                 strcpy(size, buffer);
8221
8222                                                 if ((seperator = strchr(size, ','))
8223                                                         || (seperator = strchr(size, ' '))
8224                                                         || (seperator = strchr(size, '\0'))) {
8225                                                         seperator[0] = '\0';
8226                                                 }
8227
8228                                                 mem_size = atoi(size);
8229                                         }
8230                                 }
8231                         }
8232
8233                         debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
8234                         if ( mem_size && param)
8235                         {
8236                                 data->mem = param;
8237                                 data->mem_size = mem_size;
8238                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
8239                                 ret = MM_ERROR_NONE;
8240                         }
8241                 }
8242         }
8243         else
8244         {
8245                 int file_stat = MM_ERROR_NONE;
8246
8247                 file_stat = util_exist_file_path(uri);
8248
8249                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
8250                 if (file_stat == MM_ERROR_NONE)
8251                 {
8252                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", uri);
8253
8254                         if ( util_is_sdp_file( (char*)uri ) )
8255                         {
8256                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8257                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8258                         }
8259                         else
8260                         {
8261                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8262                         }
8263                         ret = MM_ERROR_NONE;
8264                 }
8265                 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
8266                 {
8267                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8268                 }
8269                 else
8270                 {
8271                         debug_error ("invalid uri, could not play..\n");
8272                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8273                 }
8274         }
8275
8276         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
8277                 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
8278         } else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION){
8279                 ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
8280         }
8281
8282         /* dump parse result */
8283         secure_debug_warning("incomming uri : %s\n", uri);
8284         debug_log("uri_type : %d, mem : %p, mem_size : %d, urgent : %s\n",
8285                 data->uri_type, data->mem, data->mem_size, data->urgent);
8286
8287         MMPLAYER_FLEAVE();
8288
8289         return ret;
8290 }
8291
8292 gboolean _asm_postmsg(gpointer *data)
8293 {
8294         mm_player_t* player = (mm_player_t*)data;
8295         MMMessageParamType msg = {0, };
8296
8297         MMPLAYER_FENTER();
8298         return_val_if_fail ( player, FALSE );
8299         debug_warning("get notified");
8300
8301         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
8302                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
8303         {
8304                 debug_warning("dispatched");
8305                 return FALSE;
8306         }
8307
8308
8309         msg.union_type = MM_MSG_UNION_CODE;
8310         msg.code = player->sound_focus.focus_changed_msg;
8311
8312 #if 0 // should remove
8313         if (player->sm.event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
8314         {
8315                 /* fill the message with state of player */
8316                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
8317                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
8318                 player->resumable_cancel_id = 0;
8319         }
8320         else
8321 #endif
8322         {
8323                 MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
8324                 player->resume_event_id = 0;
8325         }
8326
8327         debug_warning("dispatched");
8328         return FALSE;
8329 }
8330
8331 gboolean _asm_lazy_pause(gpointer *data)
8332 {
8333         mm_player_t* player = (mm_player_t*)data;
8334         int ret = MM_ERROR_NONE;
8335
8336         MMPLAYER_FENTER();
8337
8338         return_val_if_fail ( player, FALSE );
8339
8340         if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
8341         {
8342                 debug_log ("Ready to proceed lazy pause\n");
8343                 ret = _mmplayer_pause((MMHandleType)player);
8344                 if(MM_ERROR_NONE != ret)
8345                 {
8346                         debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
8347                 }
8348         }
8349         else
8350         {
8351                 debug_log ("Invalid state to proceed lazy pause\n");
8352         }
8353
8354         /* unset mute */
8355         if (player->pipeline && player->pipeline->audiobin)
8356                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
8357
8358         player->sound_focus.by_asm_cb = FALSE; //should be reset here
8359
8360         MMPLAYER_FLEAVE();
8361
8362         return FALSE;
8363 }
8364
8365 static gboolean
8366 __mmplayer_can_do_interrupt(mm_player_t *player)
8367 {
8368         if (!player || !player->pipeline || !player->attrs)
8369         {
8370                 debug_warning("not initialized");
8371                 goto FAILED;
8372         }
8373
8374         if ((player->sound_focus.exit_cb) || (player->set_mode.pcm_extraction))
8375         {
8376                 debug_warning("leave from asm cb right now, %d, %d", player->sound_focus.exit_cb, player->set_mode.pcm_extraction);
8377                 goto FAILED;
8378         }
8379
8380         /* check if seeking */
8381         if (player->doing_seek)
8382         {
8383                 MMMessageParamType msg_param;
8384                 memset (&msg_param, 0, sizeof(MMMessageParamType));
8385                 msg_param.code = MM_ERROR_PLAYER_SEEK;
8386                 player->doing_seek = FALSE;
8387                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
8388                 goto FAILED;
8389         }
8390
8391         /* check other thread */
8392         if (!g_mutex_trylock(&player->cmd_lock))
8393         {
8394                 debug_warning("locked already, cmd state : %d", player->cmd);
8395
8396                 /* check application command */
8397                 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)
8398                 {
8399                         debug_warning("playing.. should wait cmd lock then, will be interrupted");
8400                         g_mutex_lock(&player->cmd_lock);
8401                         goto INTERRUPT;
8402                 }
8403                 debug_warning("nothing to do");
8404                 goto FAILED;
8405         }
8406         else
8407         {
8408                 debug_warning("can interrupt immediately");
8409                 goto INTERRUPT;
8410         }
8411
8412 FAILED:
8413         return FALSE;
8414
8415 INTERRUPT:
8416         return TRUE;
8417 }
8418
8419 /* if you want to enable USE_ASM, please check the history get the ASM cb code. */
8420 static int
8421 __mmplayer_convert_sound_focus_state(gboolean acquire, const char *reason_for_change, MMPlayerFocusChangedMsg *msg)
8422 {
8423         int ret = MM_ERROR_NONE;
8424         MMPlayerFocusChangedMsg focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
8425
8426         if (strstr(reason_for_change, "alarm")) {
8427                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_ALARM;
8428
8429         } else if (strstr(reason_for_change, "notification")) {
8430                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_NOTIFICATION;
8431
8432         } else if (strstr(reason_for_change, "emergency")) {
8433                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_EMERGENCY;
8434
8435         } else if (strstr(reason_for_change, "call-voice") ||
8436                strstr(reason_for_change, "call-video") ||
8437                strstr(reason_for_change, "voip") ||
8438                strstr(reason_for_change, "ringtone-voip") ||
8439                strstr(reason_for_change, "ringtone-call")) {
8440                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_CALL;
8441
8442         } else if (strstr(reason_for_change, "media") ||
8443                                 strstr(reason_for_change, "radio") ||
8444                                 strstr(reason_for_change, "loopback") ||
8445                                 strstr(reason_for_change, "system") ||
8446                                 strstr(reason_for_change, "voice-information") ||
8447                                 strstr(reason_for_change, "voice-recognition")) {
8448                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_MEDIA;
8449
8450         } else {
8451                 ret = MM_ERROR_INVALID_ARGUMENT;
8452                 debug_warning("not supported reason(%s), err(0x%08x)", reason_for_change, ret);
8453                 goto DONE;
8454         }
8455
8456         if (acquire && (focus_msg != MM_PLAYER_FOCUS_CHANGED_BY_MEDIA))
8457         {
8458                 /* can acqurie */
8459                 focus_msg = MM_PLAYER_FOCUS_CHANGED_COMPLETED;
8460         }
8461
8462         debug_log("converted from reason(%s) to msg(%d)", reason_for_change, focus_msg);
8463         *msg = focus_msg;
8464
8465 DONE:
8466         return ret;
8467 }
8468
8469 /* FIXME: will be updated with new funct */
8470 void __mmplayer_sound_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
8471                                        const char *reason_for_change, const char *additional_info, void *user_data)
8472 {
8473         mm_player_t* player = (mm_player_t*) user_data;
8474         int result = MM_ERROR_NONE;
8475         MMPlayerFocusChangedMsg msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
8476
8477         debug_warning("focus watch notified");
8478
8479         if (!__mmplayer_can_do_interrupt(player))
8480         {
8481                 debug_warning("no need to interrupt, so leave");
8482                 goto EXIT;
8483         }
8484
8485         if (player->sound_focus.session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE)
8486         {
8487                 debug_warning("flags is UNINTERRUPTIBLE. do nothing.");
8488                 goto EXIT;
8489         }
8490
8491         debug_warning("watch: state: %d, focus_type : %d, reason_for_change : %s",
8492                 focus_state, focus_type, (reason_for_change?reason_for_change:"N/A"));
8493
8494         player->sound_focus.cb_pending = TRUE;
8495         player->sound_focus.by_asm_cb = TRUE;
8496
8497         if (focus_state == FOCUS_IS_ACQUIRED)
8498         {
8499                 debug_warning("watch: FOCUS_IS_ACQUIRED");
8500                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(FALSE, reason_for_change, &msg))
8501                 {
8502                         player->sound_focus.focus_changed_msg = (int)msg;
8503                 }
8504
8505                 if (strstr(reason_for_change, "call") ||
8506                         strstr(reason_for_change, "voip") ||    /* FIXME: to check */
8507                         strstr(reason_for_change, "alarm") ||
8508                         strstr(reason_for_change, "media"))
8509                 {
8510                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
8511                         {
8512                                 // hold 0.7 second to excute "fadedown mute" effect
8513                                 debug_warning ("do fade down->pause->undo fade down");
8514
8515                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8516
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                                 __mmplayer_undo_sound_fadedown(player);
8524                         }
8525                         else
8526                         {
8527                                 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
8528                                 _mmplayer_unrealize((MMHandleType)player);
8529                         }
8530                 }
8531                 else
8532                 {
8533                         debug_warning ("pause immediately");
8534                         result = _mmplayer_pause((MMHandleType)player);
8535                         if (result != MM_ERROR_NONE)
8536                         {
8537                                 debug_warning("fail to set Pause state by asm");
8538                                 goto EXIT;
8539                         }
8540                 }
8541         }
8542         else if (focus_state == FOCUS_IS_RELEASED)
8543         {
8544                 debug_warning("FOCUS_IS_RELEASED: Got msg from asm to resume");
8545                 player->sound_focus.antishock = TRUE;
8546                 player->sound_focus.by_asm_cb = FALSE;
8547
8548                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(TRUE, reason_for_change, &msg))
8549                 {
8550                         player->sound_focus.focus_changed_msg = (int)msg;
8551                 }
8552
8553                 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
8554                 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
8555                 goto DONE;
8556         }
8557         else
8558         {
8559                 debug_warning("unknown focus state %d", focus_state);
8560         }
8561
8562 DONE:
8563         player->sound_focus.by_asm_cb = FALSE;
8564         player->sound_focus.cb_pending = FALSE;
8565         MMPLAYER_CMD_UNLOCK( player );
8566
8567 EXIT:
8568         debug_warning("dispatched");
8569         return;
8570 }
8571
8572 void
8573 __mmplayer_sound_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
8574         const char *reason_for_change, const char *additional_info, void *user_data)
8575 {
8576         mm_player_t* player = (mm_player_t*) user_data;
8577         int result = MM_ERROR_NONE;
8578         gboolean lazy_pause = FALSE;
8579         MMPlayerFocusChangedMsg msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
8580
8581         debug_warning("get focus notified");
8582
8583         if (!__mmplayer_can_do_interrupt(player))
8584         {
8585                 debug_warning("no need to interrupt, so leave");
8586                 goto EXIT;
8587         }
8588
8589         if (player->sound_focus.session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE)
8590         {
8591                 debug_warning("flags is UNINTERRUPTIBLE. do nothing.");
8592                 goto EXIT;
8593         }
8594
8595         debug_warning("state: %d, focus_type : %d, reason_for_change : %s",
8596                 focus_state, focus_type, (reason_for_change?reason_for_change:"N/A"));
8597
8598         player->sound_focus.cb_pending = TRUE;
8599         player->sound_focus.by_asm_cb = TRUE;
8600 //      player->sound_focus.event_src = event_src;
8601
8602 #if 0
8603         /* first, check event source */
8604         if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG)
8605         {
8606                 int stop_by_asm = 0;
8607                 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
8608                 if (!stop_by_asm)
8609                         goto DONE;
8610         }
8611         else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
8612         {
8613                 /* can use video overlay simultaneously */
8614                 /* video resource conflict */
8615                 if(player->pipeline->videobin)
8616                 {
8617                         debug_log("video conflict but, can support multiple video");
8618                         result = _mmplayer_pause((MMHandleType)player);
8619                         cb_res = ASM_CB_RES_PAUSE;
8620                 }
8621                 else if (player->pipeline->audiobin)
8622                 {
8623                         debug_log("audio resource conflict");
8624                         result = _mmplayer_pause((MMHandleType)player);
8625                         if (result != MM_ERROR_NONE)
8626                         {
8627                                 debug_warning("fail to set pause by asm");
8628                         }
8629                         cb_res = ASM_CB_RES_PAUSE;
8630                 }
8631                 goto DONE;
8632         }
8633 #if 0 // should remove
8634         else if (event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
8635         {
8636                 debug_warning("Got msg from asm for resumable canceled.\n");
8637                 player->sound_focus.antishock = TRUE;
8638                 player->sound_focus.by_asm_cb = FALSE;
8639
8640                 player->resumable_cancel_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
8641                 cb_res = ASM_CB_RES_IGNORE;
8642                 goto DONE;
8643         }
8644 #endif
8645 #endif
8646
8647         if (focus_state == FOCUS_IS_RELEASED)
8648         {
8649                 debug_warning("FOCUS_IS_RELEASED");
8650
8651                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(FALSE, reason_for_change, &msg))
8652                 {
8653                         player->sound_focus.focus_changed_msg = (int)msg;
8654                 }
8655
8656                 if (strstr(reason_for_change, "call") ||
8657                         strstr(reason_for_change, "voip") ||    /* FIXME: to check */
8658                         strstr(reason_for_change, "alarm") ||
8659                         strstr(reason_for_change, "media"))
8660                 {
8661                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
8662                         {
8663                                 //hold 0.7 second to excute "fadedown mute" effect
8664                                 debug_warning ("do fade down->pause->undo fade down");
8665
8666                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8667
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                                 __mmplayer_undo_sound_fadedown(player);
8675                         }
8676                         else
8677                         {
8678                                 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
8679                                 _mmplayer_unrealize((MMHandleType)player);
8680                         }
8681                 }
8682 #if 0
8683 #ifdef USE_LAZY_PAUSE // if enabled, should consider event id and context when removed
8684                 else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
8685                 {
8686                         lazy_pause = TRUE; // return as soon as possible, for fast start of other app
8687
8688                         if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
8689                                 g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
8690
8691                         player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
8692                         debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
8693                 }
8694 #endif
8695 #endif
8696                 else
8697                 {
8698                         debug_warning ("pause immediately");
8699                         result = _mmplayer_pause((MMHandleType)player);
8700                         if (result != MM_ERROR_NONE)
8701                         {
8702                                 debug_warning("fail to set Pause state by asm");
8703                                 goto EXIT;
8704                         }
8705                 }
8706         }
8707         else if (focus_state == FOCUS_IS_ACQUIRED)
8708         {
8709                 debug_warning("FOCUS_IS_ACQUIRED: Got msg from asm to resume");
8710                 player->sound_focus.antishock = TRUE;
8711                 player->sound_focus.by_asm_cb = FALSE;
8712
8713                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(TRUE, reason_for_change, &msg))
8714                 {
8715                         player->sound_focus.focus_changed_msg = (int)msg;
8716                 }
8717
8718                 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
8719                 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
8720                 goto DONE;
8721         }
8722         else
8723         {
8724                 debug_warning("unknown focus state %d", focus_state);
8725         }
8726
8727 DONE:
8728         if ( !lazy_pause )
8729         {
8730                 player->sound_focus.by_asm_cb = FALSE;
8731         }
8732         player->sound_focus.cb_pending = FALSE;
8733         MMPLAYER_CMD_UNLOCK( player );
8734
8735 EXIT:
8736         debug_warning("dispatched");
8737         return;
8738 }
8739
8740
8741 int
8742 _mmplayer_create_player(MMHandleType handle) // @
8743 {
8744         mm_player_t* player = MM_PLAYER_CAST(handle);
8745
8746         MMPLAYER_FENTER();
8747
8748         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
8749
8750         /* initialize player state */
8751         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
8752         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
8753         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
8754         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
8755
8756         /* check current state */
8757         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
8758
8759         /* construct attributes */
8760         player->attrs = _mmplayer_construct_attribute(handle);
8761
8762         if ( !player->attrs )
8763         {
8764                 debug_error("Failed to construct attributes\n");
8765                 goto ERROR;
8766         }
8767
8768         /* initialize gstreamer with configured parameter */
8769         if ( ! __mmplayer_init_gstreamer(player) )
8770         {
8771                 debug_error("Initializing gstreamer failed\n");
8772                 goto ERROR;
8773         }
8774
8775         /* initialize factories if not using decodebin */
8776         if( player->factories == NULL )
8777                 __mmplayer_init_factories(player);
8778
8779         /* create lock. note that g_tread_init() has already called in gst_init() */
8780         g_mutex_init(&player->fsink_lock);
8781
8782         /* create repeat mutex */
8783         g_mutex_init(&player->repeat_thread_mutex);
8784
8785         /* create repeat cond */
8786         g_cond_init(&player->repeat_thread_cond);
8787
8788         /* create repeat thread */
8789         player->repeat_thread =
8790                 g_thread_try_new ("repeat_thread", __mmplayer_repeat_thread, (gpointer)player, NULL);
8791
8792
8793         /* create next play mutex */
8794         g_mutex_init(&player->next_play_thread_mutex);
8795
8796         /* create next play cond */
8797         g_cond_init(&player->next_play_thread_cond);
8798
8799         /* create next play thread */
8800         player->next_play_thread =
8801                 g_thread_try_new ("next_play_thread", __mmplayer_next_play_thread, (gpointer)player, NULL);
8802         if ( ! player->next_play_thread )
8803         {
8804                 debug_error("failed to create next play thread");
8805                 goto ERROR;
8806         }
8807
8808         if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
8809         {
8810                 debug_error("failed to initialize video capture\n");
8811                 goto ERROR;
8812         }
8813
8814         /* register to asm */
8815         if ( MM_ERROR_NONE != _mmplayer_sound_register(&player->sound_focus,
8816                                                 (mm_sound_focus_changed_cb)__mmplayer_sound_focus_callback,
8817                                                 (mm_sound_focus_changed_watch_cb)__mmplayer_sound_focus_watch_callback,
8818                                                 (void*)player) )
8819
8820         {
8821                 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
8822                 debug_error("failed to register asm server\n");
8823                 return MM_ERROR_POLICY_INTERNAL;
8824         }
8825 #if 0 //need to change and test
8826         /* to add active device callback */
8827         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))
8828         {
8829                 debug_error("failed mm_sound_add_device_information_changed_callback \n");
8830         }
8831 #endif
8832         if (MMPLAYER_IS_HTTP_PD(player))
8833         {
8834                 player->pd_downloader = NULL;
8835                 player->pd_file_save_path = NULL;
8836         }
8837
8838         player->streaming_type = STREAMING_SERVICE_NONE;
8839
8840         /* give default value of audio effect setting */
8841         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
8842         player->playback_rate = DEFAULT_PLAYBACK_RATE;
8843
8844         player->play_subtitle = FALSE;
8845         player->use_textoverlay = FALSE;
8846         player->play_count = 0;
8847         player->use_decodebin = TRUE;
8848         player->ignore_asyncdone = FALSE;
8849         player->use_deinterleave = FALSE;
8850         player->max_audio_channels = 0;
8851         player->video_share_api_delta = 0;
8852         player->video_share_clock_delta = 0;
8853         player->has_closed_caption = FALSE;
8854
8855         __mmplayer_post_proc_reset(player);
8856
8857         if (player->ini.dump_element_keyword[0][0] == '\0')
8858         {
8859                 player->ini.set_dump_element_flag= FALSE;
8860         }
8861         else
8862         {
8863                 player->ini.set_dump_element_flag = TRUE;
8864         }
8865
8866         /* set player state to null */
8867         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
8868         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
8869
8870         return MM_ERROR_NONE;
8871
8872 ERROR:
8873         /* free lock */
8874         g_mutex_clear(&player->fsink_lock );
8875
8876         /* free thread */
8877         if ( player->repeat_thread )
8878         {
8879                 player->repeat_thread_exit = TRUE;
8880                 g_cond_signal( &player->repeat_thread_cond );
8881
8882                 g_thread_join( player->repeat_thread );
8883                 player->repeat_thread = NULL;
8884
8885                 g_mutex_clear(&player->repeat_thread_mutex );
8886
8887                 g_cond_clear (&player->repeat_thread_cond );
8888         }
8889         /* clear repeat thread mutex/cond if still alive
8890          * this can happen if only thread creating has failed
8891          */
8892         g_mutex_clear(&player->repeat_thread_mutex );
8893         g_cond_clear ( &player->repeat_thread_cond );
8894
8895         /* free next play thread */
8896         if ( player->next_play_thread )
8897         {
8898                 player->next_play_thread_exit = TRUE;
8899                 g_cond_signal( &player->next_play_thread_cond );
8900
8901                 g_thread_join( player->next_play_thread );
8902                 player->next_play_thread = NULL;
8903
8904                 g_mutex_clear(&player->next_play_thread_mutex );
8905
8906                 g_cond_clear ( &player->next_play_thread_cond );
8907         }
8908         /* clear next play thread mutex/cond if still alive
8909          * this can happen if only thread creating has failed
8910          */
8911         g_mutex_clear(&player->next_play_thread_mutex );
8912
8913         g_cond_clear ( &player->next_play_thread_cond );
8914
8915         /* release attributes */
8916         _mmplayer_deconstruct_attribute(handle);
8917
8918         MMPLAYER_FLEAVE();
8919
8920         return MM_ERROR_PLAYER_INTERNAL;
8921 }
8922
8923 static gboolean
8924 __mmplayer_init_gstreamer(mm_player_t* player) // @
8925 {
8926         static gboolean initialized = FALSE;
8927         static const int max_argc = 50;
8928         gint* argc = NULL;
8929         gchar** argv = NULL;
8930         gchar** argv2 = NULL;
8931         GError *err = NULL;
8932         int i = 0;
8933         int arg_count = 0;
8934
8935         if ( initialized )
8936         {
8937                 debug_log("gstreamer already initialized.\n");
8938                 return TRUE;
8939         }
8940
8941         /* alloc */
8942         argc = malloc( sizeof(int) );
8943         argv = malloc( sizeof(gchar*) * max_argc );
8944         argv2 = malloc( sizeof(gchar*) * max_argc );
8945
8946         if ( !argc || !argv || !argv2)
8947                 goto ERROR;
8948
8949         memset( argv, 0, sizeof(gchar*) * max_argc );
8950         memset( argv2, 0, sizeof(gchar*) * max_argc );
8951
8952         /* add initial */
8953         *argc = 1;
8954         argv[0] = g_strdup( "mmplayer" );
8955
8956         /* add gst_param */
8957         for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
8958         {
8959                 if ( strlen( player->ini.gst_param[i] ) > 0 )
8960                 {
8961                         argv[*argc] = g_strdup( player->ini.gst_param[i] );
8962                         (*argc)++;
8963                 }
8964         }
8965
8966         /* we would not do fork for scanning plugins */
8967         argv[*argc] = g_strdup("--gst-disable-registry-fork");
8968         (*argc)++;
8969
8970         /* check disable registry scan */
8971         if ( player->ini.skip_rescan )
8972         {
8973                 argv[*argc] = g_strdup("--gst-disable-registry-update");
8974                 (*argc)++;
8975         }
8976
8977         /* check disable segtrap */
8978         if ( player->ini.disable_segtrap )
8979         {
8980                 argv[*argc] = g_strdup("--gst-disable-segtrap");
8981                 (*argc)++;
8982         }
8983
8984         debug_log("initializing gstreamer with following parameter\n");
8985         debug_log("argc : %d\n", *argc);
8986         arg_count = *argc;
8987
8988         for ( i = 0; i < arg_count; i++ )
8989         {
8990                 argv2[i] = argv[i];
8991                 debug_log("argv[%d] : %s\n", i, argv2[i]);
8992         }
8993
8994
8995         /* initializing gstreamer */
8996         if ( ! gst_init_check (argc, &argv, &err))
8997         {
8998                 debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
8999                 if (err)
9000                 {
9001                         g_error_free (err);
9002                 }
9003
9004                 goto ERROR;
9005         }
9006         /* release */
9007         for ( i = 0; i < arg_count; i++ )
9008         {
9009                 //debug_log("release - argv[%d] : %s\n", i, argv2[i]);
9010                 MMPLAYER_FREEIF( argv2[i] );
9011         }
9012
9013         MMPLAYER_FREEIF( argv );
9014         MMPLAYER_FREEIF( argv2 );
9015         MMPLAYER_FREEIF( argc );
9016
9017         /* done */
9018         initialized = TRUE;
9019
9020         return TRUE;
9021
9022 ERROR:
9023
9024         /* release */
9025         for ( i = 0; i < arg_count; i++ )
9026         {
9027                 debug_log("free[%d] : %s\n", i, argv2[i]);
9028                 MMPLAYER_FREEIF( argv2[i] );
9029         }
9030
9031         MMPLAYER_FREEIF( argv );
9032         MMPLAYER_FREEIF( argv2 );
9033         MMPLAYER_FREEIF( argc );
9034
9035         return FALSE;
9036 }
9037
9038 int
9039 __mmplayer_destroy_streaming_ext(mm_player_t* player)
9040 {
9041         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9042
9043         if (player->pd_downloader)
9044         {
9045                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
9046                 MMPLAYER_FREEIF(player->pd_downloader);
9047         }
9048
9049         if (MMPLAYER_IS_HTTP_PD(player))
9050         {
9051                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
9052                 MMPLAYER_FREEIF(player->pd_file_save_path);
9053         }
9054
9055         return MM_ERROR_NONE;
9056 }
9057
9058 int
9059 _mmplayer_destroy(MMHandleType handle) // @
9060 {
9061         mm_player_t* player = MM_PLAYER_CAST(handle);
9062
9063         MMPLAYER_FENTER();
9064
9065         /* check player handle */
9066         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9067
9068         /* destroy can called at anytime */
9069         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
9070
9071         __mmplayer_destroy_streaming_ext(player);
9072
9073         /* release repeat thread */
9074         if ( player->repeat_thread )
9075         {
9076                 player->repeat_thread_exit = TRUE;
9077                 g_cond_signal( &player->repeat_thread_cond );
9078
9079                 debug_log("waitting for repeat thread exit\n");
9080                 g_thread_join ( player->repeat_thread );
9081                 g_mutex_clear(&player->repeat_thread_mutex );
9082                 g_cond_clear (&player->repeat_thread_cond );
9083                 debug_log("repeat thread released\n");
9084         }
9085
9086         /* release next play thread */
9087         if ( player->next_play_thread )
9088         {
9089                 player->next_play_thread_exit = TRUE;
9090                 g_cond_signal( &player->next_play_thread_cond );
9091
9092                 debug_log("waitting for next play thread exit\n");
9093                 g_thread_join ( player->next_play_thread );
9094                 g_mutex_clear(&player->next_play_thread_mutex );
9095                 g_cond_clear(&player->next_play_thread_cond );
9096                 debug_log("next play thread released\n");
9097         }
9098
9099         _mmplayer_release_video_capture(player);
9100
9101         /* flush any pending asm_cb */
9102         if (player->sound_focus.cb_pending)
9103         {
9104                 /* set a flag for make sure asm_cb to be returned immediately */
9105                 debug_warning("asm cb has pending state");
9106                 player->sound_focus.exit_cb = TRUE;
9107
9108                 /* make sure to release any pending asm_cb which locked by cmd_lock */
9109                 MMPLAYER_CMD_UNLOCK(player);
9110                 sched_yield();
9111                 MMPLAYER_CMD_LOCK(player);
9112         }
9113
9114         /* withdraw asm */
9115         if ( MM_ERROR_NONE != _mmplayer_sound_unregister(&player->sound_focus) )
9116         {
9117                 debug_error("failed to deregister asm server\n");
9118         }
9119
9120 #ifdef USE_LAZY_PAUSE
9121         if (player->lazy_pause_event_id)
9122         {
9123                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->lazy_pause_event_id);
9124                 player->lazy_pause_event_id = 0;
9125         }
9126 #endif
9127
9128         if (player->resume_event_id)
9129         {
9130                 g_source_remove (player->resume_event_id);
9131                 player->resume_event_id = 0;
9132         }
9133
9134         if (player->resumable_cancel_id)
9135         {
9136                 g_source_remove (player->resumable_cancel_id);
9137                 player->resumable_cancel_id = 0;
9138         }
9139
9140         /* release pipeline */
9141         if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
9142         {
9143                 debug_error("failed to destory pipeline\n");
9144                 return MM_ERROR_PLAYER_INTERNAL;
9145         }
9146
9147         if (player->is_external_subtitle_present && player->subtitle_language_list)
9148         {
9149           g_list_free (player->subtitle_language_list);
9150           player->subtitle_language_list = NULL;
9151         }
9152
9153         __mmplayer_release_dump_list (player->dump_list);
9154
9155         /* release miscellaneous information.
9156            these info needs to be released after pipeline is destroyed. */
9157         __mmplayer_release_misc_post( player );
9158
9159         /* release attributes */
9160         _mmplayer_deconstruct_attribute( handle );
9161
9162         /* release factories */
9163         __mmplayer_release_factories( player );
9164
9165         /* release lock */
9166         g_mutex_clear(&player->fsink_lock );
9167
9168         g_mutex_clear(&player->msg_cb_lock );
9169
9170         MMPLAYER_FLEAVE();
9171
9172         return MM_ERROR_NONE;
9173 }
9174
9175 int
9176 __mmplayer_realize_streaming_ext(mm_player_t* player)
9177 {
9178         int ret = MM_ERROR_NONE;
9179
9180         MMPLAYER_FENTER();
9181         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9182
9183         if (MMPLAYER_IS_HTTP_PD(player))
9184         {
9185                 gboolean bret = FALSE;
9186
9187                 player->pd_downloader = _mmplayer_create_pd_downloader();
9188                 if ( !player->pd_downloader )
9189                 {
9190                         debug_error ("Unable to create PD Downloader...");
9191                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
9192                 }
9193
9194                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
9195
9196                 if (FALSE == bret)
9197                 {
9198                         debug_error ("Unable to create PD Downloader...");
9199                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
9200                 }
9201         }
9202
9203         MMPLAYER_FLEAVE();
9204         return ret;
9205 }
9206
9207 int
9208 _mmplayer_realize(MMHandleType hplayer) // @
9209 {
9210         mm_player_t* player =  (mm_player_t*)hplayer;
9211         char *uri =NULL;
9212         void *param = NULL;
9213         int application_pid = -1;
9214         gboolean update_registry = FALSE;
9215         MMHandleType attrs = 0;
9216         int ret = MM_ERROR_NONE;
9217
9218         MMPLAYER_FENTER();
9219
9220         /* check player handle */
9221         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
9222
9223         /* check current state */
9224         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
9225
9226         attrs = MMPLAYER_GET_ATTRS(player);
9227         if ( !attrs )
9228         {
9229                 debug_error("fail to get attributes.\n");
9230                 return MM_ERROR_PLAYER_INTERNAL;
9231         }
9232
9233         mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
9234         player->sound_focus.pid = application_pid;
9235
9236         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
9237         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
9238
9239         ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
9240
9241         if (ret != MM_ERROR_NONE)
9242         {
9243                 debug_error("failed to parse profile\n");
9244                 return ret;
9245         }
9246
9247         /* FIXIT : we can use thouse in player->profile directly */
9248         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
9249         {
9250                 player->mem_buf.buf = (char *)player->profile.mem;
9251                 player->mem_buf.len = player->profile.mem_size;
9252                 player->mem_buf.offset = 0;
9253         }
9254
9255         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF)
9256         {
9257                 if (strstr(uri, "es_buff://push_mode"))
9258                 {
9259                         player->es_player_push_mode = TRUE;
9260                 }
9261                 else
9262                 {
9263                         player->es_player_push_mode = FALSE;
9264                 }
9265         }
9266
9267         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
9268         {
9269                 debug_warning("mms protocol is not supported format.\n");
9270                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
9271         }
9272
9273         if (MMPLAYER_IS_STREAMING(player))
9274                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
9275         else
9276                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
9277
9278         player->smooth_streaming = FALSE;
9279         player->videodec_linked  = 0;
9280         player->videosink_linked = 0;
9281         player->audiodec_linked  = 0;
9282         player->audiosink_linked = 0;
9283         player->textsink_linked = 0;
9284         player->is_external_subtitle_present = FALSE;
9285         /* set the subtitle ON default */
9286         player->is_subtitle_off = FALSE;
9287
9288         /* registry should be updated for downloadable codec */
9289         mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
9290
9291         if ( update_registry )
9292         {
9293                 debug_log("updating registry...\n");
9294                 gst_update_registry();
9295
9296                 /* then we have to rebuild factories */
9297                 __mmplayer_release_factories( player );
9298                 __mmplayer_init_factories(player);
9299         }
9300
9301         /* realize pipeline */
9302         ret = __gst_realize( player );
9303         if ( ret != MM_ERROR_NONE )
9304         {
9305                 debug_error("fail to realize the player.\n");
9306         }
9307         else
9308         {
9309                 ret = __mmplayer_realize_streaming_ext(player);
9310         }
9311
9312         MMPLAYER_FLEAVE();
9313
9314         return ret;
9315 }
9316
9317 int
9318 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
9319 {
9320         MMPLAYER_FENTER();
9321         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9322
9323         /* destroy can called at anytime */
9324         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
9325         {
9326                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
9327                 MMPLAYER_FREEIF(player->pd_downloader);
9328         }
9329
9330         MMPLAYER_FLEAVE();
9331         return MM_ERROR_NONE;
9332 }
9333
9334 int
9335 _mmplayer_unrealize(MMHandleType hplayer)
9336 {
9337         mm_player_t* player = (mm_player_t*)hplayer;
9338         int ret = MM_ERROR_NONE;
9339
9340         MMPLAYER_FENTER();
9341
9342         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
9343
9344         /* check current state */
9345         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
9346
9347         __mmplayer_unrealize_streaming_ext(player);
9348
9349         /* unrealize pipeline */
9350         ret = __gst_unrealize( player );
9351
9352         /* set asm stop if success */
9353         if (MM_ERROR_NONE == ret)
9354         {
9355                 ret = _mmplayer_sound_release_focus(&player->sound_focus);
9356                 if ( ret != MM_ERROR_NONE )
9357                 {
9358                         debug_error("failed to release sound focus\n");
9359                         return ret;
9360                 }
9361         }
9362         else
9363         {
9364                 debug_error("failed and don't change asm state to stop");
9365         }
9366
9367         MMPLAYER_FLEAVE();
9368
9369         return ret;
9370 }
9371
9372 int
9373 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
9374 {
9375         mm_player_t* player = (mm_player_t*)hplayer;
9376
9377         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9378
9379         return __gst_set_message_callback(player, callback, user_param);
9380 }
9381
9382 int
9383 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
9384 {
9385         mm_player_t *player = (mm_player_t*)hplayer;
9386
9387         return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
9388
9389         *state = MMPLAYER_CURRENT_STATE(player);
9390
9391         return MM_ERROR_NONE;
9392 }
9393
9394
9395 int
9396 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
9397 {
9398         mm_player_t* player = (mm_player_t*) hplayer;
9399         GstElement* vol_element = NULL;
9400         int i = 0;
9401
9402         MMPLAYER_FENTER();
9403
9404         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9405
9406         debug_log("volume [L]=%f:[R]=%f\n",
9407                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
9408
9409         /* invalid factor range or not */
9410         for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
9411         {
9412                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
9413                         debug_error("Invalid factor! (valid factor:0~1.0)\n");
9414                         return MM_ERROR_INVALID_ARGUMENT;
9415                 }
9416         }
9417
9418         /* not support to set other value into each channel */
9419         if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
9420                 return MM_ERROR_INVALID_ARGUMENT;
9421
9422         /* Save volume to handle. Currently the first array element will be saved. */
9423         player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
9424
9425         /* check pipeline handle */
9426         if ( ! player->pipeline || ! player->pipeline->audiobin )
9427         {
9428                 debug_log("audiobin is not created yet\n");
9429                 debug_log("but, current stored volume will be set when it's created.\n");
9430
9431                 /* NOTE : stored volume will be used in create_audiobin
9432                  * returning MM_ERROR_NONE here makes application to able to
9433                  * set volume at anytime.
9434                  */
9435                 return MM_ERROR_NONE;
9436         }
9437
9438         /* setting volume to volume element */
9439         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
9440
9441         if ( vol_element )
9442         {
9443                 debug_log("volume is set [%f]\n", player->sound.volume);
9444                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
9445         }
9446
9447         MMPLAYER_FLEAVE();
9448
9449         return MM_ERROR_NONE;
9450 }
9451
9452
9453 int
9454 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
9455 {
9456         mm_player_t* player = (mm_player_t*) hplayer;
9457         int i = 0;
9458
9459         MMPLAYER_FENTER();
9460
9461         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9462         return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
9463
9464         /* returning stored volume */
9465         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
9466                 volume->level[i] = player->sound.volume;
9467
9468         MMPLAYER_FLEAVE();
9469
9470         return MM_ERROR_NONE;
9471 }
9472
9473
9474
9475 int
9476 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
9477 {
9478         mm_player_t* player = (mm_player_t*) hplayer;
9479         GstElement* vol_element = NULL;
9480
9481         MMPLAYER_FENTER();
9482
9483         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9484
9485         /* mute value shoud 0 or 1 */
9486         if ( mute != 0 && mute != 1 )
9487         {
9488                 debug_error("bad mute value\n");
9489
9490                 /* FIXIT : definitly, we need _BAD_PARAM error code */
9491                 return MM_ERROR_INVALID_ARGUMENT;
9492         }
9493
9494         player->sound.mute = mute;
9495
9496         /* just hold mute value if pipeline is not ready */
9497         if ( !player->pipeline || !player->pipeline->audiobin )
9498         {
9499                 debug_log("pipeline is not ready. holding mute value\n");
9500                 return MM_ERROR_NONE;
9501         }
9502
9503         vol_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
9504
9505         /* NOTE : volume will only created when the bt is enabled */
9506         if ( vol_element )
9507         {
9508                 debug_log("mute : %d\n", mute);
9509                 g_object_set(vol_element, "mute", mute, NULL);
9510         }
9511         else
9512         {
9513                 debug_log("volume elemnet is not created. using volume in audiosink\n");
9514         }
9515
9516         MMPLAYER_FLEAVE();
9517
9518         return MM_ERROR_NONE;
9519 }
9520
9521 int
9522 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
9523 {
9524         mm_player_t* player = (mm_player_t*) hplayer;
9525
9526         MMPLAYER_FENTER();
9527
9528         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9529         return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
9530
9531         /* just hold mute value if pipeline is not ready */
9532         if ( !player->pipeline || !player->pipeline->audiobin )
9533         {
9534                 debug_log("pipeline is not ready. returning stored value\n");
9535                 *pmute = player->sound.mute;
9536                 return MM_ERROR_NONE;
9537         }
9538
9539         *pmute = player->sound.mute;
9540
9541         MMPLAYER_FLEAVE();
9542
9543         return MM_ERROR_NONE;
9544 }
9545
9546 int
9547 _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
9548 {
9549         mm_player_t* player = (mm_player_t*) hplayer;
9550
9551         MMPLAYER_FENTER();
9552
9553         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9554
9555         player->video_stream_changed_cb = callback;
9556         player->video_stream_changed_cb_user_param = user_param;
9557         debug_log("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
9558
9559         MMPLAYER_FLEAVE();
9560
9561         return MM_ERROR_NONE;
9562 }
9563
9564 int
9565 _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
9566 {
9567         mm_player_t* player = (mm_player_t*) hplayer;
9568
9569         MMPLAYER_FENTER();
9570
9571         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9572
9573         player->audio_stream_changed_cb = callback;
9574         player->audio_stream_changed_cb_user_param = user_param;
9575         debug_log("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
9576
9577         MMPLAYER_FLEAVE();
9578
9579         return MM_ERROR_NONE;
9580 }
9581
9582 int
9583 _mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param) // @
9584 {
9585         mm_player_t* player = (mm_player_t*) hplayer;
9586
9587         MMPLAYER_FENTER();
9588
9589         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9590
9591         player->audio_stream_render_cb_ex = callback;
9592         player->audio_stream_cb_user_param = user_param;
9593         player->audio_stream_sink_sync = sync;
9594         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);
9595
9596         MMPLAYER_FLEAVE();
9597
9598         return MM_ERROR_NONE;
9599 }
9600
9601 int
9602 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
9603 {
9604         mm_player_t* player = (mm_player_t*) hplayer;
9605
9606         MMPLAYER_FENTER();
9607
9608         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9609
9610         player->video_stream_cb = callback;
9611         player->video_stream_cb_user_param = user_param;
9612         player->use_video_stream = TRUE;
9613         debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
9614
9615         MMPLAYER_FLEAVE();
9616
9617         return MM_ERROR_NONE;
9618 }
9619
9620 int
9621 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
9622 {
9623         mm_player_t* player = (mm_player_t*) hplayer;
9624
9625         MMPLAYER_FENTER();
9626
9627         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9628
9629         player->audio_stream_cb = callback;
9630         player->audio_stream_cb_user_param = user_param;
9631         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
9632
9633         MMPLAYER_FLEAVE();
9634
9635         return MM_ERROR_NONE;
9636 }
9637
9638 // set prepare size
9639 int
9640 _mmplayer_set_prepare_buffering_time(MMHandleType hplayer, int second)
9641 {
9642         mm_player_t* player = (mm_player_t*) hplayer;
9643
9644         MMPLAYER_FENTER();
9645
9646         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9647
9648         if (MMPLAYER_CURRENT_STATE(player) !=  MM_PLAYER_STATE_NULL)
9649                 return MM_ERROR_PLAYER_INVALID_STATE;
9650
9651         debug_log("pre buffer size : %d sec\n", second);
9652
9653         if ( second <= 0 )
9654         {
9655                 debug_error("bad size value\n");
9656                 return MM_ERROR_INVALID_ARGUMENT;
9657         }
9658
9659         if (player->streamer == NULL)
9660         {
9661                 player->streamer = __mm_player_streaming_create();
9662                 __mm_player_streaming_initialize(player->streamer);
9663         }
9664
9665         player->streamer->buffering_req.initial_second = second;
9666
9667         MMPLAYER_FLEAVE();
9668
9669         return MM_ERROR_NONE;
9670 }
9671
9672 // set runtime mode
9673 int
9674 _mmplayer_set_runtime_buffering_mode(MMHandleType hplayer, MMPlayerBufferingMode mode, int second)
9675 {
9676         mm_player_t* player = (mm_player_t*) hplayer;
9677
9678         MMPLAYER_FENTER();
9679
9680         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9681
9682         debug_log("mode %d\n", mode);
9683
9684         if ((mode < 0) || (mode > MM_PLAYER_BUFFERING_MODE_MAX) ||
9685                 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) && (second <= 0)))
9686                 return MM_ERROR_INVALID_ARGUMENT;
9687
9688         if (player->streamer == NULL)
9689         {
9690                 player->streamer = __mm_player_streaming_create();
9691                 __mm_player_streaming_initialize(player->streamer);
9692         }
9693
9694         player->streamer->buffering_req.mode = mode;
9695
9696         if ((second > 0) &&
9697                 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) ||
9698                  (mode == MM_PLAYER_BUFFERING_MODE_ADAPTIVE)))
9699                 player->streamer->buffering_req.runtime_second = second;
9700
9701         MMPLAYER_FLEAVE();
9702
9703         return MM_ERROR_NONE;
9704 }
9705
9706 int
9707 _mmplayer_set_videoframe_render_error_cb(MMHandleType hplayer, mm_player_video_frame_render_error_callback callback, void *user_param) // @
9708 {
9709         mm_player_t* player = (mm_player_t*) hplayer;
9710
9711         MMPLAYER_FENTER();
9712
9713         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9714         return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
9715
9716         player->video_frame_render_error_cb = callback;
9717         player->video_frame_render_error_cb_user_param = user_param;
9718
9719         debug_log("Video frame render error cb Handle value is %p : %p\n", player, player->video_frame_render_error_cb);
9720
9721         MMPLAYER_FLEAVE();
9722
9723         return MM_ERROR_NONE;
9724 }
9725
9726 int
9727 __mmplayer_start_streaming_ext(mm_player_t *player)
9728 {
9729         gint ret = MM_ERROR_NONE;
9730
9731         MMPLAYER_FENTER();
9732         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9733
9734         if (MMPLAYER_IS_HTTP_PD(player))
9735         {
9736                 if ( !player->pd_downloader )
9737                 {
9738                         ret = __mmplayer_realize_streaming_ext(player);
9739
9740                         if ( ret != MM_ERROR_NONE)
9741                         {
9742                                 debug_error ("failed to realize streaming ext\n");
9743                                 return ret;
9744                         }
9745                 }
9746
9747                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
9748                 {
9749                         ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
9750                         if ( !ret )
9751                         {
9752                                 debug_error ("ERROR while starting PD...\n");
9753                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
9754                         }
9755                         ret = MM_ERROR_NONE;
9756                 }
9757         }
9758
9759         MMPLAYER_FLEAVE();
9760         return ret;
9761 }
9762
9763 int
9764 _mmplayer_start(MMHandleType hplayer) // @
9765 {
9766         mm_player_t* player = (mm_player_t*) hplayer;
9767         gint ret = MM_ERROR_NONE;
9768
9769         MMPLAYER_FENTER();
9770
9771         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9772
9773         /* check current state */
9774         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
9775
9776         ret = _mmplayer_sound_acquire_focus(&player->sound_focus);
9777         if ( ret != MM_ERROR_NONE )
9778         {
9779                 debug_error("failed to acquire sound focus.\n");
9780                 return ret;
9781         }
9782
9783         /* NOTE : we should check and create pipeline again if not created as we destroy
9784          * whole pipeline when stopping in streamming playback
9785          */
9786         if ( ! player->pipeline )
9787         {
9788                 ret = __gst_realize( player );
9789                 if ( MM_ERROR_NONE != ret )
9790                 {
9791                         debug_error("failed to realize before starting. only in streamming\n");
9792                         /* unlock */
9793                         return ret;
9794                 }
9795         }
9796
9797         ret = __mmplayer_start_streaming_ext(player);
9798         if ( ret != MM_ERROR_NONE )
9799         {
9800                 debug_error("failed to start streaming ext \n");
9801         }
9802
9803         /* start pipeline */
9804         ret = __gst_start( player );
9805         if ( ret != MM_ERROR_NONE )
9806         {
9807                 debug_error("failed to start player.\n");
9808         }
9809
9810         MMPLAYER_FLEAVE();
9811
9812         return ret;
9813 }
9814
9815 /* NOTE: post "not supported codec message" to application
9816  * when one codec is not found during AUTOPLUGGING in MSL.
9817  * So, it's separated with error of __mmplayer_gst_callback().
9818  * And, if any codec is not found, don't send message here.
9819  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
9820  */
9821 int
9822 __mmplayer_handle_missed_plugin(mm_player_t* player)
9823 {
9824         MMMessageParamType msg_param;
9825         memset (&msg_param, 0, sizeof(MMMessageParamType));
9826         gboolean post_msg_direct = FALSE;
9827
9828         MMPLAYER_FENTER();
9829
9830         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9831
9832         debug_log("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
9833                         player->not_supported_codec, player->can_support_codec);
9834
9835         if( player->not_found_demuxer )
9836         {
9837                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9838                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
9839
9840                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
9841                 MMPLAYER_FREEIF(msg_param.data);
9842
9843                 return MM_ERROR_NONE;
9844         }
9845
9846         if (player->not_supported_codec)
9847         {
9848                 if ( player->can_support_codec ) // There is one codec to play
9849                 {
9850                         post_msg_direct = TRUE;
9851                 }
9852                 else
9853                 {
9854                         if ( player->pipeline->audiobin ) // Some content has only PCM data in container.
9855                                 post_msg_direct = TRUE;
9856                 }
9857
9858                 if ( post_msg_direct )
9859                 {
9860                         MMMessageParamType msg_param;
9861                         memset (&msg_param, 0, sizeof(MMMessageParamType));
9862
9863                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
9864                         {
9865                                 debug_warning("not found AUDIO codec, posting error code to application.\n");
9866
9867                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9868                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9869                         }
9870                         else if ( player->not_supported_codec ==  MISSING_PLUGIN_VIDEO )
9871                         {
9872                                 debug_warning("not found VIDEO codec, posting error code to application.\n");
9873
9874                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9875                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
9876                         }
9877
9878                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
9879
9880                         MMPLAYER_FREEIF(msg_param.data);
9881
9882                         return MM_ERROR_NONE;
9883                 }
9884                 else // no any supported codec case
9885                 {
9886                         debug_warning("not found any codec, posting error code to application.\n");
9887
9888                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
9889                         {
9890                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9891                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9892                         }
9893                         else
9894                         {
9895                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9896                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
9897                         }
9898
9899                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
9900
9901                         MMPLAYER_FREEIF(msg_param.data);
9902                 }
9903         }
9904
9905         MMPLAYER_FLEAVE();
9906
9907         return MM_ERROR_NONE;
9908 }
9909
9910 static void __mmplayer_check_pipeline(mm_player_t* player)
9911 {
9912         GstState element_state = GST_STATE_VOID_PENDING;
9913         GstState element_pending_state = GST_STATE_VOID_PENDING;
9914         gint timeout = 0;
9915         int ret = MM_ERROR_NONE;
9916
9917         if (player->gapless.reconfigure)
9918         {
9919                 debug_warning("pipeline is under construction.\n");
9920
9921                 MMPLAYER_PLAYBACK_LOCK(player);
9922                 MMPLAYER_PLAYBACK_UNLOCK(player);
9923
9924                 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
9925
9926                 /* wait for state transition */
9927                 ret = gst_element_get_state( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND );
9928
9929                 if ( ret == GST_STATE_CHANGE_FAILURE )
9930                 {
9931                         debug_error("failed to change pipeline state within %d sec\n", timeout );
9932                 }
9933         }
9934 }
9935
9936 /* NOTE : it should be able to call 'stop' anytime*/
9937 int
9938 _mmplayer_stop(MMHandleType hplayer) // @
9939 {
9940         mm_player_t* player = (mm_player_t*)hplayer;
9941         int ret = MM_ERROR_NONE;
9942
9943         MMPLAYER_FENTER();
9944
9945         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9946
9947         /* check current state */
9948         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
9949
9950         /* check pipline building state */
9951         __mmplayer_check_pipeline(player);
9952         player->gapless.start_time = 0;
9953
9954         /* NOTE : application should not wait for EOS after calling STOP */
9955         __mmplayer_cancel_eos_timer( player );
9956
9957         __mmplayer_unrealize_streaming_ext(player);
9958
9959         /* reset */
9960         player->doing_seek = FALSE;
9961
9962         /* stop pipeline */
9963         ret = __gst_stop( player );
9964
9965         if ( ret != MM_ERROR_NONE )
9966         {
9967                 debug_error("failed to stop player.\n");
9968         }
9969
9970         MMPLAYER_FLEAVE();
9971
9972         return ret;
9973 }
9974
9975 int
9976 _mmplayer_pause(MMHandleType hplayer) // @
9977 {
9978         mm_player_t* player = (mm_player_t*)hplayer;
9979         gint64 pos_msec = 0;
9980         gboolean async = FALSE;
9981         gint ret = MM_ERROR_NONE;
9982
9983         MMPLAYER_FENTER();
9984
9985         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9986
9987         /* check current state */
9988         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
9989
9990         /* check pipline building state */
9991         __mmplayer_check_pipeline(player);
9992
9993         switch (MMPLAYER_CURRENT_STATE(player))
9994         {
9995                 case MM_PLAYER_STATE_READY:
9996                 {
9997                         /* check prepare async or not.
9998                          * In the case of streaming playback, it's recommned to avoid blocking wait.
9999                          */
10000                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10001                         debug_log("prepare working mode : %s", (async ? "async" : "sync"));
10002                 }
10003                 break;
10004
10005                 case MM_PLAYER_STATE_PLAYING:
10006                 {
10007                         /* NOTE : store current point to overcome some bad operation
10008                         * ( returning zero when getting current position in paused state) of some
10009                         * elements
10010                         */
10011                         if ( !gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec))
10012                                 debug_warning("getting current position failed in paused\n");
10013
10014                         player->last_position = pos_msec;
10015                 }
10016                 break;
10017         }
10018
10019         /* pause pipeline */
10020         ret = __gst_pause( player, async );
10021
10022         if ( ret != MM_ERROR_NONE )
10023         {
10024                 debug_error("failed to pause player. ret : 0x%x\n", ret);
10025         }
10026
10027         MMPLAYER_FLEAVE();
10028
10029         return ret;
10030 }
10031
10032 int
10033 _mmplayer_resume(MMHandleType hplayer)
10034 {
10035         mm_player_t* player = (mm_player_t*)hplayer;
10036         int ret = MM_ERROR_NONE;
10037         gboolean async = FALSE;
10038
10039         MMPLAYER_FENTER();
10040
10041         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10042
10043         ret = _mmplayer_sound_acquire_focus(&player->sound_focus);
10044         if ( ret != MM_ERROR_NONE )
10045         {
10046                 debug_error("failed to acquire sound focus.\n");
10047                 return ret;
10048         }
10049
10050         /* check current state */
10051         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
10052
10053         ret = __gst_resume( player, async );
10054
10055         if ( ret != MM_ERROR_NONE )
10056         {
10057                 debug_error("failed to resume player.\n");
10058         }
10059
10060         MMPLAYER_FLEAVE();
10061
10062         return ret;
10063 }
10064
10065 int
10066 __mmplayer_set_play_count(mm_player_t* player, gint count)
10067 {
10068         MMHandleType attrs = 0;
10069
10070         MMPLAYER_FENTER();
10071
10072         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10073
10074         attrs =  MMPLAYER_GET_ATTRS(player);
10075         if ( !attrs )
10076         {
10077                 debug_error("fail to get attributes.\n");
10078                 return MM_ERROR_PLAYER_INTERNAL;
10079         }
10080
10081         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
10082         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
10083                 debug_error("failed to commit\n");
10084
10085         MMPLAYER_FLEAVE();
10086
10087         return  MM_ERROR_NONE;
10088 }
10089
10090 int
10091 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
10092 {
10093         mm_player_t* player = (mm_player_t*)hplayer;
10094         gint64 start_pos = 0;
10095         gint64 end_pos = 0;
10096         gint infinity = -1;
10097
10098         MMPLAYER_FENTER();
10099
10100         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10101         return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
10102
10103         player->section_repeat = TRUE;
10104         player->section_repeat_start = start;
10105         player->section_repeat_end = end;
10106
10107         start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
10108         end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
10109
10110         __mmplayer_set_play_count( player, infinity );
10111
10112         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10113                                         player->playback_rate,
10114                                         GST_FORMAT_TIME,
10115                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10116                                         GST_SEEK_TYPE_SET, start_pos,
10117                                         GST_SEEK_TYPE_SET, end_pos)))
10118         {
10119                 debug_error("failed to activate section repeat\n");
10120
10121                 return MM_ERROR_PLAYER_SEEK;
10122         }
10123
10124         debug_log("succeeded to set section repeat from %d to %d\n",
10125                 player->section_repeat_start, player->section_repeat_end);
10126
10127         MMPLAYER_FLEAVE();
10128
10129         return  MM_ERROR_NONE;
10130 }
10131
10132 static int
10133 __mmplayer_set_pcm_extraction(mm_player_t* player)
10134 {
10135         gint64 start_nsec = 0;
10136         gint64 end_nsec = 0;
10137         gint64 dur_nsec = 0;
10138         gint64 dur_msec = 0;
10139         int required_start = 0;
10140         int required_end = 0;
10141         int ret = 0;
10142
10143         MMPLAYER_FENTER();
10144
10145         return_val_if_fail( player, FALSE );
10146
10147         mm_attrs_multiple_get(player->attrs,
10148                 NULL,
10149                 "pcm_extraction_start_msec", &required_start,
10150                 "pcm_extraction_end_msec", &required_end,
10151                 NULL);
10152
10153         debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
10154
10155         if (required_start == 0 && required_end == 0)
10156         {
10157                 debug_log("extracting entire stream");
10158                 return MM_ERROR_NONE;
10159         }
10160         else if (required_start < 0 || required_start > required_end || required_end < 0 )
10161         {
10162                 debug_log("invalid range for pcm extraction");
10163                 return MM_ERROR_INVALID_ARGUMENT;
10164         }
10165
10166         /* get duration */
10167         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
10168         if ( !ret )
10169         {
10170                 debug_error("failed to get duration");
10171                 return MM_ERROR_PLAYER_INTERNAL;
10172         }
10173         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
10174
10175         if (dur_msec < required_end) // FIXME
10176         {
10177                 debug_log("invalid end pos for pcm extraction");
10178                 return MM_ERROR_INVALID_ARGUMENT;
10179         }
10180
10181         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
10182         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
10183
10184         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10185                                         1.0,
10186                                         GST_FORMAT_TIME,
10187                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10188                                         GST_SEEK_TYPE_SET, start_nsec,
10189                                         GST_SEEK_TYPE_SET, end_nsec)))
10190         {
10191                 debug_error("failed to seek for pcm extraction\n");
10192
10193                 return MM_ERROR_PLAYER_SEEK;
10194         }
10195
10196         debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
10197
10198         MMPLAYER_FLEAVE();
10199
10200         return MM_ERROR_NONE;
10201 }
10202
10203 int
10204 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
10205 {
10206         mm_player_t* player = (mm_player_t*)hplayer;
10207         gint64 cur_pos = 0;
10208         gint onetime = 1;
10209
10210         MMPLAYER_FENTER();
10211
10212         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10213
10214         player->section_repeat = FALSE;
10215
10216         __mmplayer_set_play_count( player, onetime );
10217
10218         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_pos);
10219
10220         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10221                                         1.0,
10222                                         GST_FORMAT_TIME,
10223                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10224                                         GST_SEEK_TYPE_SET, cur_pos,
10225                                         GST_SEEK_TYPE_SET, player->duration )))
10226         {
10227                 debug_error("failed to deactivate section repeat\n");
10228
10229                 return MM_ERROR_PLAYER_SEEK;
10230         }
10231
10232         MMPLAYER_FENTER();
10233
10234         return MM_ERROR_NONE;
10235 }
10236
10237 int
10238 _mmplayer_set_playspeed(MMHandleType hplayer, float rate)
10239 {
10240         mm_player_t* player = (mm_player_t*)hplayer;
10241         gint64 pos_msec = 0;
10242         int ret = MM_ERROR_NONE;
10243         int mute = FALSE;
10244         signed long long start = 0, stop = 0;
10245         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
10246         MMPLAYER_FENTER();
10247
10248         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
10249         return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
10250
10251         /* The sound of video is not supported under 0.0 and over 2.0. */
10252         if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
10253         {
10254                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
10255                         mute = TRUE;
10256         }
10257         _mmplayer_set_mute(hplayer, mute);
10258
10259         if (player->playback_rate == rate)
10260                 return MM_ERROR_NONE;
10261
10262         /* If the position is reached at start potion during fast backward, EOS is posted.
10263          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
10264          * */
10265         player->playback_rate = rate;
10266
10267         current_state = MMPLAYER_CURRENT_STATE(player);
10268
10269         if ( current_state != MM_PLAYER_STATE_PAUSED )
10270                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
10271
10272         debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
10273
10274         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
10275                 || ( ! ret ))
10276                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
10277         {
10278                 debug_warning("returning last point : %lld\n", player->last_position );
10279                 pos_msec = player->last_position;
10280         }
10281
10282
10283         if(rate >= 0)
10284         {
10285                 start = pos_msec;
10286                 stop = GST_CLOCK_TIME_NONE;
10287         }
10288         else
10289         {
10290                 start = GST_CLOCK_TIME_NONE;
10291                 stop = pos_msec;
10292         }
10293         if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10294                                 rate,
10295                                 GST_FORMAT_TIME,
10296                                 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10297                                 GST_SEEK_TYPE_SET, start,
10298                                 GST_SEEK_TYPE_SET, stop)))
10299         {
10300                 debug_error("failed to set speed playback\n");
10301                 return MM_ERROR_PLAYER_SEEK;
10302         }
10303
10304         debug_log("succeeded to set speed playback as %0.1f\n", rate);
10305
10306         MMPLAYER_FLEAVE();
10307
10308         return MM_ERROR_NONE;;
10309 }
10310
10311 int
10312 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
10313 {
10314         mm_player_t* player = (mm_player_t*)hplayer;
10315         int ret = MM_ERROR_NONE;
10316
10317         MMPLAYER_FENTER();
10318
10319         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10320
10321         ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
10322
10323         MMPLAYER_FLEAVE();
10324
10325         return ret;
10326 }
10327
10328 int
10329 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
10330 {
10331         mm_player_t* player = (mm_player_t*)hplayer;
10332         int ret = MM_ERROR_NONE;
10333
10334         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10335
10336         ret = __gst_get_position ( player, format, position );
10337
10338         return ret;
10339 }
10340
10341 int
10342 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
10343 {
10344         mm_player_t* player = (mm_player_t*)hplayer;
10345         int ret = MM_ERROR_NONE;
10346
10347         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10348
10349         ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
10350
10351         return ret;
10352 }
10353
10354 int
10355 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
10356 {
10357         mm_player_t* player = (mm_player_t*)hplayer;
10358         int ret = MM_ERROR_NONE;
10359
10360         MMPLAYER_FENTER();
10361
10362         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10363
10364         ret = __gst_adjust_subtitle_position(player, format, position);
10365
10366         MMPLAYER_FLEAVE();
10367
10368         return ret;
10369 }
10370 int
10371 _mmplayer_adjust_video_postion(MMHandleType hplayer, int offset) // @
10372 {
10373         mm_player_t* player = (mm_player_t*)hplayer;
10374         int ret = MM_ERROR_NONE;
10375
10376         MMPLAYER_FENTER();
10377
10378         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10379
10380         ret = __gst_adjust_video_position(player, offset);
10381
10382         MMPLAYER_FLEAVE();
10383
10384         return ret;
10385 }
10386
10387 static gboolean
10388 __mmplayer_is_midi_type( gchar* str_caps)
10389 {
10390         if ( ( g_strrstr(str_caps, "audio/midi") ) ||
10391                 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
10392                 ( g_strrstr(str_caps, "application/x-smaf") ) ||
10393                 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
10394                 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
10395                 ( g_strrstr(str_caps, "audio/xmf") ) ||
10396                 ( g_strrstr(str_caps, "audio/mxmf") ) )
10397         {
10398                 debug_log("midi\n");
10399
10400                 return TRUE;
10401         }
10402
10403         return FALSE;
10404 }
10405
10406 static gboolean
10407 __mmplayer_is_only_mp3_type (gchar *str_caps)
10408 {
10409         if (g_strrstr(str_caps, "application/x-id3") ||
10410                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
10411         {
10412                 return TRUE;
10413         }
10414         return FALSE;
10415 }
10416
10417 static void
10418 __mmplayer_set_audio_attrs (mm_player_t* player, GstCaps* caps)
10419 {
10420         GstStructure* caps_structure = NULL;
10421         gint samplerate = 0;
10422         gint channels = 0;
10423
10424         MMPLAYER_FENTER();
10425         return_if_fail (player && caps);
10426
10427         caps_structure = gst_caps_get_structure(caps, 0);
10428
10429         /* set stream information */
10430         gst_structure_get_int (caps_structure, "rate", &samplerate);
10431         mm_attrs_set_int_by_name (player->attrs, "content_audio_samplerate", samplerate);
10432
10433         gst_structure_get_int (caps_structure, "channels", &channels);
10434         mm_attrs_set_int_by_name (player->attrs, "content_audio_channels", channels);
10435
10436         debug_log ("audio samplerate : %d       channels : %d\n", samplerate, channels);
10437 }
10438
10439 static void
10440 __mmplayer_update_content_type_info(mm_player_t* player)
10441 {
10442         MMPLAYER_FENTER();
10443         return_if_fail( player && player->type);
10444
10445         if (__mmplayer_is_midi_type(player->type))
10446         {
10447                 player->bypass_audio_effect = TRUE;
10448         }
10449         else if (g_strrstr(player->type, "application/x-hls"))
10450         {
10451                 /* If it can't know exact type when it parses uri because of redirection case,
10452                  * it will be fixed by typefinder or when doing autoplugging.
10453                  */
10454                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
10455                 if (player->streamer)
10456                 {
10457                         player->streamer->is_adaptive_streaming = TRUE;
10458                         player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
10459                         player->streamer->buffering_req.runtime_second = 5;
10460                 }
10461         }
10462         else if (g_strrstr(player->type, "application/dash+xml"))
10463         {
10464                 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
10465         }
10466
10467         MMPLAYER_FLEAVE();
10468 }
10469
10470 static void
10471 __mmplayer_typefind_have_type(  GstElement *tf, guint probability,  // @
10472 GstCaps *caps, gpointer data)
10473 {
10474         mm_player_t* player = (mm_player_t*)data;
10475         GstPad* pad = NULL;
10476
10477         MMPLAYER_FENTER();
10478
10479         return_if_fail( player && tf && caps );
10480
10481         /* store type string */
10482         MMPLAYER_FREEIF(player->type);
10483         player->type = gst_caps_to_string(caps);
10484         if (player->type)
10485                 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
10486
10487         if ( (!MMPLAYER_IS_WFD_STREAMING( player )) &&
10488                  (!MMPLAYER_IS_RTSP_STREAMING( player )) &&
10489                  (g_strrstr(player->type, "audio/x-raw-int")))
10490         {
10491                 debug_error("not support media format\n");
10492
10493                 if (player->msg_posted == FALSE)
10494                 {
10495                         MMMessageParamType msg_param;
10496                         memset (&msg_param, 0, sizeof(MMMessageParamType));
10497
10498                         msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
10499                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10500
10501                         /* don't post more if one was sent already */
10502                         player->msg_posted = TRUE;
10503                 }
10504                 return;
10505         }
10506
10507         __mmplayer_update_content_type_info(player);
10508
10509         pad = gst_element_get_static_pad(tf, "src");
10510         if ( !pad )
10511         {
10512                 debug_error("fail to get typefind src pad.\n");
10513                 return;
10514         }
10515
10516         if (player->use_decodebin)
10517         {
10518                 if(!__mmplayer_try_to_plug_decodebin( player, pad, caps ))
10519                 {
10520                         gboolean async = FALSE;
10521                         debug_error("failed to autoplug %s\n", player->type);
10522
10523                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10524
10525                         if ( async && player->msg_posted == FALSE )
10526                         {
10527                                 __mmplayer_handle_missed_plugin( player );
10528                         }
10529
10530                         goto DONE;
10531                 }
10532         }
10533         else
10534         {
10535                 /* try to plug */
10536                 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
10537                 {
10538                         gboolean async = FALSE;
10539                         debug_error("failed to autoplug %s\n", player->type);
10540
10541                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10542
10543                         if ( async && player->msg_posted == FALSE )
10544                         {
10545                                 __mmplayer_handle_missed_plugin( player );
10546                         }
10547
10548                         goto DONE;
10549                 }
10550
10551                 /* finish autopluging if no dynamic pad waiting */
10552                 if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
10553                 {
10554                         if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
10555                         {
10556                                 __mmplayer_pipeline_complete( NULL, (gpointer)player );
10557                         }
10558                 }
10559         }
10560
10561 DONE:
10562         gst_object_unref( GST_OBJECT(pad) );
10563
10564         MMPLAYER_FLEAVE();
10565
10566         return;
10567 }
10568
10569 #ifdef _MM_PLAYER_ALP_PARSER
10570 void check_name (void *data, void *user_data)
10571 {
10572         mm_player_t* player = user_data;
10573
10574         if (g_strrstr((gchar*)data, "mpegaudioparse"))
10575         {
10576                 debug_log("mpegaudioparse - set alp-mp3dec\n");
10577                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "alp-mp3dec", TRUE, NULL);
10578         }
10579 }
10580 #endif
10581
10582 static GstElement *
10583 __mmplayer_create_decodebin (mm_player_t* player)
10584 {
10585         GstElement *decodebin = NULL;
10586
10587         MMPLAYER_FENTER();
10588
10589         /* create decodebin */
10590         decodebin = gst_element_factory_make("decodebin", NULL);
10591
10592         if (!decodebin)
10593         {
10594                 debug_error("fail to create decodebin\n");
10595                 goto ERROR;
10596         }
10597
10598         /* raw pad handling signal */
10599         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
10600                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
10601
10602         /* no-more-pad pad handling signal */
10603         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
10604                                                 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
10605
10606         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
10607                                                 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
10608
10609         /* This signal is emitted when a pad for which there is no further possible
10610            decoding is added to the decodebin.*/
10611         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
10612                                                 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player );
10613
10614         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
10615            before looking for any elements that can handle that stream.*/
10616         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
10617                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
10618
10619         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
10620            before looking for any elements that can handle that stream.*/
10621         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
10622                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
10623
10624         /* This signal is emitted once decodebin has finished decoding all the data.*/
10625         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
10626                                                 G_CALLBACK(__mmplayer_gst_decode_drained), player);
10627
10628         /* This signal is emitted when a element is added to the bin.*/
10629         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
10630                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
10631
10632 ERROR:
10633         return decodebin;
10634 }
10635
10636 static gboolean
10637 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
10638 {
10639         MMPlayerGstElement* mainbin = NULL;
10640         GstElement* decodebin = NULL;
10641         GstElement* queue2 = NULL;
10642         GstPad* sinkpad = NULL;
10643         GstPad* qsrcpad= NULL;
10644         gchar *caps_str = NULL;
10645         gint64 dur_bytes = 0L;
10646         gchar* file_buffering_path = NULL;
10647         gboolean use_file_buffer = FALSE;
10648
10649         guint max_buffer_size_bytes = 0;
10650         gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
10651
10652         MMPLAYER_FENTER();
10653         return_val_if_fail (player && player->pipeline && player->pipeline->mainbin, FALSE);
10654
10655         mainbin = player->pipeline->mainbin;
10656
10657         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
10658                 (MMPLAYER_IS_HTTP_STREAMING(player)))
10659         {
10660                 debug_log ("creating http streaming buffering queue (queue2)\n");
10661
10662                 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
10663                 {
10664                         debug_error ("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
10665                 }
10666                 else
10667             {
10668                         queue2 = gst_element_factory_make ("queue2", "queue2");
10669                         if (!queue2)
10670                         {
10671                                 debug_error ("failed to create buffering queue element\n");
10672                                 goto ERROR;
10673                         }
10674
10675                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2))
10676                         {
10677                                 debug_error("failed to add buffering queue\n");
10678                                 goto ERROR;
10679                         }
10680
10681                         sinkpad = gst_element_get_static_pad(queue2, "sink");
10682                         qsrcpad = gst_element_get_static_pad(queue2, "src");
10683
10684                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
10685                         {
10686                                 debug_error("failed to link buffering queue\n");
10687                                 goto ERROR;
10688                         }
10689
10690                         // if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
10691                         {
10692                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
10693                                         debug_error("fail to get duration.\n");
10694
10695                                 debug_log("dur_bytes = %lld\n", dur_bytes);
10696
10697                                 if (dur_bytes > 0)
10698                                 {
10699                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
10700                                         file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
10701                                 }
10702                                 else
10703                                 {
10704                                         dur_bytes = 0;
10705                                 }
10706                         }
10707
10708                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
10709                         // if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
10710                         if(!g_strrstr(player->type, "video/mpegts"))
10711                         {
10712                                 max_buffer_size_bytes = (use_file_buffer)?(player->ini.http_max_size_bytes):(5*1024*1024);
10713                                 debug_log("max_buffer_size_bytes = %d\n", max_buffer_size_bytes);
10714
10715                                 __mm_player_streaming_set_queue2(player->streamer,
10716                                                                                                 queue2,
10717                                                                                                 FALSE,
10718                                                                                                 max_buffer_size_bytes,
10719                                                                                                 player->ini.http_buffering_time,
10720                                                                                                 1.0,                                                            // no meaning
10721                                                                                                 player->ini.http_buffering_limit,       // no meaning
10722                                                                                                 use_file_buffer,
10723                                                                                                 file_buffering_path,
10724                                                                                                 (guint64)dur_bytes);
10725                         }
10726
10727                         MMPLAYER_FREEIF(file_buffering_path);
10728                         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (queue2))
10729                         {
10730                                 debug_error("failed to sync queue2 state with parent\n");
10731                                 goto ERROR;
10732                         }
10733
10734                         srcpad = qsrcpad;
10735
10736                         gst_object_unref(GST_OBJECT(sinkpad));
10737
10738                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
10739                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
10740                 }
10741         }
10742
10743         /* create decodebin */
10744         decodebin = __mmplayer_create_decodebin(player);
10745
10746         if (!decodebin)
10747         {
10748                 debug_error("can not create autoplug element\n");
10749                 goto ERROR;
10750         }
10751
10752         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin))
10753         {
10754                 debug_error("failed to add decodebin\n");
10755                 goto ERROR;
10756         }
10757
10758         /* to force caps on the decodebin element and avoid reparsing stuff by
10759         * typefind. It also avoids a deadlock in the way typefind activates pads in
10760         * the state change */
10761         g_object_set (decodebin, "sink-caps", caps, NULL);
10762
10763         sinkpad = gst_element_get_static_pad(decodebin, "sink");
10764
10765         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
10766         {
10767                 debug_error("failed to link decodebin\n");
10768                 goto ERROR;
10769         }
10770
10771         gst_object_unref(GST_OBJECT(sinkpad));
10772
10773         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
10774         mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin;
10775
10776         /* set decodebin property about buffer in streaming playback. *
10777          * in case of hls, it does not need to have big buffer        *
10778          * because it is kind of adaptive streaming.                  */
10779         if ( ((!MMPLAYER_IS_HTTP_PD(player)) &&
10780             (MMPLAYER_IS_HTTP_STREAMING(player))) || MMPLAYER_IS_DASH_STREAMING (player))
10781         {
10782                 guint max_size_bytes = MAX_DECODEBIN_BUFFER_BYTES;
10783                 guint64 max_size_time = MAX_DECODEBIN_BUFFER_TIME;
10784                 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
10785
10786                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {
10787                         max_size_bytes = MAX_DECODEBIN_ADAPTIVE_BUFFER_BYTES;
10788                         max_size_time = MAX_DECODEBIN_ADAPTIVE_BUFFER_TIME;
10789                 }
10790
10791                 g_object_set (G_OBJECT(decodebin), "use-buffering", TRUE,
10792                                                                                         "high-percent", (gint)player->ini.http_buffering_limit,
10793                                                                                         "low-percent", 1,   // 1%
10794                                                                                         "max-size-bytes", max_size_bytes,
10795                                                                                         "max-size-time", (guint64)(max_size_time * GST_SECOND),
10796                                                                                         "max-size-buffers", 0, NULL);  // disable or automatic
10797         }
10798
10799         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin))
10800         {
10801                 debug_error("failed to sync decodebin state with parent\n");
10802                 goto ERROR;
10803         }
10804
10805         MMPLAYER_FLEAVE();
10806
10807         return TRUE;
10808
10809 ERROR:
10810
10811         MMPLAYER_FREEIF( caps_str );
10812
10813         if (sinkpad)
10814                 gst_object_unref(GST_OBJECT(sinkpad));
10815
10816         if (queue2)
10817         {
10818                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
10819                  * You need to explicitly set elements to the NULL state before
10820                  * dropping the final reference, to allow them to clean up.
10821                  */
10822                 gst_element_set_state(queue2, GST_STATE_NULL);
10823
10824                 /* And, it still has a parent "player".
10825                  * You need to let the parent manage the object instead of unreffing the object directly.
10826                  */
10827                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
10828                 gst_object_unref (queue2);
10829                 queue2 = NULL;
10830         }
10831
10832         if (decodebin)
10833         {
10834                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
10835                  * You need to explicitly set elements to the NULL state before
10836                  * dropping the final reference, to allow them to clean up.
10837                  */
10838                 gst_element_set_state(decodebin, GST_STATE_NULL);
10839
10840                 /* And, it still has a parent "player".
10841                  * You need to let the parent manage the object instead of unreffing the object directly.
10842                  */
10843
10844                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
10845                 gst_object_unref (decodebin);
10846                 decodebin = NULL;
10847         }
10848
10849         return FALSE;
10850 }
10851
10852 /* it will return first created element */
10853 static gboolean
10854 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
10855 {
10856         MMPlayerGstElement* mainbin = NULL;
10857         const char* mime = NULL;
10858         const GList* item = NULL;
10859         const gchar* klass = NULL;
10860         GstCaps* res = NULL;
10861         gboolean skip = FALSE;
10862         GstPad* queue_pad = NULL;
10863         GstElement* queue = NULL;
10864         GstElement *element = NULL;
10865
10866         MMPLAYER_FENTER();
10867
10868         return_val_if_fail( player && player->pipeline && player->pipeline->mainbin, FALSE );
10869
10870         mainbin = player->pipeline->mainbin;
10871
10872         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
10873
10874         /* return if we got raw output */
10875         if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
10876                 || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup"))
10877         {
10878
10879                 element = (GstElement*)gst_pad_get_parent(pad);
10880 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
10881  * No queue will be added. I think it can caused breaking sound when playing raw audio
10882  * frames but there's no different. Decodebin also doesn't add with those wav fils.
10883  * Anyway, currentely raw-queue seems not necessary.
10884  */
10885 #if 1
10886                 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
10887                  * has linked. if so, we need to add queue for quality of output. note that
10888                  * decodebin also has same problem.
10889                  */
10890                 klass = gst_element_factory_get_metadata (gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
10891
10892                 /* add queue if needed */
10893                 if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
10894                         || g_strrstr(klass, "Parse")) &&  !g_str_has_prefix(mime, "text"))
10895                 {
10896                         debug_log("adding raw queue\n");
10897
10898                         queue = gst_element_factory_make("queue", NULL);
10899                         if ( ! queue )
10900                         {
10901                                 debug_warning("failed to create queue\n");
10902                                 goto ERROR;
10903                         }
10904
10905                         /* warmup */
10906                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
10907                         {
10908                                 debug_warning("failed to set state READY to queue\n");
10909                                 goto ERROR;
10910                         }
10911
10912                         /* add to pipeline */
10913                         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
10914                         {
10915                                 debug_warning("failed to add queue\n");
10916                                 goto ERROR;
10917                         }
10918
10919                         /* link queue */
10920                         queue_pad = gst_element_get_static_pad(queue, "sink");
10921
10922                         if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
10923                         {
10924                                 debug_warning("failed to link queue\n");
10925                                 goto ERROR;
10926                         }
10927                         gst_object_unref ( GST_OBJECT(queue_pad) );
10928                         queue_pad = NULL;
10929
10930                         /* running */
10931                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
10932                         {
10933                                 debug_warning("failed to set state PAUSED to queue\n");
10934                                 goto ERROR;
10935                         }
10936
10937                         /* replace given pad to queue:src */
10938                         pad = gst_element_get_static_pad(queue, "src");
10939                         if ( ! pad )
10940                         {
10941                                 debug_warning("failed to get pad from queue\n");
10942                                 goto ERROR;
10943                         }
10944                 }
10945 #endif
10946                 /* check if player can do start continually */
10947                 MMPLAYER_CHECK_CMD_IF_EXIT(player);
10948
10949                 if(__mmplayer_link_sink(player,pad))
10950                         __mmplayer_gst_decode_callback(element, pad, player);
10951
10952                 gst_object_unref( GST_OBJECT(element));
10953                 element = NULL;
10954
10955                 return TRUE;
10956         }
10957
10958         item = player->factories;
10959         for(; item != NULL ; item = item->next)
10960         {
10961                 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
10962                 const GList *pads;
10963                 gint idx = 0;
10964
10965                 skip = FALSE;
10966
10967                 /* filtering exclude keyword */
10968                 for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
10969                 {
10970                         if ( g_strrstr(GST_OBJECT_NAME (factory),
10971                                         player->ini.exclude_element_keyword[idx] ) )
10972                         {
10973                                 debug_warning("skipping [%s] by exculde keyword [%s]\n",
10974                                         GST_OBJECT_NAME (factory),
10975                                         player->ini.exclude_element_keyword[idx] );
10976
10977                                 skip = TRUE;
10978                                 break;
10979                         }
10980                 }
10981
10982                 if ( MMPLAYER_IS_RTSP_STREAMING(player) && g_strrstr(GST_OBJECT_NAME (factory), "omx_mpeg4dec"))
10983                 {
10984                         // omx decoder can not support mpeg4video data partitioned
10985                         // rtsp streaming didn't know mpeg4video data partitioned format
10986                         // so, if rtsp playback, player will skip omx_mpeg4dec.
10987                         debug_warning("skipping [%s] when rtsp streaming \n",
10988                                         GST_OBJECT_NAME (factory));
10989
10990                         skip = TRUE;
10991                 }
10992
10993                 if ( skip ) continue;
10994
10995                 /* check factory class for filtering */
10996                 klass = gst_element_factory_get_metadata (GST_ELEMENT_FACTORY(factory), GST_ELEMENT_METADATA_KLASS);
10997
10998                 /*parsers are not required in case of external feeder*/
10999                 if (g_strrstr(klass, "Codec/Parser") && MMPLAYER_IS_ES_BUFF_SRC(player))
11000                         continue;
11001
11002                 /* NOTE : msl don't need to use image plugins.
11003                  * So, those plugins should be skipped for error handling.
11004                  */
11005                 if ( g_strrstr(klass, "Codec/Decoder/Image") )
11006                 {
11007                         debug_log("skipping [%s] by not required\n", GST_OBJECT_NAME (factory));
11008                         continue;
11009                 }
11010
11011                 /* check pad compatability */
11012                 for(pads = gst_element_factory_get_static_pad_templates(factory);
11013                                         pads != NULL; pads=pads->next)
11014                 {
11015                         GstStaticPadTemplate *temp1 = pads->data;
11016                         GstCaps* static_caps = NULL;
11017
11018                         if( temp1->direction != GST_PAD_SINK
11019                                 || temp1->presence != GST_PAD_ALWAYS)
11020                                 continue;
11021
11022                         if ( GST_IS_CAPS( &temp1->static_caps.caps) )
11023                         {
11024                                 /* using existing caps */
11025                                 static_caps = gst_caps_ref(temp1->static_caps.caps );
11026                         }
11027                         else
11028                         {
11029                                 /* create one */
11030                                 static_caps = gst_caps_from_string ( temp1->static_caps.string );
11031                         }
11032
11033                         res = gst_caps_intersect((GstCaps*)caps, static_caps);
11034                         gst_caps_unref( static_caps );
11035                         static_caps = NULL;
11036
11037                         if( res && !gst_caps_is_empty(res) )
11038                         {
11039                                 GstElement *new_element;
11040                                 GList *elements = player->parsers;
11041                                 char *name_template = g_strdup(temp1->name_template);
11042                                 gchar *name_to_plug = GST_OBJECT_NAME(factory);
11043                                 gst_caps_unref(res);
11044
11045                                 /* check ALP Codec can be used or not */
11046                                 if ((g_strrstr(klass, "Codec/Decoder/Audio")))
11047                                 {
11048                                         /* consider mp3 audio only */
11049                                         if ( !MMPLAYER_IS_STREAMING(player) && __mmplayer_is_only_mp3_type(player->type) )
11050                                         {
11051                                                 /* try to use ALP decoder first instead of selected decoder */
11052                                                 GstElement *element = NULL;
11053                                                 GstElementFactory * element_facory;
11054                                                 gchar *path = NULL;
11055                                                 guint64 data_size = 0;
11056                                                 #define MIN_THRESHOLD_SIZE  320 * 1024 // 320K
11057                                                 struct stat sb;
11058
11059                                                 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
11060
11061                                                 if (stat(path, &sb) == 0)
11062                                                 {
11063                                                         data_size = (guint64)sb.st_size;
11064                                                 }
11065                                                 debug_log("file size : %u", data_size);
11066
11067                                                 if (data_size > MIN_THRESHOLD_SIZE)
11068                                                 {
11069                                                         debug_log("checking if ALP can be used or not");
11070                                                         element = gst_element_factory_make("omx_mp3dec", "omx mp3 decoder");
11071                                                         if ( element )
11072                                                         {
11073                                                                 /* check availability because multi-instance is not supported */
11074                                                                 GstStateChangeReturn ret = gst_element_set_state(element, GST_STATE_READY);
11075
11076                                                                 if (ret != GST_STATE_CHANGE_SUCCESS) // use just selected decoder
11077                                                                 {
11078                                                                         gst_object_unref (element);
11079                                                                 }
11080                                                                 else if (ret == GST_STATE_CHANGE_SUCCESS) // replace facotry to use omx
11081                                                                 {
11082                                                                         /* clean  */
11083                                                                         gst_element_set_state(element, GST_STATE_NULL);
11084                                                                         gst_object_unref (element);
11085
11086                                                                         element_facory = gst_element_factory_find("omx_mp3dec");
11087                                                                         /* replace, otherwise use selected thing instead */
11088                                                                         if (element_facory)
11089                                                                         {
11090                                                                                 factory = element_facory;
11091                                                                                 name_to_plug = GST_OBJECT_NAME(factory);
11092                                                                         }
11093
11094                                                                         /* make parser alp mode */
11095                                                                         #ifdef _MM_PLAYER_ALP_PARSER
11096                                                                         g_list_foreach (player->parsers, check_name, player);
11097                                                                         #endif
11098                                                                 }
11099                                                         }
11100                                                 }
11101                                         }
11102                                 }
11103                                 else if ((g_strrstr(klass, "Codec/Decoder/Video")))
11104                                 {
11105                                         if ( g_strrstr(GST_OBJECT_NAME(factory), "omx_") )
11106                                         {
11107                                                 char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
11108                                                 if (env != NULL)
11109                                                 {
11110                                                         if (strncasecmp(env, "yes", 3) == 0)
11111                                                         {
11112                                                                 debug_log("skipping [%s] by disabled\n", name_to_plug);
11113                                                                 MMPLAYER_FREEIF(name_template);
11114                                                                 continue;
11115                                                         }
11116                                                 }
11117                                         }
11118                                 }
11119
11120                                 debug_log("found %s to plug\n", name_to_plug);
11121
11122                                 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
11123                                 if ( ! new_element )
11124                                 {
11125                                         debug_error("failed to create element [%s]. continue with next.\n",
11126                                                 GST_OBJECT_NAME (factory));
11127
11128                                         MMPLAYER_FREEIF(name_template);
11129
11130                                         continue;
11131                                 }
11132
11133                                 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
11134                                  * because parser can accept its own output as input.
11135                                  */
11136                                 if (g_strrstr(klass, "Parser"))
11137                                 {
11138                                         gchar *selected = NULL;
11139
11140                                         for ( ; elements; elements = g_list_next(elements))
11141                                         {
11142                                                 gchar *element_name = elements->data;
11143
11144                                                 if (g_strrstr(element_name, name_to_plug))
11145                                                 {
11146                                                         debug_log("but, %s already linked, so skipping it\n", name_to_plug);
11147                                                         skip = TRUE;
11148                                                 }
11149                                         }
11150
11151                                         if (skip)
11152                                         {
11153                                                 MMPLAYER_FREEIF(name_template);
11154                                                 continue;
11155                                         }
11156
11157                                         selected = g_strdup(name_to_plug);
11158                                         player->parsers = g_list_append(player->parsers, selected);
11159                                 }
11160
11161                                 /* store specific handles for futher control */
11162                                 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
11163                                 {
11164                                         /* FIXIT : first value will be overwritten if there's more
11165                                          * than 1 demuxer/parser
11166                                          */
11167                                         debug_log("plugged element is demuxer. take it\n");
11168                                         mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
11169                                         mainbin[MMPLAYER_M_DEMUX].gst = new_element;
11170
11171                                         /*Added for multi audio support */
11172                                         if(g_strrstr(klass, "Demux"))
11173                                         {
11174                                                 mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
11175                                                 mainbin[MMPLAYER_M_DEMUX_EX].gst = new_element;
11176
11177                                                 /* NOTE : workaround for bug in mpegtsdemux since doesn't emit
11178                                                 no-more-pad signal. this may cause wrong content attributes at PAUSED state
11179                                                 this code should be removed after mpegtsdemux is fixed */
11180                                                 if ( g_strrstr(GST_OBJECT_NAME(factory), "mpegtsdemux") )
11181                                                 {
11182                                                         debug_warning("force no-more-pad to TRUE since mpegtsdemux os not giving no-more-pad signal. content attributes may wrong");
11183                                                         player->no_more_pad = TRUE;
11184                                                 }
11185                                         }
11186                                         if (g_strrstr(name_to_plug, "asfdemux")) // to support trust-zone only
11187                                         {
11188                                                 g_object_set(mainbin[MMPLAYER_M_DEMUX_EX].gst, "file-location", player->profile.uri,NULL);
11189                                         }
11190                                 }
11191                                 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
11192                                 {
11193                                         if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
11194                                         {
11195                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
11196                                                 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
11197                                                 mainbin[MMPLAYER_M_DEC1].gst = new_element;
11198                                         }
11199                                         else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
11200                                         {
11201                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
11202                                                 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
11203                                                 mainbin[MMPLAYER_M_DEC2].gst = new_element;
11204                                         }
11205                                         /* NOTE : IF one codec is found, add it to supported_codec and remove from
11206                                          * missing plugin. Both of them are used to check what's supported codec
11207                                          * before returning result of play start. And, missing plugin should be
11208                                          * updated here for multi track files.
11209                                          */
11210                                         if(g_str_has_prefix(mime, "video"))
11211                                         {
11212                                                 GstPad *src_pad = NULL;
11213                                                 GstPadTemplate *pad_templ = NULL;
11214                                                 GstCaps *caps = NULL;
11215                                                 gchar *caps_str = NULL;
11216
11217                                                 debug_log("found VIDEO decoder\n");
11218                                                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
11219                                                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
11220
11221                                                 src_pad = gst_element_get_static_pad (new_element, "src");
11222                                                 pad_templ = gst_pad_get_pad_template (src_pad);
11223                                                 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
11224
11225                                                 caps_str = gst_caps_to_string(caps);
11226
11227                                                 /* clean */
11228                                                 MMPLAYER_FREEIF( caps_str );
11229                                                 gst_object_unref (src_pad);
11230                                         }
11231                                         else if (g_str_has_prefix(mime, "audio"))
11232                                         {
11233                                                 debug_log("found AUDIO decoder\n");
11234                                                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
11235                                                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
11236                                         }
11237                                 }
11238
11239                                 if ( ! __mmplayer_close_link(player, pad, new_element,
11240                                                         name_template,gst_element_factory_get_static_pad_templates(factory)) )
11241                                 {
11242                                         MMPLAYER_FREEIF(name_template);
11243                                         if (player->keep_detecting_vcodec)
11244                                         continue;
11245
11246                                         /* Link is failed even though a supportable codec is found. */
11247                                         __mmplayer_check_not_supported_codec(player, klass, mime);
11248
11249                                         debug_error("failed to call _close_link\n");
11250                                         return FALSE;
11251                                 }
11252
11253                                 MMPLAYER_FREEIF(name_template);
11254                                 return TRUE;
11255                         }
11256
11257                         gst_caps_unref(res);
11258                         break;
11259                 }
11260         }
11261
11262         /* There is no available codec. */
11263         __mmplayer_check_not_supported_codec(player, klass, mime);
11264
11265         MMPLAYER_FLEAVE();
11266         return FALSE;
11267
11268 ERROR:
11269         /* release */
11270         if ( queue )
11271                 gst_object_unref( queue );
11272
11273         if ( queue_pad )
11274                 gst_object_unref( queue_pad );
11275
11276         if ( element )
11277                 gst_object_unref ( element );
11278
11279         return FALSE;
11280 }
11281
11282
11283 static int
11284 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
11285 {
11286         MMPLAYER_FENTER();
11287
11288         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
11289         return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
11290
11291         debug_log("class : %s, mime : %s \n", factory_class, mime );
11292
11293         /* add missing plugin */
11294         /* NOTE : msl should check missing plugin for image mime type.
11295          * Some motion jpeg clips can have playable audio track.
11296          * So, msl have to play audio after displaying popup written video format not supported.
11297          */
11298         if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
11299         {
11300                 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
11301                 {
11302                         debug_log("not found demuxer\n");
11303                         player->not_found_demuxer = TRUE;
11304                         player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
11305
11306                         goto DONE;
11307                 }
11308         }
11309
11310         if( !g_strrstr(factory_class, "Demuxer"))
11311         {
11312                 if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
11313                 {
11314                         debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
11315                                 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
11316
11317                         /* check that clip have multi tracks or not */
11318                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
11319                         {
11320                                 debug_log("video plugin is already linked\n");
11321                         }
11322                         else
11323                         {
11324                                 debug_warning("add VIDEO to missing plugin\n");
11325                                 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
11326                         }
11327                 }
11328                 else if ( g_str_has_prefix(mime, "audio") )
11329                 {
11330                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
11331                         {
11332                                 debug_log("audio plugin is already linked\n");
11333                         }
11334                         else
11335                         {
11336                                 debug_warning("add AUDIO to missing plugin\n");
11337                                 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
11338                         }
11339                 }
11340         }
11341
11342 DONE:
11343         MMPLAYER_FLEAVE();
11344
11345         return MM_ERROR_NONE;
11346 }
11347
11348
11349 static void
11350 __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
11351 {
11352     mm_player_t* player = (mm_player_t*)data;
11353
11354         MMPLAYER_FENTER();
11355
11356         return_if_fail( player );
11357
11358         /* remove fakesink. */
11359         if ( !__mmplayer_gst_remove_fakesink( player,
11360                                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
11361         {
11362                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
11363                  * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
11364                  * source element are not same. To overcome this situation, this function will called
11365                  * several places and several times. Therefore, this is not an error case.
11366                  */
11367                 return;
11368         }
11369
11370         debug_log("pipeline has completely constructed\n");
11371
11372         if (( player->ini.async_start ) &&
11373                 ( player->msg_posted == FALSE ) &&
11374                 ( player->cmd >= MMPLAYER_COMMAND_START ))
11375         {
11376                 __mmplayer_handle_missed_plugin( player );
11377         }
11378
11379         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complete" );
11380 }
11381
11382 static gboolean
11383 __mmplayer_verify_next_play_path(mm_player_t *player)
11384 {
11385         MMHandleType attrs = 0;
11386         MMPlayerParseProfile profile;
11387         gint uri_idx = 0, check_cnt = 0;
11388         char *uri = NULL;
11389         gint mode = MM_PLAYER_PD_MODE_NONE;
11390         gint count = 0;
11391         guint num_of_list = 0;
11392
11393         MMPLAYER_FENTER();
11394
11395         debug_log("checking for gapless play");
11396
11397         if (player->pipeline->textbin)
11398         {
11399                 debug_error("subtitle path is enabled. gapless play is not supported.\n");
11400                 goto ERROR;
11401         }
11402
11403         attrs = MMPLAYER_GET_ATTRS(player);
11404         if ( !attrs )
11405         {
11406                 debug_error("fail to get attributes.\n");
11407                 goto ERROR;
11408         }
11409
11410         /* seamless playback is supported in case of audio only */
11411         mm_attrs_get_int_by_name(attrs, "content_video_found", &mode);
11412         if (mode)
11413         {
11414                 debug_log("video found");
11415                 goto ERROR;
11416         }
11417
11418         if (mm_attrs_get_int_by_name (attrs, "pd_mode", &mode) == MM_ERROR_NONE)
11419         {
11420                 if (mode == TRUE)
11421                 {
11422                         debug_warning("pd mode\n");
11423                         goto ERROR;
11424                 }
11425         }
11426
11427         if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
11428         {
11429                 debug_error("can not get play count\n");
11430         }
11431
11432         num_of_list = g_list_length(player->uri_info.uri_list);
11433
11434         debug_log("repeat count = %d, num_of_list = %d\n", count, num_of_list);
11435
11436         if ( num_of_list == 0 )
11437         {
11438                 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE)
11439                 {
11440                         debug_error("can not get profile_uri\n");
11441                         goto ERROR;
11442                 }
11443
11444                 if (!uri)
11445                 {
11446                         debug_error("uri list is empty.\n");
11447                         goto ERROR;
11448                 }
11449
11450                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
11451                 debug_log("add original path : %s ", uri);
11452
11453                 num_of_list = 1;
11454                 uri= NULL;
11455         }
11456
11457         uri_idx = player->uri_info.uri_idx;
11458
11459         while(TRUE)
11460         {
11461                 check_cnt++;
11462
11463                 if (check_cnt > num_of_list)
11464                 {
11465                         debug_error("there is no valid uri.");
11466                         goto ERROR;
11467                 }
11468
11469                 debug_log("uri idx : %d / %d\n", uri_idx, num_of_list);
11470
11471                 if ( uri_idx < num_of_list-1 )
11472                 {
11473                         uri_idx++;
11474                 }
11475                 else
11476                 {
11477                         if ((count <= 1) && (count != -1))
11478                         {
11479                                 debug_log("no repeat.");
11480                                 goto ERROR;
11481                         }
11482                         else if ( count > 1 )   /* decrease play count */
11483                         {
11484                                 /* we successeded to rewind. update play count and then wait for next EOS */
11485                                 count--;
11486
11487                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
11488
11489                                 /* commit attribute */
11490                                 if ( mmf_attrs_commit ( attrs ) )
11491                                 {
11492                                         debug_error("failed to commit attribute\n");
11493                                 }
11494                         }
11495
11496                         /* count < 0 : repeat continually */
11497                         uri_idx = 0;
11498                 }
11499
11500                 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
11501                 debug_log("uri idx : %d, uri = %s\n", uri_idx, uri);
11502
11503                 if (uri == NULL)
11504                 {
11505                         debug_warning("next uri does not exist\n");
11506                         continue;
11507                 }
11508
11509                 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE)
11510                 {
11511                         debug_error("failed to parse profile\n");
11512                         continue;
11513                 }
11514
11515                 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
11516                         (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP))
11517                 {
11518                         debug_warning("uri type is not supported (%d).", profile.uri_type);
11519                         continue;
11520                 }
11521
11522                 break;
11523         }
11524
11525         player->uri_info.uri_idx = uri_idx;
11526         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
11527
11528
11529         if (mmf_attrs_commit(player->attrs))
11530         {
11531                 debug_error("failed to commit.\n");
11532                 goto ERROR;
11533         }
11534
11535         debug_log("next uri %s (%d)\n", uri, uri_idx);
11536
11537         return TRUE;
11538
11539 ERROR:
11540
11541         debug_error("unable to play next path. EOS will be posted soon.\n");
11542         return FALSE;
11543 }
11544
11545 static void
11546 __mmplayer_initialize_next_play(mm_player_t *player)
11547 {
11548         int i;
11549
11550         MMPLAYER_FENTER();
11551
11552         player->smooth_streaming = FALSE;
11553         player->videodec_linked = 0;
11554         player->audiodec_linked = 0;
11555         player->videosink_linked = 0;
11556         player->audiosink_linked = 0;
11557         player->textsink_linked = 0;
11558         player->is_external_subtitle_present = FALSE;
11559         player->not_supported_codec = MISSING_PLUGIN_NONE;
11560         player->can_support_codec = FOUND_PLUGIN_NONE;
11561         player->pending_seek.is_pending = FALSE;
11562         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
11563         player->pending_seek.pos = 0;
11564         player->msg_posted = FALSE;
11565         player->has_many_types = FALSE;
11566         player->no_more_pad = FALSE;
11567         player->is_drm_file = FALSE;
11568         player->not_found_demuxer = 0;
11569         player->doing_seek = FALSE;
11570         player->max_audio_channels = 0;
11571         player->is_subtitle_force_drop = FALSE;
11572         player->play_subtitle = FALSE;
11573         player->use_textoverlay = FALSE;
11574         player->adjust_subtitle_pos = 0;
11575
11576         player->updated_bitrate_count = 0;
11577         player->total_bitrate = 0;
11578         player->updated_maximum_bitrate_count = 0;
11579         player->total_maximum_bitrate = 0;
11580
11581         _mmplayer_track_initialize(player);
11582
11583         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
11584         {
11585                 player->bitrate[i] = 0;
11586                 player->maximum_bitrate[i] = 0;
11587         }
11588
11589         if (player->v_stream_caps)
11590         {
11591                 gst_caps_unref(player->v_stream_caps);
11592                 player->v_stream_caps = NULL;
11593         }
11594
11595         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
11596         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
11597
11598         /* clean found parsers */
11599         if (player->parsers)
11600         {
11601                 GList *parsers = player->parsers;
11602                 for ( ;parsers ; parsers = g_list_next(parsers))
11603                 {
11604                         gchar *name = parsers->data;
11605                         MMPLAYER_FREEIF(name);
11606                 }
11607                 g_list_free(player->parsers);
11608                 player->parsers = NULL;
11609         }
11610
11611         /* clean found audio decoders */
11612         if (player->audio_decoders)
11613         {
11614                 GList *a_dec = player->audio_decoders;
11615                 for ( ;a_dec ; a_dec = g_list_next(a_dec))
11616                 {
11617                         gchar *name = a_dec->data;
11618                         MMPLAYER_FREEIF(name);
11619                 }
11620                 g_list_free(player->audio_decoders);
11621                 player->audio_decoders = NULL;
11622         }
11623
11624         MMPLAYER_FLEAVE();
11625 }
11626
11627 static void
11628 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
11629 {
11630         MMPlayerGstElement *mainbin = NULL;
11631         MMMessageParamType msg_param = {0,};
11632         GstElement *element = NULL;
11633         MMHandleType attrs = 0;
11634         char *uri = NULL;
11635         enum MainElementID elemId = MMPLAYER_M_NUM;
11636
11637         MMPLAYER_FENTER();
11638
11639         if ((player == NULL) ||
11640                 (player->pipeline == NULL) ||
11641                 (player->pipeline->mainbin == NULL))
11642         {
11643                 debug_error("player is null.\n");
11644                 goto ERROR;
11645         }
11646
11647         mainbin = player->pipeline->mainbin;
11648         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
11649
11650         attrs = MMPLAYER_GET_ATTRS(player);
11651         if ( !attrs )
11652         {
11653                 debug_error("fail to get attributes.\n");
11654                 goto ERROR;
11655         }
11656
11657         /* Initialize Player values */
11658         __mmplayer_initialize_next_play(player);
11659
11660         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
11661
11662         if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE)
11663         {
11664                 debug_error("failed to parse profile\n");
11665                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
11666                 goto ERROR;
11667         }
11668
11669         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
11670                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player)))
11671         {
11672                 debug_error("it's dash or hls. not support.");
11673                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
11674                 goto ERROR;
11675         }
11676
11677         /* setup source */
11678         switch ( player->profile.uri_type )
11679         {
11680                 /* file source */
11681                 case MM_PLAYER_URI_TYPE_FILE:
11682                 {
11683                         debug_log("using filesrc for 'file://' handler.\n");
11684
11685                         element = gst_element_factory_make("filesrc", "source");
11686
11687                         if ( !element )
11688                         {
11689                                 debug_error("failed to create filesrc\n");
11690                                 break;
11691                         }
11692
11693                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
11694                         break;
11695                 }
11696                 case MM_PLAYER_URI_TYPE_URL_HTTP:
11697                 {
11698                         gchar *user_agent, *proxy, *cookies, **cookie_list;
11699                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
11700                         user_agent = proxy = cookies = NULL;
11701                         cookie_list = NULL;
11702
11703                         element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
11704                         if ( !element )
11705                         {
11706                                 debug_error("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
11707                                 break;
11708                         }
11709                         debug_log("using http streamming source [%s].\n", player->ini.httpsrc_element);
11710
11711                         /* get attribute */
11712                         mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
11713                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
11714                         mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
11715                         mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
11716
11717                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
11718                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
11719                         {
11720                                 debug_log("get timeout from ini\n");
11721                                 http_timeout = player->ini.http_timeout;
11722                         }
11723
11724                         /* get attribute */
11725                         secure_debug_log("location : %s\n", player->profile.uri);
11726                         secure_debug_log("cookies : %s\n", cookies);
11727                         secure_debug_log("proxy : %s\n", proxy);
11728                         secure_debug_log("user_agent :  %s\n", user_agent);
11729                         debug_log("timeout : %d\n", http_timeout);
11730
11731                         /* setting property to streaming source */
11732                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
11733                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
11734                         g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
11735
11736                         /* check if prosy is vailid or not */
11737                         if ( util_check_valid_url ( proxy ) )
11738                                 g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
11739                         /* parsing cookies */
11740                         if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
11741                                 g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
11742                         if ( user_agent )
11743                                 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
11744                         break;
11745                 }
11746                 default:
11747                         debug_error("not support uri type %d\n", player->profile.uri_type);
11748                         break;
11749         }
11750
11751         if ( !element )
11752         {
11753                 debug_error("no source element was created.\n");
11754                 goto ERROR;
11755         }
11756
11757         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
11758         {
11759                 debug_error("failed to add source element to pipeline\n");
11760                 gst_object_unref(GST_OBJECT(element));
11761                 element = NULL;
11762                 goto ERROR;
11763         }
11764
11765         /* take source element */
11766         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
11767         mainbin[MMPLAYER_M_SRC].gst = element;
11768
11769         element = NULL;
11770
11771         if (MMPLAYER_IS_HTTP_STREAMING(player))
11772         {
11773                 if (player->streamer == NULL)
11774                 {
11775                         player->streamer = __mm_player_streaming_create();
11776                         __mm_player_streaming_initialize(player->streamer);
11777                 }
11778
11779                 elemId = MMPLAYER_M_TYPEFIND;
11780                 element = gst_element_factory_make("typefind", "typefinder");
11781                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
11782                         G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
11783         }
11784         else
11785         {
11786                 elemId = MMPLAYER_M_AUTOPLUG;
11787                 element = __mmplayer_create_decodebin(player);
11788         }
11789
11790         /* check autoplug element is OK */
11791         if ( ! element )
11792         {
11793                 debug_error("can not create element (%d)\n", elemId);
11794                 goto ERROR;
11795         }
11796
11797         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
11798         {
11799                 debug_error("failed to add sinkbin to pipeline\n");
11800                 gst_object_unref(GST_OBJECT(element));
11801                 element = NULL;
11802                 goto ERROR;
11803         }
11804
11805         mainbin[elemId].id = elemId;
11806         mainbin[elemId].gst = element;
11807
11808         if ( gst_element_link (mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE )
11809         {
11810                 debug_error("Failed to link src - autoplug (or typefind)\n");
11811                 goto ERROR;
11812         }
11813
11814         if (gst_element_set_state (mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE)
11815         {
11816                 debug_error("Failed to change state of src element\n");
11817                 goto ERROR;
11818         }
11819
11820         if (!MMPLAYER_IS_HTTP_STREAMING(player))
11821         {
11822                 if (gst_element_set_state (mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE)
11823                 {
11824                         debug_error("Failed to change state of decodebin\n");
11825                         goto ERROR;
11826                 }
11827         }
11828         else
11829         {
11830                 if (gst_element_set_state (mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE)
11831                 {
11832                         debug_error("Failed to change state of src element\n");
11833                         goto ERROR;
11834                 }
11835         }
11836
11837         player->gapless.stream_changed = TRUE;
11838         player->gapless.running = TRUE;
11839         MMPLAYER_FLEAVE();
11840         return;
11841
11842 ERROR:
11843         MMPLAYER_PLAYBACK_UNLOCK(player);
11844
11845         if (!player->msg_posted)
11846         {
11847                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
11848                 player->msg_posted = TRUE;
11849         }
11850         return;
11851 }
11852
11853 static gboolean
11854 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
11855 {
11856         mm_player_selector_t *selector = &player->selector[type];
11857         MMPlayerGstElement *sinkbin = NULL;
11858         enum MainElementID selectorId = MMPLAYER_M_NUM;
11859         enum MainElementID sinkId = MMPLAYER_M_NUM;
11860         GstPad *srcpad = NULL;
11861         GstPad *sinkpad = NULL;
11862
11863         MMPLAYER_FENTER();
11864         return_val_if_fail (player, FALSE);
11865
11866         debug_log("type %d", type);
11867
11868         switch (type)
11869         {
11870                 case MM_PLAYER_TRACK_TYPE_AUDIO:
11871                         selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
11872                         sinkId = MMPLAYER_A_BIN;
11873                         sinkbin = player->pipeline->audiobin;
11874                 break;
11875                 case MM_PLAYER_TRACK_TYPE_TEXT:
11876                         selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
11877                         sinkId = MMPLAYER_T_BIN;
11878                         sinkbin = player->pipeline->textbin;
11879                 break;
11880                 default:
11881                         debug_error("requested type is not supportable");
11882                         return FALSE;
11883                 break;
11884         }
11885
11886         if (player->pipeline->mainbin[selectorId].gst)
11887         {
11888                 gint n;
11889
11890                 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
11891
11892                 if (selector->event_probe_id != 0)
11893                         gst_pad_remove_probe (srcpad, selector->event_probe_id);
11894                 selector->event_probe_id = 0;
11895
11896                 if ((sinkbin) && (sinkbin[sinkId].gst))
11897                 {
11898                         sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
11899
11900                         if (srcpad && sinkpad)
11901                         {
11902                                 /* after getting drained signal there is no data flows, so no need to do pad_block */
11903                                 debug_log("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
11904                                 gst_pad_unlink (srcpad, sinkpad);
11905                         }
11906
11907                         gst_object_unref (sinkpad);
11908                         sinkpad = NULL;
11909                 }
11910                 gst_object_unref (srcpad);
11911                 srcpad = NULL;
11912
11913                 debug_log("selector release");
11914
11915                 /* release and unref requests pad from the selector */
11916                 for (n = 0; n < selector->channels->len; n++)
11917                 {
11918                         GstPad *sinkpad = g_ptr_array_index (selector->channels, n);
11919                         gst_element_release_request_pad ((player->pipeline->mainbin[selectorId].gst), sinkpad);
11920                 }
11921                 g_ptr_array_set_size (selector->channels, 0);
11922
11923                 gst_element_set_state (player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
11924                 gst_bin_remove (GST_BIN_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
11925
11926                 player->pipeline->mainbin[selectorId].gst = NULL;
11927                 selector = NULL;
11928         }
11929
11930         return TRUE;
11931 }
11932
11933 static void
11934 __mmplayer_deactivate_old_path(mm_player_t *player)
11935 {
11936         MMPLAYER_FENTER();
11937         return_if_fail ( player );
11938
11939         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
11940                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT)))
11941         {
11942                 debug_error("deactivate selector error");
11943                 goto ERROR;
11944         }
11945
11946         _mmplayer_track_destroy(player);
11947         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG );
11948
11949         if (player->streamer)
11950         {
11951                 __mm_player_streaming_deinitialize (player->streamer);
11952                 __mm_player_streaming_destroy(player->streamer);
11953                 player->streamer = NULL;
11954         }
11955
11956         MMPLAYER_PLAYBACK_LOCK(player);
11957         g_cond_signal( &player->next_play_thread_cond );
11958
11959         MMPLAYER_FLEAVE();
11960         return;
11961
11962 ERROR:
11963
11964         if (!player->msg_posted)
11965         {
11966                 MMMessageParamType msg = {0,};
11967
11968                 /*post error*/
11969                 msg.code = MM_ERROR_PLAYER_INTERNAL;
11970                 debug_error("next_uri_play> deactivate error");
11971
11972                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
11973                 player->msg_posted = TRUE;
11974         }
11975         return;
11976 }
11977
11978 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
11979 {
11980         int result = MM_ERROR_NONE;
11981         mm_player_t* player = (mm_player_t*) hplayer;
11982         MMPLAYER_FENTER();
11983
11984         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
11985
11986         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
11987         if (mmf_attrs_commit(player->attrs))
11988         {
11989                 debug_error("failed to commit the original uri.\n");
11990                 result = MM_ERROR_PLAYER_INTERNAL;
11991         }
11992         else
11993         {
11994                 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
11995                 {
11996                         debug_error("failed to add the original uri in the uri list.\n");
11997                 }
11998         }
11999
12000         MMPLAYER_FLEAVE();
12001         return result;
12002 }
12003
12004 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
12005 {
12006         mm_player_t* player = (mm_player_t*) hplayer;
12007         guint num_of_list = 0;
12008
12009         MMPLAYER_FENTER();
12010
12011         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12012         return_val_if_fail (uri, MM_ERROR_INVALID_ARGUMENT);
12013
12014         if (player->pipeline && player->pipeline->textbin)
12015         {
12016                 debug_error("subtitle path is enabled.\n");
12017                 return MM_ERROR_PLAYER_INVALID_STATE;
12018         }
12019
12020         num_of_list = g_list_length(player->uri_info.uri_list);
12021
12022         if (is_first_path == TRUE)
12023         {
12024                 if (num_of_list == 0)
12025                 {
12026                         player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12027                         debug_log("add original path : %s", uri);
12028                 }
12029                 else
12030                 {
12031                         player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
12032                         player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
12033
12034                         debug_log("change original path : %s", uri);
12035                 }
12036         }
12037         else
12038         {
12039                 if (num_of_list == 0)
12040                 {
12041                         MMHandleType attrs = 0;
12042                         char *original_uri = NULL;
12043
12044                         attrs = MMPLAYER_GET_ATTRS(player);
12045                         if ( attrs )
12046                         {
12047                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
12048
12049                                 if (!original_uri)
12050                                 {
12051                                         debug_error("there is no original uri.");
12052                                         return MM_ERROR_PLAYER_INVALID_STATE;
12053                                 }
12054
12055                                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
12056                                 player->uri_info.uri_idx = 0;
12057
12058                                 debug_log("add original path at first : %s (%d)", original_uri);
12059                         }
12060                 }
12061
12062                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12063                 debug_log("add new path : %s (total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
12064         }
12065
12066         MMPLAYER_FLEAVE();
12067         return MM_ERROR_NONE;
12068 }
12069
12070 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
12071 {
12072         mm_player_t* player = (mm_player_t*) hplayer;
12073         char *next_uri = NULL;
12074         guint num_of_list = 0;
12075
12076         MMPLAYER_FENTER();
12077         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12078
12079         num_of_list = g_list_length(player->uri_info.uri_list);
12080
12081         if (num_of_list > 0)
12082         {
12083                 gint uri_idx = player->uri_info.uri_idx;
12084
12085                 if ( uri_idx < num_of_list-1 )
12086                         uri_idx++;
12087                 else
12088                         uri_idx = 0;
12089
12090                 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12091                 debug_error("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
12092
12093                 *uri = g_strdup(next_uri);
12094         }
12095
12096         MMPLAYER_FLEAVE();
12097         return MM_ERROR_NONE;
12098 }
12099
12100 static void
12101 __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad,
12102 GstCaps *caps, gpointer data)
12103 {
12104         mm_player_t* player = (mm_player_t*)data;
12105         const gchar* klass = NULL;
12106         const gchar* mime = NULL;
12107         gchar* caps_str = NULL;
12108
12109         klass = gst_element_factory_get_metadata (gst_element_get_factory(elem), GST_ELEMENT_METADATA_KLASS);
12110         mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12111         caps_str = gst_caps_to_string(caps);
12112
12113         debug_warning("unknown type of caps : %s from %s",
12114                                         caps_str, GST_ELEMENT_NAME (elem));
12115
12116         MMPLAYER_FREEIF(caps_str);
12117
12118         /* There is no available codec. */
12119         __mmplayer_check_not_supported_codec (player, klass, mime);
12120 }
12121
12122 static gboolean
12123 __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad,
12124 GstCaps * caps,  gpointer data)
12125 {
12126         mm_player_t* player = (mm_player_t*)data;
12127         const char* mime = NULL;
12128         gboolean ret = TRUE;
12129
12130         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
12131         mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12132
12133         if (g_str_has_prefix(mime, "audio")) {
12134                 GstStructure* caps_structure = NULL;
12135                 gint samplerate = 0;
12136                 gint channels = 0;
12137                 gchar *caps_str = NULL;
12138
12139                 caps_structure = gst_caps_get_structure(caps, 0);
12140                 gst_structure_get_int (caps_structure, "rate", &samplerate);
12141                 gst_structure_get_int (caps_structure, "channels", &channels);
12142
12143                 if ( (channels > 0 && samplerate == 0)) {
12144                         debug_log("exclude audio...");
12145                         ret = FALSE;
12146                 }
12147
12148                 caps_str = gst_caps_to_string(caps);
12149                 /* set it directly because not sent by TAG */
12150                 if (g_strrstr(caps_str, "mobile-xmf")) {
12151                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
12152                 }
12153                 MMPLAYER_FREEIF (caps_str);
12154         } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
12155                 debug_log("already video linked");
12156                 ret = FALSE;
12157         } else {
12158                 debug_log("found new stream");
12159         }
12160
12161         return ret;
12162 }
12163
12164 static gint
12165 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad,
12166 GstCaps* caps, GstElementFactory* factory, gpointer data)
12167 {
12168         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
12169          We are defining our own and will be removed when it actually exposed */
12170         typedef enum {
12171                 GST_AUTOPLUG_SELECT_TRY,
12172                 GST_AUTOPLUG_SELECT_EXPOSE,
12173                 GST_AUTOPLUG_SELECT_SKIP
12174         } GstAutoplugSelectResult;
12175
12176         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
12177         mm_player_t* player = (mm_player_t*)data;
12178
12179         gchar* factory_name = NULL;
12180         gchar* caps_str = NULL;
12181         const gchar* klass = NULL;
12182         gint idx = 0;
12183
12184         factory_name = GST_OBJECT_NAME (factory);
12185         klass = gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
12186         caps_str = gst_caps_to_string(caps);
12187
12188 //      debug_log("found new element [%s] to link for caps [%s]", factory_name, caps_str);
12189         debug_log("found new element [%s] to link", factory_name);
12190
12191         /* store type string */
12192         if (player->type == NULL)
12193         {
12194                 player->type = gst_caps_to_string(caps);
12195                 __mmplayer_update_content_type_info(player);
12196         }
12197
12198         /* To support evasimagesink, omx is excluded temporarily*/
12199         int surface_type = 0;
12200         mm_attrs_get_int_by_name(player->attrs, "display_surface_client_type", &surface_type);
12201         if (surface_type == MM_DISPLAY_SURFACE_NULL)
12202                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
12203         debug_log("check display surface type attribute: %d", surface_type);
12204         if (surface_type == MM_DISPLAY_SURFACE_EVAS && strstr(factory_name, "omx"))
12205         {
12206                 debug_warning("skipping [%s] for supporting evasimagesink temporarily.\n", factory_name);
12207                 result = GST_AUTOPLUG_SELECT_SKIP;
12208                 goto DONE;
12209         }
12210
12211         /* filtering exclude keyword */
12212         for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
12213         {
12214                 if ( strstr(factory_name, player->ini.exclude_element_keyword[idx] ) )
12215                 {
12216                         debug_warning("skipping [%s] by exculde keyword [%s]\n",
12217                         factory_name, player->ini.exclude_element_keyword[idx] );
12218
12219                         // NOTE : does we need to check n_value against the number of item selected?
12220                         result = GST_AUTOPLUG_SELECT_SKIP;
12221                         goto DONE;
12222                 }
12223         }
12224
12225         /* check factory class for filtering */
12226         /* NOTE : msl don't need to use image plugins.
12227          * So, those plugins should be skipped for error handling.
12228          */
12229         if (g_strrstr(klass, "Codec/Decoder/Image"))
12230         {
12231                 debug_log("skipping [%s] by not required\n", factory_name);
12232                 result = GST_AUTOPLUG_SELECT_SKIP;
12233                 goto DONE;
12234         }
12235
12236         if ((MMPLAYER_IS_ES_BUFF_SRC(player)) &&
12237                 (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser"))))
12238         {
12239                 // TO CHECK : subtitle if needed, add subparse exception.
12240                 debug_log("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
12241                 result = GST_AUTOPLUG_SELECT_SKIP;
12242                 goto DONE;
12243         }
12244
12245         if (g_strrstr(factory_name, "mpegpsdemux"))
12246         {
12247                 debug_log("skipping PS container - not support\n");
12248                 result = GST_AUTOPLUG_SELECT_SKIP;
12249                 goto DONE;
12250         }
12251
12252         if (g_strrstr(factory_name, SMOOTH_STREAMING_DEMUX))
12253                 player->smooth_streaming = TRUE;
12254
12255         /* check ALP Codec can be used or not */
12256         if ((g_strrstr(klass, "Codec/Decoder/Audio")))
12257         {
12258                 GstStructure* str = NULL;
12259                 gint channels = 0;
12260
12261                 str = gst_caps_get_structure( caps, 0 );
12262                 if ( str )
12263                 {
12264                         gst_structure_get_int (str, "channels", &channels);
12265
12266                         debug_log ("check audio ch : %d %d\n", player->max_audio_channels, channels);
12267                         if (player->max_audio_channels < channels)
12268                         {
12269                                 player->max_audio_channels = channels;
12270                         }
12271                 }
12272
12273                 if (!player->audiodec_linked)
12274                 {
12275                         /* set stream information */
12276                         __mmplayer_set_audio_attrs (player, caps);
12277                 }
12278         }
12279         else if ((g_strrstr(klass, "Codec/Decoder/Video")))
12280         {
12281                 if (g_strrstr(factory_name, "omx_"))
12282                 {
12283                         char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
12284                         if (env != NULL)
12285                         {
12286                                 if (strncasecmp(env, "yes", 3) == 0)
12287                                 {
12288                                         debug_log ("skipping [%s] by disabled\n", factory_name);
12289                                         result = GST_AUTOPLUG_SELECT_SKIP;
12290                                         goto DONE;
12291                                 }
12292                         }
12293                 }
12294         }
12295
12296         if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
12297                 (g_strrstr(klass, "Codec/Decoder/Video")))
12298         {
12299                 gint stype = 0;
12300                 gint width = 0;
12301                 GstStructure *str = NULL;
12302                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
12303
12304                 /* don't make video because of not required */
12305                 if (stype == MM_DISPLAY_SURFACE_NULL)
12306                 {
12307                         debug_log ("no video because it's not required. -> return expose");
12308                         if (player->set_mode.media_packet_video_stream == FALSE)
12309                         {
12310                                 result = GST_AUTOPLUG_SELECT_EXPOSE;
12311                                 goto DONE;
12312                         }
12313                 }
12314
12315                 /* get w/h for omx state-tune */
12316                 str = gst_caps_get_structure (caps, 0);
12317                 gst_structure_get_int (str, "width", &width);
12318
12319                 if (width != 0) {
12320                         if (player->v_stream_caps) {
12321                                 gst_caps_unref(player->v_stream_caps);
12322                                 player->v_stream_caps = NULL;
12323                         }
12324
12325                         player->v_stream_caps = gst_caps_copy(caps);
12326                         debug_log ("take caps for video state tune");
12327                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
12328                 }
12329         }
12330
12331         if (g_strrstr(klass, "Decoder"))
12332         {
12333                 const char* mime = NULL;
12334                 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12335
12336                 if (g_str_has_prefix(mime, "video"))
12337                 {
12338                         // __mmplayer_check_video_zero_cpoy(player, factory);
12339
12340                         player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
12341                         player->can_support_codec |= FOUND_PLUGIN_VIDEO;
12342
12343                         player->videodec_linked = 1;
12344                 }
12345                 else if(g_str_has_prefix(mime, "audio"))
12346                 {
12347                         player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
12348                         player->can_support_codec |= FOUND_PLUGIN_AUDIO;
12349
12350                         player->audiodec_linked = 1;
12351                 }
12352         }
12353
12354 DONE:
12355         MMPLAYER_FREEIF(caps_str);
12356
12357         return result;
12358 }
12359
12360
12361 #if 0
12362 static GValueArray*
12363 __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad,
12364 GstCaps * caps,  gpointer data)
12365 {
12366         //mm_player_t* player = (mm_player_t*)data;
12367
12368         debug_log("decodebin is requesting factories for caps [%s] from element[%s]",
12369                 gst_caps_to_string(caps),
12370                 GST_ELEMENT_NAME(GST_PAD_PARENT(pad)));
12371
12372         return NULL;
12373 }
12374 #endif
12375
12376 static void
12377 __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad,
12378 gpointer data) // @
12379 {
12380         //mm_player_t* player = (mm_player_t*)data;
12381         GstCaps* caps = NULL;
12382
12383         debug_log("[Decodebin2] pad-removed signal\n");
12384
12385         caps = gst_pad_query_caps(new_pad, NULL);
12386         if (caps)
12387         {
12388                 gchar* caps_str = NULL;
12389                 caps_str = gst_caps_to_string(caps);
12390
12391                 debug_log("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem) );
12392
12393                 MMPLAYER_FREEIF(caps_str);
12394         }
12395 }
12396
12397 static void
12398 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
12399 {
12400         mm_player_t* player = (mm_player_t*)data;
12401
12402         MMPLAYER_FENTER();
12403         return_if_fail ( player );
12404
12405         debug_log("__mmplayer_gst_decode_drained");
12406
12407         if (player->use_deinterleave == TRUE)
12408         {
12409                 debug_log("group playing mode.");
12410                 return;
12411         }
12412
12413         if (!g_mutex_trylock(&player->cmd_lock))
12414         {
12415                 debug_warning("Fail to get cmd lock");
12416                 return;
12417         }
12418
12419         if (!__mmplayer_verify_next_play_path(player))
12420         {
12421                 debug_log("decoding is finished.");
12422                 player->gapless.running = FALSE;
12423                 player->gapless.start_time = 0;
12424                 g_mutex_unlock(&player->cmd_lock);
12425                 return;
12426         }
12427
12428         player->gapless.reconfigure = TRUE;
12429
12430         /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
12431         __mmplayer_deactivate_old_path(player);
12432
12433         g_mutex_unlock(&player->cmd_lock);
12434
12435         MMPLAYER_FLEAVE();
12436 }
12437
12438 static void
12439 __mmplayer_gst_element_added (GstElement *bin, GstElement *element, gpointer data)
12440 {
12441         mm_player_t* player = (mm_player_t*)data;
12442         const gchar* klass = NULL;
12443         gchar* factory_name = NULL;
12444
12445         klass = gst_element_factory_get_metadata (gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
12446         factory_name = GST_OBJECT_NAME (gst_element_get_factory(element));
12447
12448         debug_log("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
12449
12450         if (__mmplayer_add_dump_buffer_probe(player, element))
12451                 debug_log("add buffer probe");
12452
12453         //<-
12454         if (g_strrstr(klass, "Codec/Decoder/Audio"))
12455         {
12456                 gchar* selected = NULL;
12457                 selected = g_strdup( GST_ELEMENT_NAME(element));
12458                 player->audio_decoders = g_list_append (player->audio_decoders, selected);
12459         }
12460         //-> temp code
12461
12462         if (g_strrstr(klass, "Parser"))
12463         {
12464                 gchar* selected = NULL;
12465
12466                 selected = g_strdup (factory_name);
12467                 player->parsers = g_list_append (player->parsers, selected);
12468         }
12469
12470         if ((g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) && !(g_strrstr(klass, "Adaptive")))
12471         {
12472                 /* FIXIT : first value will be overwritten if there's more
12473                  * than 1 demuxer/parser
12474                  */
12475
12476                 //debug_log ("plugged element is demuxer. take it\n");
12477                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
12478                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
12479
12480                 /*Added for multi audio support */ // Q. del?
12481                 if (g_strrstr(klass, "Demux"))
12482                 {
12483                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
12484                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
12485                 }
12486         }
12487
12488         if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux"))
12489         {
12490                 int surface_type = 0;
12491
12492                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
12493
12494 #if 0   // this is for 0.10 plugin with downstream modification
12495                 /* playback protection if drm file */
12496                 if (player->use_video_stream || surface_type == MM_DISPLAY_SURFACE_EVAS || surface_type == MM_DISPLAY_SURFACE_X_EXT)
12497                 {
12498                         debug_log("playback can be protected if playready drm");
12499                         g_object_set (G_OBJECT(element), "playback-protection", TRUE, NULL);
12500                 }
12501 #endif
12502         }
12503
12504         // to support trust-zone only
12505         if (g_strrstr(factory_name, "asfdemux"))
12506         {
12507                 debug_log ("set file-location %s\n", player->profile.uri);
12508                 g_object_set (G_OBJECT(element), "file-location", player->profile.uri, NULL);
12509
12510                 if (player->video_hub_download_mode == TRUE)
12511                 {
12512                         g_object_set (G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
12513                 }
12514         }
12515         else if (g_strrstr(factory_name, "legacyh264parse"))    // SMOOTH_STREAMING_DEMUX
12516         {
12517                 debug_log ("[%s] output-format to legacyh264parse\n", SMOOTH_STREAMING_DEMUX);
12518                 g_object_set (G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
12519         }
12520         else if (g_strrstr(factory_name, "mpegaudioparse"))
12521         {
12522                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
12523                         (__mmplayer_is_only_mp3_type(player->type)))
12524                 {
12525                         debug_log ("[mpegaudioparse] set streaming pull mode.");
12526                         g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
12527                 }
12528         }
12529         else if (g_strrstr(factory_name, "omx"))
12530         {
12531                 if (g_strrstr(klass, "Codec/Decoder/Video"))
12532                 {
12533                         gboolean ret = FALSE;
12534
12535                         if (player->v_stream_caps != NULL)
12536                         {
12537                                 GstPad *pad = gst_element_get_static_pad(element, "sink");
12538
12539                                 if (pad)
12540                                 {
12541                                         ret = gst_pad_set_caps(pad, player->v_stream_caps);
12542                                         debug_log("found omx decoder, setting gst_pad_set_caps for omx (ret:%d)", ret);
12543                                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
12544                                         gst_object_unref (pad);
12545                                 }
12546                         }
12547                         g_object_set (G_OBJECT(element), "state-tuning", TRUE, NULL);
12548                 }
12549 #ifdef _MM_PLAYER_ALP_PARSER
12550                 if (g_strrstr(factory_name, "omx_mp3dec"))
12551                 {
12552                         g_list_foreach (player->parsers, check_name, player);
12553                 }
12554 #endif
12555                 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
12556         }
12557
12558         if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
12559                 (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue")))
12560         {
12561                 debug_log ("plugged element is multiqueue. take it\n");
12562
12563                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
12564                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
12565
12566                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
12567                         (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)))
12568                 {
12569                         /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
12570                         __mm_player_streaming_set_multiqueue(player->streamer,
12571                                 element,
12572                                 TRUE,
12573                                 player->ini.http_buffering_time,
12574                                 1.0,
12575                                 player->ini.http_buffering_limit);
12576
12577                         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
12578                 }
12579         }
12580
12581         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-added" );
12582         return;
12583 }
12584
12585 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
12586 {
12587         MMPLAYER_FENTER();
12588         return_val_if_fail ( player, FALSE );
12589
12590         if ( MMPLAYER_IS_STREAMING(player) )
12591                 return FALSE;
12592
12593         /* This callback can be set to music player only. */
12594         if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
12595         {
12596                 debug_warning("audio callback is not supported for video");
12597                 return FALSE;
12598         }
12599
12600         if (player->audio_stream_cb)
12601         {
12602                 {
12603                         GstPad *pad = NULL;
12604
12605                         pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
12606
12607                         if ( !pad )
12608                         {
12609                                 debug_error("failed to get sink pad from audiosink to probe data\n");
12610                                 return FALSE;
12611                         }
12612                         player->audio_cb_probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
12613                                 __mmplayer_audio_stream_probe, player, NULL);
12614
12615                         gst_object_unref (pad);
12616
12617                         pad = NULL;
12618                }
12619         }
12620         else
12621         {
12622                 debug_error("There is no audio callback to configure.\n");
12623                 return FALSE;
12624         }
12625
12626         MMPLAYER_FLEAVE();
12627
12628         return TRUE;
12629 }
12630
12631 static void
12632 __mmplayer_init_factories(mm_player_t* player) // @
12633 {
12634         return_if_fail ( player );
12635
12636         player->factories = gst_registry_feature_filter(gst_registry_get(),
12637                                         (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
12638         player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
12639 }
12640
12641 static void
12642 __mmplayer_release_factories(mm_player_t* player) // @
12643 {
12644         MMPLAYER_FENTER();
12645         return_if_fail ( player );
12646
12647         if (player->factories)
12648         {
12649                 gst_plugin_feature_list_free (player->factories);
12650                 player->factories = NULL;
12651         }
12652
12653         MMPLAYER_FLEAVE();
12654 }
12655
12656 static void
12657 __mmplayer_release_misc(mm_player_t* player)
12658 {
12659         int i;
12660         gboolean cur_mode = player->set_mode.rich_audio;
12661         MMPLAYER_FENTER();
12662
12663         return_if_fail ( player );
12664
12665         player->use_video_stream = FALSE;
12666         player->video_stream_cb = NULL;
12667         player->video_stream_cb_user_param = NULL;
12668
12669         player->audio_stream_cb = NULL;
12670         player->audio_stream_render_cb_ex = NULL;
12671         player->audio_stream_cb_user_param = NULL;
12672         player->audio_stream_sink_sync = false;
12673
12674         player->video_stream_changed_cb = NULL;
12675         player->video_stream_changed_cb_user_param = NULL;
12676
12677         player->audio_stream_changed_cb = NULL;
12678         player->audio_stream_changed_cb_user_param = NULL;
12679
12680         player->sent_bos = FALSE;
12681         player->playback_rate = DEFAULT_PLAYBACK_RATE;
12682
12683         player->doing_seek = FALSE;
12684
12685         player->updated_bitrate_count = 0;
12686         player->total_bitrate = 0;
12687         player->updated_maximum_bitrate_count = 0;
12688         player->total_maximum_bitrate = 0;
12689
12690         player->not_found_demuxer = 0;
12691
12692         player->last_position = 0;
12693         player->duration = 0;
12694         player->http_content_size = 0;
12695         player->not_supported_codec = MISSING_PLUGIN_NONE;
12696         player->can_support_codec = FOUND_PLUGIN_NONE;
12697         player->pending_seek.is_pending = FALSE;
12698         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
12699         player->pending_seek.pos = 0;
12700         player->msg_posted = FALSE;
12701         player->has_many_types = FALSE;
12702         player->is_drm_file = FALSE;
12703         player->max_audio_channels = 0;
12704         player->video_share_api_delta = 0;
12705         player->video_share_clock_delta = 0;
12706         player->sound_focus.keep_last_pos = FALSE;
12707         player->sound_focus.acquired = FALSE;
12708         player->is_subtitle_force_drop = FALSE;
12709         player->play_subtitle = FALSE;
12710         player->use_textoverlay = FALSE;
12711         player->adjust_subtitle_pos = 0;
12712         player->last_multiwin_status = FALSE;
12713         player->has_closed_caption = FALSE;
12714         player->set_mode.media_packet_video_stream = FALSE;
12715         memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
12716         /* recover mode */
12717         player->set_mode.rich_audio = cur_mode;
12718
12719         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
12720         {
12721                 player->bitrate[i] = 0;
12722                 player->maximum_bitrate[i] = 0;
12723         }
12724
12725         /* remove media stream cb (appsrc cb) */
12726         for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++)
12727         {
12728                 player->media_stream_buffer_status_cb[i] = NULL;
12729                 player->media_stream_seek_data_cb[i] = NULL;
12730         }
12731
12732         /* free memory related to audio effect */
12733         MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
12734
12735         if (player->state_tune_caps)
12736         {
12737                 gst_caps_unref(player->state_tune_caps);
12738                 player->state_tune_caps = NULL;
12739         }
12740
12741         if (player->video_cb_probe_id)
12742         {
12743                 GstPad *pad = NULL;
12744
12745                 pad = gst_element_get_static_pad (player->video_fakesink, "sink");
12746
12747                 if (pad) {
12748                         debug_log("release video probe\n");
12749
12750                         /* release audio callback */
12751                         gst_pad_remove_probe (pad, player->video_cb_probe_id);
12752                         player->video_cb_probe_id = 0;
12753                         player->video_stream_cb = NULL;
12754                         player->video_stream_cb_user_param = NULL;
12755                 }
12756         }
12757
12758         MMPLAYER_FLEAVE();
12759 }
12760
12761 static void
12762 __mmplayer_release_misc_post(mm_player_t* player)
12763 {
12764         char *original_uri = NULL;
12765         MMPLAYER_FENTER();
12766
12767         /* player->pipeline is already released before. */
12768
12769         return_if_fail ( player );
12770
12771         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
12772         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
12773
12774         /* clean found parsers */
12775         if (player->parsers)
12776         {
12777                 GList *parsers = player->parsers;
12778                 for ( ;parsers ; parsers = g_list_next(parsers))
12779                 {
12780                         gchar *name = parsers->data;
12781                         MMPLAYER_FREEIF(name);
12782                 }
12783                 g_list_free(player->parsers);
12784                 player->parsers = NULL;
12785         }
12786
12787         /* clean found audio decoders */
12788         if (player->audio_decoders)
12789         {
12790                 GList *a_dec = player->audio_decoders;
12791                 for ( ;a_dec ; a_dec = g_list_next(a_dec))
12792                 {
12793                         gchar *name = a_dec->data;
12794                         MMPLAYER_FREEIF(name);
12795                 }
12796                 g_list_free(player->audio_decoders);
12797                 player->audio_decoders = NULL;
12798         }
12799
12800         /* clean the uri list except original uri */
12801         if (player->uri_info.uri_list)
12802         {
12803                 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
12804
12805                 if (player->attrs)
12806                 {
12807                         mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
12808                         debug_log("restore original uri = %s\n", original_uri);
12809
12810                         if (mmf_attrs_commit(player->attrs))
12811                         {
12812                                 debug_error("failed to commit the original uri.\n");
12813                         }
12814                 }
12815
12816                 GList *uri_list = player->uri_info.uri_list;
12817                 for ( ;uri_list ; uri_list = g_list_next(uri_list))
12818                 {
12819                         gchar *uri = uri_list->data;
12820                         MMPLAYER_FREEIF(uri);
12821                 }
12822                 g_list_free(player->uri_info.uri_list);
12823                 player->uri_info.uri_list = NULL;
12824         }
12825
12826         player->uri_info.uri_idx = 0;
12827         MMPLAYER_FLEAVE();
12828 }
12829
12830 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
12831 {
12832         GstElement *element = NULL;
12833         GstPad *sinkpad;
12834
12835         debug_log("creating %s to plug\n", name);
12836
12837         element = gst_element_factory_make(name, NULL);
12838         if ( ! element )
12839         {
12840                 debug_error("failed to create queue\n");
12841                 return NULL;
12842         }
12843
12844         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
12845         {
12846                 debug_error("failed to set state READY to %s\n", name);
12847                 gst_object_unref (element);
12848                 return NULL;
12849         }
12850
12851         if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
12852         {
12853                 debug_error("failed to add %s\n", name);
12854                 gst_object_unref (element);
12855                 return NULL;
12856         }
12857
12858         sinkpad = gst_element_get_static_pad(element, "sink");
12859
12860         if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
12861         {
12862                 debug_error("failed to link %s\n", name);
12863                 gst_object_unref (sinkpad);
12864                 gst_object_unref (element);
12865                 return NULL;
12866         }
12867
12868         debug_log("linked %s to pipeline successfully\n", name);
12869
12870         gst_object_unref (sinkpad);
12871
12872         return element;
12873 }
12874
12875 static gboolean
12876 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
12877 const char *padname, const GList *templlist)
12878 {
12879         GstPad *pad = NULL;
12880         gboolean has_dynamic_pads = FALSE;
12881         gboolean has_many_types = FALSE;
12882         const char *klass = NULL;
12883         GstStaticPadTemplate *padtemplate = NULL;
12884         GstElementFactory *factory = NULL;
12885         GstElement* queue = NULL;
12886         GstElement* parser = NULL;
12887         GstPad *pssrcpad = NULL;
12888         GstPad *qsrcpad = NULL, *qsinkpad = NULL;
12889         MMPlayerGstElement *mainbin = NULL;
12890         GstStructure* str = NULL;
12891         GstCaps* srccaps = NULL;
12892         GstState target_state = GST_STATE_READY;
12893         gboolean isvideo_decoder = FALSE;
12894         guint q_max_size_time = 0;
12895
12896         MMPLAYER_FENTER();
12897
12898         return_val_if_fail ( player &&
12899                 player->pipeline &&
12900                 player->pipeline->mainbin,
12901                 FALSE );
12902
12903         mainbin = player->pipeline->mainbin;
12904
12905         debug_log("plugging pad %s:%s to newly create %s:%s\n",
12906                         GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
12907                         GST_PAD_NAME( srcpad ),
12908                         GST_ELEMENT_NAME( sinkelement ),
12909                         padname);
12910
12911         factory = gst_element_get_factory(sinkelement);
12912         klass = gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
12913
12914         /* check if player can do start continually */
12915         MMPLAYER_CHECK_CMD_IF_EXIT(player);
12916
12917         /* need it to warm up omx before linking to pipeline */
12918         if (g_strrstr(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ), "demux"))
12919         {
12920                 debug_log("get demux caps.\n");
12921                 if (player->state_tune_caps)
12922                 {
12923                         gst_caps_unref(player->state_tune_caps);
12924                         player->state_tune_caps = NULL;
12925                 }
12926                 player->state_tune_caps = gst_caps_copy(gst_pad_get_current_caps(srcpad));
12927         }
12928
12929         /* NOTE : OMX Codec can check if resource is available or not at this state. */
12930         if (g_strrstr(GST_ELEMENT_NAME(sinkelement), "omx"))
12931         {
12932                 if (player->state_tune_caps != NULL)
12933                 {
12934                         debug_log("set demux's caps to omx codec if resource is available");
12935                         if (gst_pad_set_caps(gst_element_get_static_pad(sinkelement, "sink"), player->state_tune_caps))
12936                         {
12937                                 target_state = GST_STATE_PAUSED;
12938                                 isvideo_decoder = TRUE;
12939                                 g_object_set(G_OBJECT(sinkelement), "state-tuning", TRUE, NULL);
12940                         }
12941                         else
12942                         {
12943                                 debug_warning("failed to set caps for state tuning");
12944                         }
12945                 }
12946                 gst_caps_unref(player->state_tune_caps);
12947                 player->state_tune_caps = NULL;
12948         }
12949
12950         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, target_state) )
12951         {
12952                 debug_error("failed to set %d state to %s\n", target_state, GST_ELEMENT_NAME( sinkelement ));
12953                 if (isvideo_decoder)
12954                 {
12955                         gst_element_set_state(sinkelement, GST_STATE_NULL);
12956                         gst_object_unref(G_OBJECT(sinkelement));
12957                         player->keep_detecting_vcodec = TRUE;
12958                 }
12959                 goto ERROR;
12960         }
12961
12962         /* add to pipeline */
12963         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
12964         {
12965                 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
12966                 goto ERROR;
12967         }
12968
12969         debug_log("element klass : %s\n", klass);
12970
12971         /* added to support multi track files */
12972         /* only decoder case and any of the video/audio still need to link*/
12973         if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
12974         {
12975                 gchar *name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
12976
12977                 if (g_strrstr(name, "mpegtsdemux")|| g_strrstr(name, SMOOTH_STREAMING_DEMUX))
12978                 {
12979                         gchar *src_demux_caps_str = NULL;
12980                         gchar *needed_parser = NULL;
12981                         GstCaps *src_demux_caps = NULL;
12982                         gboolean smooth_streaming = FALSE;
12983
12984                         src_demux_caps = gst_pad_query_caps(srcpad, NULL);
12985                         src_demux_caps_str = gst_caps_to_string(src_demux_caps);
12986
12987                         gst_caps_unref(src_demux_caps);
12988
12989                         if (g_strrstr(src_demux_caps_str, "video/x-h264"))
12990                         {
12991                                 if (g_strrstr(name, SMOOTH_STREAMING_DEMUX))
12992                                 {
12993                                         needed_parser = g_strdup("legacyh264parse");
12994                                         smooth_streaming = TRUE;
12995                                 }
12996                                 else
12997                                 {
12998                                         needed_parser = g_strdup("h264parse");
12999                                 }
13000                         }
13001                         else if (g_strrstr(src_demux_caps_str, "video/mpeg"))
13002                         {
13003                                 needed_parser = g_strdup("mpeg4videoparse");
13004                         }
13005                         MMPLAYER_FREEIF(src_demux_caps_str);
13006
13007                         if (needed_parser)
13008                         {
13009                                 parser = __mmplayer_element_create_and_link(player, srcpad, needed_parser);
13010                                 MMPLAYER_FREEIF(needed_parser);
13011
13012                                 if ( !parser )
13013                                 {
13014                                         debug_error("failed to create parser\n");
13015                                 }
13016                                 else
13017                                 {
13018                                         if (smooth_streaming)
13019                                         {
13020                                                 g_object_set (parser, "output-format", 1, NULL); /* NALU/Byte Stream format */
13021                                         }
13022
13023                                         /* update srcpad if parser is created */
13024                                         pssrcpad = gst_element_get_static_pad(parser, "src");
13025                                         srcpad = pssrcpad;
13026                                 }
13027                         }
13028                 }
13029                 MMPLAYER_FREEIF(name);
13030
13031                 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
13032                 if ( ! queue )
13033                 {
13034                         debug_error("failed to create queue\n");
13035                         goto ERROR;
13036                 }
13037
13038                 /* update srcpad to link with decoder */
13039                 qsrcpad = gst_element_get_static_pad(queue, "src");
13040                 srcpad = qsrcpad;
13041
13042                 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
13043
13044                 /* assigning queue handle for futher manipulation purpose */
13045                 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
13046                 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
13047                 {
13048                         mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
13049                         mainbin[MMPLAYER_M_Q1].gst = queue;
13050
13051                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
13052                         {
13053                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", 0 , NULL);
13054                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-buffers", 2, NULL);
13055                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-bytes", 0, NULL);
13056                         }
13057                         else
13058                         {
13059                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
13060                                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
13061                         }
13062                 }
13063                 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
13064                 {
13065                         mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
13066                         mainbin[MMPLAYER_M_Q2].gst = queue;
13067
13068                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
13069                         {
13070                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", 0 , NULL);
13071                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-buffers", 2, NULL);
13072                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-bytes", 0, NULL);
13073                         }
13074                         else
13075                         {
13076                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
13077                                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
13078                         }
13079                 }
13080                 else
13081                 {
13082                         debug_error("Not supporting more then two elementary stream\n");
13083                         g_assert(1);
13084                 }
13085
13086                 pad = gst_element_get_static_pad(sinkelement, padname);
13087
13088                 if ( ! pad )
13089                 {
13090                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
13091                                 padname, GST_ELEMENT_NAME(sinkelement) );
13092
13093                         pad = gst_element_get_static_pad(sinkelement, "sink");
13094                         if ( ! pad )
13095                         {
13096                                 debug_error("failed to get pad(sink) from %s. \n",
13097                                 GST_ELEMENT_NAME(sinkelement) );
13098                                 goto ERROR;
13099                         }
13100                 }
13101
13102                 /*  to check the video/audio type set the proper flag*/
13103                 const gchar *mime_type = NULL;
13104                 {
13105                         srccaps = gst_pad_query_caps(srcpad, NULL);
13106                         if ( !srccaps )
13107                                 goto ERROR;
13108
13109                         str = gst_caps_get_structure( srccaps, 0 );
13110                         if ( ! str )
13111                                 goto ERROR;
13112
13113                         mime_type = gst_structure_get_name(str);
13114                         if ( ! mime_type )
13115                                 goto ERROR;
13116                 }
13117
13118                 /* link queue and decoder. so, it will be queue - decoder. */
13119                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
13120                 {
13121                         gst_object_unref(GST_OBJECT(pad));
13122                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
13123
13124                         /* reconstitute supportable codec */
13125                         if (strstr(mime_type, "video"))
13126                         {
13127                                 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
13128                         }
13129                         else if (strstr(mime_type, "audio"))
13130                         {
13131                                 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
13132                         }
13133                         goto ERROR;
13134                 }
13135
13136                 if (strstr(mime_type, "video"))
13137                 {
13138                         player->videodec_linked = 1;
13139                         debug_msg("player->videodec_linked set to 1\n");
13140
13141                 }
13142                 else if (strstr(mime_type, "audio"))
13143                 {
13144                         player->audiodec_linked = 1;
13145                         debug_msg("player->auddiodec_linked set to 1\n");
13146                 }
13147
13148                 gst_object_unref(GST_OBJECT(pad));
13149                 gst_caps_unref(GST_CAPS(srccaps));
13150                 srccaps = NULL;
13151         }
13152
13153         if ( !MMPLAYER_IS_HTTP_PD(player) )
13154         {
13155                 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
13156                 {
13157                         if (MMPLAYER_IS_HTTP_STREAMING(player))
13158                         {
13159                                 gint64 dur_bytes = 0L;
13160                                 gchar *file_buffering_path = NULL;
13161                                 gboolean use_file_buffer = FALSE;
13162
13163                                 if ( !mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
13164                                 {
13165                                         debug_log("creating http streaming buffering queue\n");
13166
13167                                         queue = gst_element_factory_make("queue2", "queue2");
13168                                         if ( ! queue )
13169                                         {
13170                                                 debug_error ( "failed to create buffering queue element\n" );
13171                                                 goto ERROR;
13172                                         }
13173
13174                                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
13175                                         {
13176                                                 debug_error("failed to set state READY to buffering queue\n");
13177                                                 goto ERROR;
13178                                         }
13179
13180                                         if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
13181                                         {
13182                                                 debug_error("failed to add buffering queue\n");
13183                                                 goto ERROR;
13184                                         }
13185
13186                                         qsinkpad = gst_element_get_static_pad(queue, "sink");
13187                                         qsrcpad = gst_element_get_static_pad(queue, "src");
13188
13189                                         if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
13190                                         {
13191                                                 debug_error("failed to link buffering queue\n");
13192                                                 goto ERROR;
13193                                         }
13194                                         srcpad = qsrcpad;
13195
13196
13197                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
13198                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue;
13199
13200                                         if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
13201                                         {
13202                                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
13203                                                         debug_error("fail to get duration.\n");
13204
13205                                                 if (dur_bytes > 0)
13206                                                 {
13207                                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
13208                                                         file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
13209                                                 }
13210                                                 else
13211                                                 {
13212                                                         dur_bytes = 0;
13213                                                 }
13214                                         }
13215
13216                                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
13217                                         if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
13218                                         {
13219                                                 __mm_player_streaming_set_queue2(player->streamer,
13220                                                         queue,
13221                                                         TRUE,
13222                                                         player->ini.http_max_size_bytes,
13223                                                         player->ini.http_buffering_time,
13224                                                         1.0,
13225                                                         player->ini.http_buffering_limit,
13226                                                         use_file_buffer,
13227                                                         file_buffering_path,
13228                                                         (guint64)dur_bytes);
13229                                         }
13230
13231                                         MMPLAYER_FREEIF(file_buffering_path);
13232                                 }
13233                         }
13234                 }
13235         }
13236         /* if it is not decoder or */
13237         /* in decoder case any of the video/audio still need to link*/
13238         if(!g_strrstr(klass, "Decoder"))
13239         {
13240
13241                 pad = gst_element_get_static_pad(sinkelement, padname);
13242                 if ( ! pad )
13243                 {
13244                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
13245                                         padname, GST_ELEMENT_NAME(sinkelement) );
13246
13247                         pad = gst_element_get_static_pad(sinkelement, "sink");
13248
13249                         if ( ! pad )
13250                         {
13251                                 debug_error("failed to get pad(sink) from %s. \n",
13252                                         GST_ELEMENT_NAME(sinkelement) );
13253                                 goto ERROR;
13254                         }
13255                 }
13256
13257                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
13258                 {
13259                         gst_object_unref(GST_OBJECT(pad));
13260                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
13261                         goto ERROR;
13262                 }
13263
13264                 gst_object_unref(GST_OBJECT(pad));
13265         }
13266
13267         for(;templlist != NULL; templlist = templlist->next)
13268         {
13269                 padtemplate = templlist->data;
13270
13271                 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
13272
13273                 if(     padtemplate->direction != GST_PAD_SRC ||
13274                         padtemplate->presence == GST_PAD_REQUEST        )
13275                         continue;
13276
13277                 switch(padtemplate->presence)
13278                 {
13279                         case GST_PAD_ALWAYS:
13280                         {
13281                                 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
13282                                 GstCaps *caps = gst_pad_query_caps(srcpad, NULL);
13283
13284                                 /* Check whether caps has many types */
13285                                 if ( !gst_caps_is_fixed(caps))
13286                                 {
13287                                         debug_log ("always pad but, caps has many types");
13288                                         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
13289                                         has_many_types = TRUE;
13290                                         break;
13291                                 }
13292
13293                                 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
13294                                 {
13295                                         gst_object_unref(GST_OBJECT(srcpad));
13296                                         gst_caps_unref(GST_CAPS(caps));
13297
13298                                         debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
13299                                         goto ERROR;
13300                                 }
13301
13302                                 gst_caps_unref(GST_CAPS(caps));
13303                                 gst_object_unref(GST_OBJECT(srcpad));
13304
13305                         }
13306                         break;
13307
13308
13309                         case GST_PAD_SOMETIMES:
13310                                 has_dynamic_pads = TRUE;
13311                         break;
13312
13313                         default:
13314                                 break;
13315                 }
13316         }
13317
13318         /* check if player can do start continually */
13319         MMPLAYER_CHECK_CMD_IF_EXIT(player);
13320
13321         if( has_dynamic_pads )
13322         {
13323                 player->have_dynamic_pad = TRUE;
13324                 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
13325                         G_CALLBACK(__mmplayer_add_new_pad), player);
13326
13327                 /* for streaming, more then one typefind will used for each elementary stream
13328                  * so this doesn't mean the whole pipeline completion
13329                  */
13330                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
13331                 {
13332                         MMPLAYER_SIGNAL_CONNECT( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
13333                                 G_CALLBACK(__mmplayer_pipeline_complete), player);
13334                 }
13335         }
13336
13337         if (has_many_types)
13338         {
13339                 GstPad *pad = NULL;
13340
13341                 player->has_many_types = has_many_types;
13342
13343                 pad = gst_element_get_static_pad(sinkelement, "src");
13344                 MMPLAYER_SIGNAL_CONNECT (player, pad, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
13345                 gst_object_unref (GST_OBJECT(pad));
13346         }
13347
13348
13349         /* check if player can do start continually */
13350         MMPLAYER_CHECK_CMD_IF_EXIT(player);
13351
13352         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
13353         {
13354                 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
13355                 goto ERROR;
13356         }
13357
13358         if ( queue )
13359         {
13360                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
13361                 {
13362                         debug_error("failed to set state PAUSED to queue\n");
13363                         goto ERROR;
13364                 }
13365
13366                 queue = NULL;
13367
13368                 gst_object_unref (GST_OBJECT(qsrcpad));
13369                 qsrcpad = NULL;
13370         }
13371
13372         if ( parser )
13373         {
13374                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
13375                 {
13376                         debug_error("failed to set state PAUSED to queue\n");
13377                         goto ERROR;
13378                 }
13379
13380                 parser = NULL;
13381
13382                 gst_object_unref (GST_OBJECT(pssrcpad));
13383                 pssrcpad = NULL;
13384         }
13385
13386         MMPLAYER_FLEAVE();
13387
13388         return TRUE;
13389
13390 ERROR:
13391
13392         if ( queue )
13393         {
13394                 gst_object_unref(GST_OBJECT(qsrcpad));
13395
13396                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
13397                  * You need to explicitly set elements to the NULL state before
13398                  * dropping the final reference, to allow them to clean up.
13399                  */
13400                 gst_element_set_state(queue, GST_STATE_NULL);
13401                 /* And, it still has a parent "player".
13402                  * You need to let the parent manage the object instead of unreffing the object directly.
13403                  */
13404
13405                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
13406                 //gst_object_unref( queue );
13407         }
13408
13409         if ( srccaps )
13410                 gst_caps_unref(GST_CAPS(srccaps));
13411
13412     return FALSE;
13413 }
13414
13415 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
13416 {
13417         const gchar *klass;
13418         //const gchar *name;
13419
13420         /* we only care about element factories */
13421         if (!GST_IS_ELEMENT_FACTORY(feature))
13422                 return FALSE;
13423
13424         /* only parsers, demuxers and decoders */
13425                 klass = gst_element_factory_get_metadata (GST_ELEMENT_FACTORY(feature), GST_ELEMENT_METADATA_KLASS);
13426             //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
13427
13428         if( g_strrstr(klass, "Demux") == NULL &&
13429                 g_strrstr(klass, "Codec/Decoder") == NULL &&
13430                 g_strrstr(klass, "Depayloader") == NULL &&
13431                 g_strrstr(klass, "Parse") == NULL)
13432         {
13433                 return FALSE;
13434         }
13435     return TRUE;
13436 }
13437
13438
13439 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
13440 {
13441         mm_player_t* player = (mm_player_t*) data;
13442         GstCaps *caps = NULL;
13443         GstStructure *str = NULL;
13444         const char *name;
13445
13446         MMPLAYER_FENTER();
13447
13448         return_if_fail ( pad )
13449         return_if_fail ( unused )
13450         return_if_fail ( data )
13451
13452         caps = gst_pad_query_caps(pad, NULL);
13453         if ( !caps )
13454                 return;
13455
13456         str = gst_caps_get_structure(caps, 0);
13457         if ( !str )
13458                 return;
13459
13460         name = gst_structure_get_name(str);
13461         if ( !name )
13462                 return;
13463         debug_log("name=%s\n", name);
13464
13465         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
13466         {
13467                 debug_error("failed to autoplug for type (%s)\n", name);
13468                 gst_caps_unref(caps);
13469                 return;
13470         }
13471
13472         gst_caps_unref(caps);
13473
13474         __mmplayer_pipeline_complete( NULL, (gpointer)player );
13475
13476         MMPLAYER_FLEAVE();
13477
13478         return;
13479 }
13480
13481 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
13482 {
13483         GstStructure *str;
13484         gint version = 0;
13485         const char *stream_type;
13486         gchar *version_field = NULL;
13487
13488         MMPLAYER_FENTER();
13489
13490         return_if_fail ( player );
13491         return_if_fail ( caps );
13492
13493         str = gst_caps_get_structure(caps, 0);
13494         if ( !str )
13495                 return;
13496
13497         stream_type = gst_structure_get_name(str);
13498         if ( !stream_type )
13499                 return;
13500
13501
13502         /* set unlinked mime type for downloadable codec */
13503         if (g_str_has_prefix(stream_type, "video/"))
13504         {
13505                 if (g_str_has_prefix(stream_type, "video/mpeg"))
13506                 {
13507                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
13508                         version_field = MM_PLAYER_MPEG_VNAME;
13509                 }
13510                 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
13511                 {
13512                         gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
13513                         version_field = MM_PLAYER_WMV_VNAME;
13514
13515                 }
13516                 else if (g_str_has_prefix(stream_type, "video/x-divx"))
13517                 {
13518                         gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
13519                         version_field = MM_PLAYER_DIVX_VNAME;
13520                 }
13521
13522                 if (version)
13523                 {
13524                         player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
13525                 }
13526                 else
13527                 {
13528                         player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
13529                 }
13530         }
13531         else if (g_str_has_prefix(stream_type, "audio/"))
13532         {
13533                 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
13534                 {
13535                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
13536                         version_field = MM_PLAYER_MPEG_VNAME;
13537                 }
13538                 else if (g_str_has_prefix(stream_type, "audio/x-wma"))
13539                 {
13540                         gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
13541                         version_field = MM_PLAYER_WMA_VNAME;
13542                 }
13543
13544                 if (version)
13545                 {
13546                         player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
13547                 }
13548                 else
13549                 {
13550                         player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
13551                 }
13552         }
13553
13554         MMPLAYER_FLEAVE();
13555 }
13556
13557 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
13558 {
13559         mm_player_t* player = (mm_player_t*) data;
13560         GstCaps *caps = NULL;
13561         GstStructure *str = NULL;
13562         const char *name;
13563
13564         MMPLAYER_FENTER();
13565         return_if_fail ( player );
13566         return_if_fail ( pad );
13567
13568         GST_OBJECT_LOCK (pad);
13569         if ((caps = gst_pad_get_current_caps(pad)))
13570                 gst_caps_ref(caps);
13571         GST_OBJECT_UNLOCK (pad);
13572
13573         if ( NULL == caps )
13574         {
13575                 caps = gst_pad_query_caps(pad, NULL);
13576                 if ( !caps ) return;
13577         }
13578
13579         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
13580
13581         str = gst_caps_get_structure(caps, 0);
13582         if ( !str )
13583                 return;
13584
13585         name = gst_structure_get_name(str);
13586         if ( !name )
13587                 return;
13588
13589         player->num_dynamic_pad++;
13590         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
13591
13592         /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
13593           *     If want to play it, remove this code.
13594           */
13595         if (g_strrstr(name, "application"))
13596         {
13597                 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
13598                 {
13599                         /* If id3/ape tag comes, keep going */
13600                         debug_log("application mime exception : id3/ape tag");
13601                 }
13602                 else
13603                 {
13604                         /* Otherwise, we assume that this stream is subtile. */
13605                         debug_log(" application mime type pad is closed.");
13606                         return;
13607                 }
13608         }
13609         else if (g_strrstr(name, "audio"))
13610         {
13611                 gint samplerate = 0, channels = 0;
13612
13613                 if (player->audiodec_linked)
13614                 {
13615                         gst_caps_unref(caps);
13616                         debug_log("multi tracks. skip to plug");
13617                         return;
13618                 }
13619
13620                 /* set stream information */
13621                 /* if possible, set it here because the caps is not distrubed by resampler. */
13622                 gst_structure_get_int (str, "rate", &samplerate);
13623                 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
13624
13625                 gst_structure_get_int (str, "channels", &channels);
13626                 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
13627
13628                 debug_log("audio samplerate : %d        channels : %d", samplerate, channels);
13629         }
13630         else if (g_strrstr(name, "video"))
13631         {
13632                 gint stype;
13633                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
13634
13635                 /* don't make video because of not required */
13636                 if (stype == MM_DISPLAY_SURFACE_NULL)
13637                 {
13638                         debug_log("no video because it's not required");
13639                         return;
13640                 }
13641
13642                 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
13643         }
13644
13645         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
13646         {
13647                 debug_error("failed to autoplug for type (%s)", name);
13648
13649                 __mmplayer_set_unlinked_mime_type(player, caps);
13650         }
13651
13652         gst_caps_unref(caps);
13653
13654         MMPLAYER_FLEAVE();
13655         return;
13656 }
13657
13658 gboolean
13659 __mmplayer_check_subtitle( mm_player_t* player )
13660 {
13661         MMHandleType attrs = 0;
13662         char *subtitle_uri = NULL;
13663
13664         MMPLAYER_FENTER();
13665
13666         return_val_if_fail( player, FALSE );
13667
13668         /* get subtitle attribute */
13669         attrs = MMPLAYER_GET_ATTRS(player);
13670         if ( !attrs )
13671                 return FALSE;
13672
13673         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
13674         if ( !subtitle_uri || !strlen(subtitle_uri))
13675                 return FALSE;
13676
13677         debug_log ("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
13678         player->is_external_subtitle_present = TRUE;
13679
13680         MMPLAYER_FLEAVE();
13681
13682         return TRUE;
13683 }
13684
13685 static gboolean
13686 __mmplayer_can_extract_pcm( mm_player_t* player )
13687 {
13688         MMHandleType attrs = 0;
13689         gboolean is_drm = FALSE;
13690         gboolean sound_extraction = FALSE;
13691
13692         return_val_if_fail ( player, FALSE );
13693
13694         attrs = MMPLAYER_GET_ATTRS(player);
13695         if ( !attrs )
13696         {
13697                 debug_error("fail to get attributes.");
13698                 return FALSE;
13699         }
13700
13701         /* check file is drm or not */
13702         if (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm"))
13703                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
13704
13705         /* get sound_extraction property */
13706         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
13707
13708         if ( ! sound_extraction || is_drm )
13709         {
13710                 debug_log("checking pcm extraction mode : %d, drm : %d", sound_extraction, is_drm);
13711                 return FALSE;
13712         }
13713
13714         return TRUE;
13715 }
13716
13717 static gboolean
13718 __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message )
13719 {
13720         debug_log("\n");
13721         MMMessageParamType msg_param;
13722         gchar *msg_src_element = NULL;
13723         GstStructure *s = NULL;
13724         guint error_id = 0;
13725         gchar *error_string = NULL;
13726
13727         MMPLAYER_FENTER();
13728
13729         return_val_if_fail ( player, FALSE );
13730         return_val_if_fail ( message, FALSE );
13731
13732         s = malloc( sizeof(GstStructure) );
13733         memcpy ( s, gst_message_get_structure ( message ), sizeof(GstStructure));
13734
13735         if ( !gst_structure_get_uint (s, "error_id", &error_id) )
13736                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
13737
13738         switch ( error_id )
13739         {
13740                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
13741                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
13742                         break;
13743                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
13744                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
13745                         break;
13746                 case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
13747                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
13748                         break;
13749                 case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
13750                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
13751                         break;
13752                 case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
13753                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
13754                         break;
13755                 case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
13756                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
13757                         break;
13758                 case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
13759                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
13760                         break;
13761                 case MMPLAYER_STREAMING_ERROR_INVALID_URL:
13762                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
13763                         break;
13764                 case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
13765                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
13766                         break;
13767                 case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
13768                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
13769                         break;
13770                 case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
13771                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
13772                         break;
13773                 case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
13774                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
13775                         break;
13776                 case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
13777                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
13778                         break;
13779                 case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
13780                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
13781                         break;
13782                 case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
13783                         msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
13784                         break;
13785                 case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
13786                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
13787                         break;
13788                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
13789                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
13790                         break;
13791                 case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
13792                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
13793                         break;
13794                 case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
13795                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
13796                         break;
13797                 case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
13798                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
13799                         break;
13800                 case MMPLAYER_STREAMING_ERROR_GONE:
13801                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
13802                         break;
13803                 case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
13804                         msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
13805                         break;
13806                 case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
13807                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
13808                         break;
13809                 case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
13810                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
13811                         break;
13812                 case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
13813                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
13814                         break;
13815                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
13816                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
13817                         break;
13818                 case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
13819                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
13820                         break;
13821                 case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
13822                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
13823                         break;
13824                 case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
13825                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
13826                         break;
13827                 case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
13828                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
13829                         break;
13830                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
13831                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
13832                         break;
13833                 case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
13834                         msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
13835                         break;
13836                 case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
13837                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
13838                         break;
13839                 case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
13840                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
13841                         break;
13842                 case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
13843                         msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
13844                         break;
13845                 case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
13846                         msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
13847                         break;
13848                 case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
13849                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
13850                         break;
13851                 case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
13852                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
13853                         break;
13854                 case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
13855                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
13856                         break;
13857                 case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
13858                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
13859                         break;
13860                 case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
13861                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
13862                         break;
13863                 case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
13864                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
13865                         break;
13866                 case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
13867                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
13868                         break;
13869                 case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
13870                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
13871                         break;
13872                 case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
13873                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
13874                         break;
13875                 default:
13876                         {
13877                                 MMPLAYER_FREEIF(s);
13878                                 return MM_ERROR_PLAYER_STREAMING_FAIL;
13879                         }
13880         }
13881
13882         error_string = g_strdup(gst_structure_get_string (s, "error_string"));
13883         if ( error_string )
13884                 msg_param.data = (void *) error_string;
13885
13886         if ( message->src )
13887         {
13888                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
13889
13890                 debug_error("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
13891                         msg_src_element, msg_param.code, (char*)msg_param.data );
13892         }
13893
13894         /* post error to application */
13895         if ( ! player->msg_posted )
13896         {
13897                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
13898
13899                 /* don't post more if one was sent already */
13900                 player->msg_posted = TRUE;
13901         }
13902         else
13903         {
13904                 debug_log("skip error post because it's sent already.\n");
13905         }
13906
13907         MMPLAYER_FREEIF(s);
13908         MMPLAYER_FLEAVE();
13909         g_free(error_string);
13910
13911         return TRUE;
13912
13913 }
13914
13915 static void
13916 __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms )
13917 {
13918         return_if_fail( player );
13919
13920
13921         /* post now if delay is zero */
13922         if ( delay_in_ms == 0 || player->set_mode.pcm_extraction)
13923         {
13924                 debug_log("eos delay is zero. posting EOS now\n");
13925                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
13926
13927                 if ( player->set_mode.pcm_extraction )
13928                         __mmplayer_cancel_eos_timer(player);
13929
13930                 return;
13931         }
13932
13933         /* cancel if existing */
13934         __mmplayer_cancel_eos_timer( player );
13935
13936         /* init new timeout */
13937         /* NOTE : consider give high priority to this timer */
13938         debug_log("posting EOS message after [%d] msec\n", delay_in_ms);
13939
13940         player->eos_timer = g_timeout_add( delay_in_ms,
13941                 __mmplayer_eos_timer_cb, player );
13942
13943         player->context.global_default = g_main_context_default ();
13944         debug_log("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
13945
13946         /* check timer is valid. if not, send EOS now */
13947         if ( player->eos_timer == 0 )
13948         {
13949                 debug_warning("creating timer for delayed EOS has failed. sending EOS now\n");
13950                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
13951         }
13952 }
13953
13954 static void
13955 __mmplayer_cancel_eos_timer( mm_player_t* player )
13956 {
13957         return_if_fail( player );
13958
13959         if ( player->eos_timer )
13960         {
13961                 debug_log("cancel eos timer");
13962                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
13963                 player->eos_timer = 0;
13964         }
13965
13966         return;
13967 }
13968
13969 static gboolean
13970 __mmplayer_eos_timer_cb(gpointer u_data)
13971 {
13972         mm_player_t* player = NULL;
13973         player = (mm_player_t*) u_data;
13974
13975         return_val_if_fail( player, FALSE );
13976
13977         if ( player->play_count > 1 )
13978         {
13979                 gint ret_value = 0;
13980                 ret_value = __gst_set_position( player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
13981                 if (ret_value == MM_ERROR_NONE)
13982                 {
13983                         MMHandleType attrs = 0;
13984                         attrs = MMPLAYER_GET_ATTRS(player);
13985
13986                         /* we successeded to rewind. update play count and then wait for next EOS */
13987                         player->play_count--;
13988
13989                         mm_attrs_set_int_by_name(attrs, "profile_play_count", player->play_count);
13990                         mmf_attrs_commit ( attrs );
13991                 }
13992                 else
13993                 {
13994                         debug_error("seeking to 0 failed in repeat play");
13995                 }
13996         }
13997         else
13998         {
13999                 /* posting eos */
14000                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
14001         }
14002
14003         /* we are returning FALSE as we need only one posting */
14004         return FALSE;
14005 }
14006
14007 static gboolean
14008 __mmplayer_link_decoder( mm_player_t* player, GstPad *srcpad)
14009 {
14010         const gchar* name = NULL;
14011         GstStructure* str = NULL;
14012         GstCaps* srccaps = NULL;
14013
14014         MMPLAYER_FENTER();
14015
14016         return_val_if_fail( player, FALSE );
14017         return_val_if_fail ( srcpad, FALSE );
14018
14019         /* to check any of the decoder (video/audio) need to be linked  to parser*/
14020         srccaps = gst_pad_query_caps( srcpad, NULL);
14021         if ( !srccaps )
14022                 goto ERROR;
14023
14024         str = gst_caps_get_structure( srccaps, 0 );
14025         if ( ! str )
14026                 goto ERROR;
14027
14028         name = gst_structure_get_name(str);
14029         if ( ! name )
14030                 goto ERROR;
14031
14032         if (strstr(name, "video"))
14033         {
14034                 if(player->videodec_linked)
14035                 {
14036                     debug_msg("Video decoder already linked\n");
14037                         return FALSE;
14038                 }
14039         }
14040         if (strstr(name, "audio"))
14041         {
14042                 if(player->audiodec_linked)
14043                 {
14044                     debug_msg("Audio decoder already linked\n");
14045                         return FALSE;
14046                 }
14047         }
14048
14049         gst_caps_unref( srccaps );
14050
14051         MMPLAYER_FLEAVE();
14052
14053         return TRUE;
14054
14055 ERROR:
14056         if ( srccaps )
14057                 gst_caps_unref( srccaps );
14058
14059         return FALSE;
14060 }
14061
14062 static gboolean
14063 __mmplayer_link_sink( mm_player_t* player , GstPad *srcpad)
14064 {
14065         const gchar* name = NULL;
14066         GstStructure* str = NULL;
14067         GstCaps* srccaps = NULL;
14068
14069         MMPLAYER_FENTER();
14070
14071         return_val_if_fail ( player, FALSE );
14072         return_val_if_fail ( srcpad, FALSE );
14073
14074         /* to check any of the decoder (video/audio) need to be linked  to parser*/
14075         srccaps = gst_pad_query_caps( srcpad, NULL );
14076         if ( !srccaps )
14077                 goto ERROR;
14078
14079         str = gst_caps_get_structure( srccaps, 0 );
14080         if ( ! str )
14081                 goto ERROR;
14082
14083         name = gst_structure_get_name(str);
14084         if ( ! name )
14085                 goto ERROR;
14086
14087         if (strstr(name, "video"))
14088         {
14089                 if(player->videosink_linked)
14090                 {
14091                         debug_msg("Video Sink already linked\n");
14092                         return FALSE;
14093                 }
14094         }
14095         if (strstr(name, "audio"))
14096         {
14097                 if(player->audiosink_linked)
14098                 {
14099                         debug_msg("Audio Sink already linked\n");
14100                         return FALSE;
14101                 }
14102         }
14103         if (strstr(name, "text"))
14104         {
14105                 if(player->textsink_linked)
14106                 {
14107                         debug_msg("Text Sink already linked\n");
14108                         return FALSE;
14109                 }
14110         }
14111
14112         gst_caps_unref( srccaps );
14113
14114         MMPLAYER_FLEAVE();
14115
14116         return TRUE;
14117         //return (!player->videosink_linked || !player->audiosink_linked);
14118
14119 ERROR:
14120         if ( srccaps )
14121                 gst_caps_unref( srccaps );
14122
14123         return FALSE;
14124 }
14125
14126
14127 /* sending event to one of sinkelements */
14128 static gboolean
14129 __gst_send_event_to_sink( mm_player_t* player, GstEvent* event )
14130 {
14131         GstEvent * event2 = NULL;
14132         GList *sinks = NULL;
14133         gboolean res = FALSE;
14134         MMPLAYER_FENTER();
14135
14136         return_val_if_fail( player, FALSE );
14137         return_val_if_fail ( event, FALSE );
14138
14139         if ( player->play_subtitle && !player->use_textoverlay)
14140                 event2 = gst_event_copy((const GstEvent *)event);
14141
14142         sinks = player->sink_elements;
14143         while (sinks)
14144         {
14145                 GstElement *sink = GST_ELEMENT_CAST (sinks->data);
14146
14147                 if (GST_IS_ELEMENT(sink))
14148                 {
14149                         /* keep ref to the event */
14150                         gst_event_ref (event);
14151
14152                         if ( (res = gst_element_send_event (sink, event)) )
14153                         {
14154                                 debug_log("sending event[%s] to sink element [%s] success!\n",
14155                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
14156
14157                                 /* rtsp case, asyn_done is not called after seek during pause state */
14158                                 if (MMPLAYER_IS_RTSP_STREAMING(player))
14159                                 {
14160                                         if (strstr(GST_EVENT_TYPE_NAME(event), "seek"))
14161                                         {
14162                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
14163                                                 {
14164                                                         debug_log("RTSP seek completed, after pause state..\n");
14165                                                         player->doing_seek = FALSE;
14166                                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
14167                                                 }
14168
14169                                         }
14170                                 }
14171
14172                                 if( MMPLAYER_IS_ES_BUFF_SRC(player))
14173                                 {
14174                                         sinks = g_list_next (sinks);
14175                                         continue;
14176                                 }
14177                                 else
14178                                         break;
14179                         }
14180
14181                         debug_log("sending event[%s] to sink element [%s] failed. try with next one.\n",
14182                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
14183                 }
14184
14185                 sinks = g_list_next (sinks);
14186         }
14187
14188 #if 0
14189         if (internal_sub)
14190           request pad name = sink0;
14191         else
14192           request pad name = sink1; // external
14193 #endif
14194
14195         /* Note : Textbin is not linked to the video or audio bin.
14196          * It needs to send the event to the text sink seperatelly.
14197          */
14198          if ( player->play_subtitle && !player->use_textoverlay)
14199          {
14200                 GstElement *text_sink = GST_ELEMENT_CAST (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
14201
14202                 if (GST_IS_ELEMENT(text_sink))
14203                 {
14204                         /* keep ref to the event */
14205                         gst_event_ref (event2);
14206
14207                         if ((res = gst_element_send_event (text_sink, event2)))
14208                         {
14209                                 debug_log("sending event[%s] to subtitle sink element [%s] success!\n",
14210                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
14211                         }
14212                         else
14213                         {
14214                                 debug_error("sending event[%s] to subtitle sink element [%s] failed!\n",
14215                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
14216                         }
14217
14218                         gst_event_unref (event2);
14219                 }
14220          }
14221
14222         gst_event_unref (event);
14223
14224         MMPLAYER_FLEAVE();
14225
14226         return res;
14227 }
14228
14229 static void
14230 __mmplayer_add_sink( mm_player_t* player, GstElement* sink )
14231 {
14232         MMPLAYER_FENTER();
14233
14234         return_if_fail ( player );
14235         return_if_fail ( sink );
14236
14237         player->sink_elements =
14238                 g_list_append(player->sink_elements, sink);
14239
14240         MMPLAYER_FLEAVE();
14241 }
14242
14243 static void
14244 __mmplayer_del_sink( mm_player_t* player, GstElement* sink )
14245 {
14246         MMPLAYER_FENTER();
14247
14248         return_if_fail ( player );
14249         return_if_fail ( sink );
14250
14251         player->sink_elements =
14252                         g_list_remove(player->sink_elements, sink);
14253
14254         MMPLAYER_FLEAVE();
14255 }
14256
14257 static gboolean
14258 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
14259                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
14260                         gint64 cur, GstSeekType stop_type, gint64 stop )
14261 {
14262         GstEvent* event = NULL;
14263         gboolean result = FALSE;
14264
14265         MMPLAYER_FENTER();
14266
14267         return_val_if_fail( player, FALSE );
14268
14269         __mmplayer_drop_subtitle(player, FALSE);
14270
14271         event = gst_event_new_seek (rate, format, flags, cur_type,
14272                 cur, stop_type, stop);
14273
14274         result = __gst_send_event_to_sink( player, event );
14275
14276         MMPLAYER_FLEAVE();
14277
14278         return result;
14279 }
14280
14281 /* NOTE : be careful with calling this api. please refer to below glib comment
14282  * glib comment : Note that there is a bug in GObject that makes this function much
14283  * less useful than it might seem otherwise. Once gobject is disposed, the callback
14284  * will no longer be called, but, the signal handler is not currently disconnected.
14285  * If the instance is itself being freed at the same time than this doesn't matter,
14286  * since the signal will automatically be removed, but if instance persists,
14287  * then the signal handler will leak. You should not remove the signal yourself
14288  * because in a future versions of GObject, the handler will automatically be
14289  * disconnected.
14290  *
14291  * It's possible to work around this problem in a way that will continue to work
14292  * with future versions of GObject by checking that the signal handler is still
14293  * connected before disconnected it:
14294  *
14295  *  if (g_signal_handler_is_connected (instance, id))
14296  *    g_signal_handler_disconnect (instance, id);
14297  */
14298 static void
14299 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
14300 {
14301         GList* sig_list = NULL;
14302         MMPlayerSignalItem* item = NULL;
14303
14304         MMPLAYER_FENTER();
14305
14306         return_if_fail( player );
14307
14308         debug_log("release signals type : %d", type);
14309
14310         if ((type < MM_PLAYER_SIGNAL_TYPE_AUTOPLUG) || (type >= MM_PLAYER_SIGNAL_TYPE_ALL))
14311         {
14312                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
14313                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
14314                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
14315                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
14316                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
14317                 return;
14318         }
14319
14320         sig_list = player->signals[type];
14321
14322         for ( ; sig_list; sig_list = sig_list->next )
14323         {
14324                 item = sig_list->data;
14325
14326                 if ( item && item->obj && GST_IS_ELEMENT(item->obj) )
14327                 {
14328                         if ( g_signal_handler_is_connected ( item->obj, item->sig ) )
14329                         {
14330                                 g_signal_handler_disconnect ( item->obj, item->sig );
14331                         }
14332                 }
14333
14334                 MMPLAYER_FREEIF( item );
14335         }
14336
14337         g_list_free ( player->signals[type] );
14338         player->signals[type] = NULL;
14339
14340         MMPLAYER_FLEAVE();
14341
14342         return;
14343 }
14344
14345 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
14346 {
14347         mm_player_t* player = 0;
14348         int prev_display_surface_type = 0;
14349         void *prev_display_overlay = NULL;
14350         const gchar *klass = NULL;
14351         gchar *cur_videosink_name = NULL;
14352         int ret = 0;
14353         int i = 0;
14354         int num_of_dec = 2; /* DEC1, DEC2 */
14355
14356         MMPLAYER_FENTER();
14357
14358         return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
14359         return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
14360
14361         player = MM_PLAYER_CAST(handle);
14362
14363         if (surface_type < MM_DISPLAY_SURFACE_X && surface_type >= MM_DISPLAY_SURFACE_NUM)
14364         {
14365                 debug_error("Not support this surface type(%d) for changing vidoesink", surface_type);
14366                 MMPLAYER_FLEAVE();
14367                 return MM_ERROR_INVALID_ARGUMENT;
14368         }
14369
14370         /* load previous attributes */
14371         if (player->attrs)
14372         {
14373                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &prev_display_surface_type);
14374                 mm_attrs_get_data_by_name (player->attrs, "display_overlay", &prev_display_overlay);
14375                 debug_log("[0: X surface, 1: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
14376                 if (prev_display_surface_type == surface_type)
14377                 {
14378                         debug_log("incoming display surface type is same as previous one, do nothing..");
14379                         MMPLAYER_FLEAVE();
14380                         return MM_ERROR_NONE;
14381                 }
14382         }
14383         else
14384         {
14385                 debug_error("failed to load attributes");
14386                 MMPLAYER_FLEAVE();
14387                 return MM_ERROR_PLAYER_INTERNAL;
14388         }
14389
14390         /* check videosink element is created */
14391         if (!player->pipeline || !player->pipeline->videobin ||
14392                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
14393         {
14394                 debug_log("videosink element is not yet ready");
14395
14396                 /* videobin is not created yet, so we just set attributes related to display surface */
14397                 debug_log("store display attribute for given surface type(%d)", surface_type);
14398                 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
14399                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
14400                 if ( mmf_attrs_commit ( player->attrs ) )
14401                 {
14402                         debug_error("failed to commit attribute");
14403                         MMPLAYER_FLEAVE();
14404                         return MM_ERROR_PLAYER_INTERNAL;
14405                 }
14406                 MMPLAYER_FLEAVE();
14407                 return MM_ERROR_NONE;
14408         }
14409         else
14410         {
14411                 /* get player command status */
14412                 if ( !(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE) )
14413                 {
14414                         debug_error("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command",player->cmd);
14415                         MMPLAYER_FLEAVE();
14416                         return MM_ERROR_PLAYER_INVALID_STATE;
14417                 }
14418
14419                 /* get a current videosink name */
14420                 cur_videosink_name = GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
14421
14422                 /* surface change */
14423                 for ( i = 0 ; i < num_of_dec ; i++)
14424                 {
14425                         if ( player->pipeline->mainbin &&
14426                                 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst )
14427                         {
14428                                 GstElementFactory *decfactory;
14429                                 decfactory = gst_element_get_factory (player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst);
14430
14431                                 klass = gst_element_factory_get_metadata (decfactory, GST_ELEMENT_METADATA_KLASS);
14432                                 if ((g_strrstr(klass, "Codec/Decoder/Video")))
14433                                 {
14434                                         if ( !strncmp(cur_videosink_name, "x", 1) && (surface_type == MM_DISPLAY_SURFACE_EVAS) )
14435                                         {
14436                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_evas, surface_type, display_overlay);
14437                                                 if (ret)
14438                                                 {
14439                                                         goto ERROR_CASE;
14440                                                 }
14441                                                 else
14442                                                 {
14443                                                         debug_warning("success to changing display surface(%d)",surface_type);
14444                                                         MMPLAYER_FLEAVE();
14445                                                         return MM_ERROR_NONE;
14446                                                 }
14447                                         }
14448                                         else if (!strncmp(cur_videosink_name, "evas", 4) && (surface_type == MM_DISPLAY_SURFACE_X) )
14449                                         {
14450                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_x, surface_type, display_overlay);
14451                                                 if (ret)
14452                                                 {
14453                                                         goto ERROR_CASE;
14454                                                 }
14455                                                 else
14456                                                 {
14457                                                         debug_warning("success to changing display surface(%d)",surface_type);
14458                                                         MMPLAYER_FLEAVE();
14459                                                         return MM_ERROR_NONE;
14460                                                 }
14461                                         }
14462                                         else
14463                                         {
14464                                                 debug_error("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface",surface_type, cur_videosink_name);
14465                                                 ret = MM_ERROR_PLAYER_INTERNAL;
14466                                                 goto ERROR_CASE;
14467                                         }
14468                                 }
14469                         }
14470                 }
14471         }
14472
14473 ERROR_CASE:
14474         /* rollback to previous attributes */
14475         mm_attrs_set_int_by_name (player->attrs, "display_surface_type", prev_display_surface_type);
14476         mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(void*));
14477         if ( mmf_attrs_commit ( player->attrs ) )
14478         {
14479                 debug_error("failed to commit attributes to rollback");
14480                 MMPLAYER_FLEAVE();
14481                 return MM_ERROR_PLAYER_INTERNAL;
14482         }
14483         MMPLAYER_FLEAVE();
14484         return ret;
14485 }
14486
14487 /* NOTE : It does not support some use cases, eg using colorspace converter */
14488 int
14489 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
14490 {
14491         GstPad *src_pad_dec = NULL;
14492         GstPad *sink_pad_videosink = NULL;
14493         GstPad *sink_pad_videobin = NULL;
14494         GstClock *clock = NULL;
14495         MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
14496         int ret = MM_ERROR_NONE;
14497         gboolean is_audiobin_created = TRUE;
14498
14499         MMPLAYER_FENTER();
14500
14501         return_val_if_fail(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
14502         return_val_if_fail(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
14503         return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
14504
14505         debug_log("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
14506         debug_log("surface type(%d), display overlay(%x)", surface_type, display_overlay);
14507
14508         /* get information whether if audiobin is created */
14509         if ( !player->pipeline->audiobin ||
14510                      !player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
14511         {
14512                 debug_warning("audiobin is null, this video content may not have audio data");
14513                 is_audiobin_created = FALSE;
14514         }
14515
14516         /* get current state of player */
14517         previous_state = MMPLAYER_CURRENT_STATE(player);
14518         debug_log("previous state(%d)", previous_state);
14519
14520
14521         /* get src pad of decoder and block it */
14522         src_pad_dec = gst_element_get_static_pad (GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
14523         if (!src_pad_dec)
14524         {
14525                 debug_error("failed to get src pad from decode in mainbin");
14526                 return MM_ERROR_PLAYER_INTERNAL;
14527         }
14528
14529         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
14530         {
14531                 debug_warning("trying to block pad(video)");
14532 //              if (!gst_pad_set_blocked (src_pad_dec, TRUE))
14533                 gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
14534                         NULL, NULL, NULL);
14535
14536                 {
14537                         debug_error("failed to set block pad(video)");
14538                         return MM_ERROR_PLAYER_INTERNAL;
14539                 }
14540                 debug_warning("pad is blocked(video)");
14541         }
14542         else
14543         {
14544                 /* no data flows, so no need to do pad_block */
14545                 if (player->doing_seek) {
14546                         debug_warning("not completed seek(%d), do nothing", player->doing_seek);
14547                 }
14548                 debug_log("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
14549         }
14550
14551         /* remove pad */
14552         if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
14553                 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin))))
14554         {
14555                 debug_error("failed to remove previous ghost_pad for videobin");
14556                 return MM_ERROR_PLAYER_INTERNAL;
14557         }
14558
14559         /* change state of videobin to NULL */
14560         debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
14561         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
14562         if (ret != GST_STATE_CHANGE_SUCCESS)
14563         {
14564                 debug_error("failed to change state of videobin to NULL");
14565                 return MM_ERROR_PLAYER_INTERNAL;
14566         }
14567
14568         /* unlink between decoder and videobin and remove previous videosink from videobin */
14569         GST_ELEMENT_UNLINK(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst),GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
14570         if ( !gst_bin_remove (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst)) )
14571         {
14572                 debug_error("failed to remove former videosink from videobin");
14573                 return MM_ERROR_PLAYER_INTERNAL;
14574         }
14575
14576         __mmplayer_del_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
14577
14578         /* create a new videosink and add it to videobin */
14579         player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, videosink_element);
14580         gst_bin_add (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
14581         __mmplayer_add_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
14582         g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
14583
14584         /* save attributes */
14585         if (player->attrs)
14586         {
14587                 /* set a new display surface type */
14588                 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
14589                 /* set a new diplay overlay */
14590                 switch (surface_type)
14591                 {
14592                         case MM_DISPLAY_SURFACE_X:
14593                                 debug_log("save attributes related to display surface to X : xid = %d", *(int*)display_overlay);
14594                                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
14595                                 break;
14596                         case MM_DISPLAY_SURFACE_EVAS:
14597                                 debug_log("save attributes related to display surface to EVAS : evas image object = %x", display_overlay);
14598                                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(void*));
14599                                 break;
14600                         default:
14601                                 debug_error("invalid type(%d) for changing display surface",surface_type);
14602                                 MMPLAYER_FLEAVE();
14603                                 return MM_ERROR_INVALID_ARGUMENT;
14604                 }
14605                 if ( mmf_attrs_commit ( player->attrs ) )
14606                 {
14607                         debug_error("failed to commit");
14608                         MMPLAYER_FLEAVE();
14609                         return MM_ERROR_PLAYER_INTERNAL;
14610                 }
14611         }
14612         else
14613         {
14614                 debug_error("player->attrs is null, failed to save attributes");
14615                 MMPLAYER_FLEAVE();
14616                 return MM_ERROR_PLAYER_INTERNAL;
14617         }
14618
14619         /* update video param */
14620         if ( MM_ERROR_NONE != _mmplayer_update_video_param( player ) )
14621         {
14622                 debug_error("failed to update video param");
14623                 return MM_ERROR_PLAYER_INTERNAL;
14624         }
14625
14626         /* change state of videobin to READY */
14627         debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
14628         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
14629         if (ret != GST_STATE_CHANGE_SUCCESS)
14630         {
14631                 debug_error("failed to change state of videobin to READY");
14632                 return MM_ERROR_PLAYER_INTERNAL;
14633         }
14634
14635         /* change ghostpad */
14636         sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
14637         if ( !sink_pad_videosink )
14638         {
14639                 debug_error("failed to get sink pad from videosink element");
14640                 return MM_ERROR_PLAYER_INTERNAL;
14641         }
14642         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
14643         if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE))
14644         {
14645                 debug_error("failed to set active to ghost_pad");
14646                 return MM_ERROR_PLAYER_INTERNAL;
14647         }
14648         if ( FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
14649         {
14650                 debug_error("failed to change ghostpad for videobin");
14651                 return MM_ERROR_PLAYER_INTERNAL;
14652         }
14653         gst_object_unref(sink_pad_videosink);
14654
14655         /* link decoder with videobin */
14656         sink_pad_videobin = gst_element_get_static_pad( GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
14657         if ( !sink_pad_videobin )
14658         {
14659                 debug_error("failed to get sink pad from videobin");
14660                 return MM_ERROR_PLAYER_INTERNAL;
14661         }
14662         if ( GST_PAD_LINK_OK != GST_PAD_LINK(src_pad_dec, sink_pad_videobin) )
14663         {
14664                 debug_error("failed to link");
14665                 return MM_ERROR_PLAYER_INTERNAL;
14666         }
14667         gst_object_unref(sink_pad_videobin);
14668
14669         /* clock setting for a new videosink plugin */
14670         /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
14671                         so we set it from audiosink plugin or pipeline(system clock) */
14672         if (!is_audiobin_created)
14673         {
14674                 debug_warning("audiobin is not created, get clock from pipeline..");
14675                 clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
14676         }
14677         else
14678         {
14679                 clock = GST_ELEMENT_CLOCK (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
14680         }
14681         if (clock)
14682         {
14683                 GstClockTime now;
14684                 GstClockTime base_time;
14685                 debug_log("set the clock to videosink");
14686                 gst_element_set_clock (GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
14687                 clock = GST_ELEMENT_CLOCK (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
14688                 if (clock)
14689                 {
14690                         debug_log("got clock of videosink");
14691                         now = gst_clock_get_time ( clock );
14692                         base_time = GST_ELEMENT_CAST (player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
14693                         debug_log ("at time %" GST_TIME_FORMAT ", base %"
14694                                         GST_TIME_FORMAT, GST_TIME_ARGS (now), GST_TIME_ARGS (base_time));
14695                 }
14696                 else
14697                 {
14698                         debug_error("failed to get clock of videosink after setting clock");
14699                         return MM_ERROR_PLAYER_INTERNAL;
14700                 }
14701         }
14702         else
14703         {
14704                 debug_warning("failed to get clock, maybe it is the time before first playing");
14705         }
14706
14707         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
14708         {
14709                 /* change state of videobin to PAUSED */
14710                 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
14711                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
14712                 if (ret != GST_STATE_CHANGE_FAILURE)
14713                 {
14714                         debug_warning("change state of videobin to PLAYING, ret(%d)", ret);
14715                 }
14716                 else
14717                 {
14718                         debug_error("failed to change state of videobin to PLAYING");
14719                         return MM_ERROR_PLAYER_INTERNAL;
14720                 }
14721
14722                 /* release blocked and unref src pad of video decoder */
14723                 #if 0
14724                 if (!gst_pad_set_blocked (src_pad_dec, FALSE))
14725                 {
14726                         debug_error("failed to set pad blocked FALSE(video)");
14727                         return MM_ERROR_PLAYER_INTERNAL;
14728                 }
14729                 #endif
14730                 debug_warning("pad is unblocked(video)");
14731         }
14732         else
14733         {
14734                 if (player->doing_seek) {
14735                         debug_warning("not completed seek(%d)", player->doing_seek);
14736                 }
14737                 /* change state of videobin to PAUSED */
14738                 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
14739                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
14740                 if (ret != GST_STATE_CHANGE_FAILURE)
14741                 {
14742                         debug_warning("change state of videobin to PAUSED, ret(%d)", ret);
14743                 }
14744                 else
14745                 {
14746                         debug_error("failed to change state of videobin to PLAYING");
14747                         return MM_ERROR_PLAYER_INTERNAL;
14748                 }
14749
14750                 /* already skipped pad block */
14751                 debug_log("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
14752         }
14753
14754         /* do get/set position for new videosink plugin */
14755         {
14756                 unsigned long position = 0;
14757                 gint64 pos_msec = 0;
14758
14759                 debug_log("do get/set position for new videosink plugin");
14760                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
14761                 {
14762                         debug_error("failed to get position");
14763                         return MM_ERROR_PLAYER_INTERNAL;
14764                 }
14765 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
14766                 /* accurate seek */
14767                 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE ))
14768                 {
14769                         debug_error("failed to set position");
14770                         return MM_ERROR_PLAYER_INTERNAL;
14771                 }
14772 #else
14773                 /* key unit seek */
14774                 pos_msec = position * G_GINT64_CONSTANT(1000000);
14775                 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
14776                                 GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT ),
14777                                                         GST_SEEK_TYPE_SET, pos_msec,
14778                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
14779                 if ( !ret  )
14780                 {
14781                         debug_error("failed to set position");
14782                         return MM_ERROR_PLAYER_INTERNAL;
14783                 }
14784 #endif
14785         }
14786
14787         if (src_pad_dec)
14788         {
14789                 gst_object_unref (src_pad_dec);
14790         }
14791         debug_log("success to change sink");
14792
14793         MMPLAYER_FLEAVE();
14794
14795         return MM_ERROR_NONE;
14796 }
14797
14798
14799 /* Note : if silent is true, then subtitle would not be displayed. :*/
14800 int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent)
14801 {
14802         mm_player_t* player = (mm_player_t*) hplayer;
14803
14804         MMPLAYER_FENTER();
14805
14806         /* check player handle */
14807         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14808
14809         player->set_mode.subtitle_off = silent;
14810
14811         debug_log("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
14812
14813         MMPLAYER_FLEAVE();
14814
14815         return MM_ERROR_NONE;
14816 }
14817
14818 int _mmplayer_remove_audio_parser_decoder(mm_player_t* player,GstPad *inpad)
14819 {
14820         int result = MM_ERROR_NONE;
14821         GstPad *peer = NULL,*pad = NULL;
14822         GstElement *Element = NULL;
14823         MMPlayerGstElement* mainbin = NULL;
14824         mainbin = player->pipeline->mainbin;
14825
14826         #if 0
14827         if(!gst_pad_set_blocked(inpad,TRUE))
14828         {
14829                 result = MM_ERROR_PLAYER_INTERNAL;
14830                 goto EXIT;
14831         }
14832         #endif
14833         gst_pad_add_probe(inpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
14834                         NULL, NULL, NULL);
14835
14836         /*Getting pad connected to demuxer audio pad */
14837         peer = gst_pad_get_peer(inpad);
14838         /* Disconnecting Demuxer and its peer plugin [audio] */
14839         if(peer)
14840         {
14841                 if(!gst_pad_unlink(inpad,peer))
14842                 {
14843                         result = MM_ERROR_PLAYER_INTERNAL;
14844                         goto EXIT;
14845                 }
14846         }
14847         else
14848         {
14849                 result = MM_ERROR_PLAYER_INTERNAL;
14850                 goto EXIT;
14851         }
14852         /*Removing elements between Demuxer and audiobin*/
14853         while(peer != NULL)
14854         {
14855                 gchar *Element_name = NULL;
14856                 gchar *factory_name = NULL;
14857                 GList *elements = NULL;
14858                 GstElementFactory *factory = NULL;
14859                 /*Getting peer element*/
14860                 Element = gst_pad_get_parent_element(peer);
14861                 if(Element == NULL)
14862                 {
14863                         gst_object_unref(peer);
14864                         result = MM_ERROR_PLAYER_INTERNAL;
14865                         break;
14866                 }
14867
14868                 Element_name = gst_element_get_name(Element);
14869                 factory = gst_element_get_factory(Element);
14870                 /*checking the element is audio bin*/
14871                 if(!strcmp(Element_name,"audiobin"))
14872                 {
14873                         gst_object_unref(peer);
14874                         result = MM_ERROR_NONE;
14875             g_free(Element_name);
14876                         break;
14877                 }
14878                 factory_name = GST_OBJECT_NAME(factory);
14879                 pad = gst_element_get_static_pad(Element,"src");
14880                 if(pad == NULL)
14881                 {
14882                         result = MM_ERROR_PLAYER_INTERNAL;
14883             g_free(Element_name);
14884                         break;
14885                 }
14886                 gst_object_unref(peer);
14887                 peer = gst_pad_get_peer(pad);
14888                 if(peer)
14889                 {
14890                         if(!gst_pad_unlink(pad,peer))
14891                         {
14892                                 gst_object_unref(peer);
14893                                 gst_object_unref(pad);
14894                                 result = MM_ERROR_PLAYER_INTERNAL;
14895                 g_free(Element_name);
14896                                 break;
14897                         }
14898                 }
14899                 elements = player->parsers;
14900                 /* Removing the element form the list*/
14901                 for ( ; elements; elements = g_list_next(elements))
14902                 {
14903                         Element_name = elements->data;
14904                         if(g_strrstr(Element_name,factory_name))
14905                         {
14906                                 player->parsers = g_list_remove(player->parsers,elements->data);
14907                         }
14908                 }
14909                 gst_element_set_state(Element,GST_STATE_NULL);
14910                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),Element);
14911                 gst_object_unref(pad);
14912                 if(Element == mainbin[MMPLAYER_M_Q1].gst)
14913                 {
14914                         mainbin[MMPLAYER_M_Q1].gst = NULL;
14915                 }
14916                 else if(Element == mainbin[MMPLAYER_M_Q2].gst)
14917                 {
14918                         mainbin[MMPLAYER_M_Q2].gst = NULL;
14919                 }
14920                 else if(Element == mainbin[MMPLAYER_M_DEC1].gst)
14921                 {
14922                         mainbin[MMPLAYER_M_DEC1].gst = NULL;
14923                 }
14924                 else if(Element == mainbin[MMPLAYER_M_DEC2].gst)
14925                 {
14926                         mainbin[MMPLAYER_M_DEC2].gst = NULL;
14927                 }
14928                 gst_object_unref(Element);
14929         }
14930 EXIT:
14931         return result;
14932 }
14933
14934 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
14935 {
14936         MMPlayerGstElement* mainbin = NULL;
14937         MMPlayerGstElement* textbin = NULL;
14938         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
14939         GstState current_state = GST_STATE_VOID_PENDING;
14940         GstState element_state = GST_STATE_VOID_PENDING;
14941         GstState element_pending_state = GST_STATE_VOID_PENDING;
14942         gint64 time = 0;
14943         GstEvent *event = NULL;
14944         int result = MM_ERROR_NONE;
14945
14946         GstClock *curr_clock = NULL;
14947         GstClockTime base_time, start_time, curr_time;
14948
14949
14950         MMPLAYER_FENTER();
14951
14952         /* check player handle */
14953         return_val_if_fail ( player && player->pipeline , MM_ERROR_PLAYER_NOT_INITIALIZED);
14954
14955         if (!(player->pipeline->mainbin) || !(player->pipeline->textbin))
14956         {
14957                 debug_error("Pipeline is not in proper state\n");
14958                 result = MM_ERROR_PLAYER_NOT_INITIALIZED;
14959                 goto EXIT;
14960         }
14961
14962         mainbin = player->pipeline->mainbin;
14963         textbin = player->pipeline->textbin;
14964
14965         current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
14966
14967         // sync clock with current pipeline
14968         curr_clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
14969         curr_time = gst_clock_get_time (curr_clock);
14970
14971         base_time = gst_element_get_base_time (GST_ELEMENT_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
14972         start_time = gst_element_get_start_time (GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
14973
14974         debug_log ("base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
14975                 GST_TIME_ARGS (base_time), GST_TIME_ARGS (start_time), GST_TIME_ARGS (curr_time));
14976
14977         if (current_state > GST_STATE_READY)
14978         {
14979                 // sync state with current pipeline
14980                 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
14981                 gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_PAUSED);
14982                 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
14983
14984                 ret = gst_element_get_state (mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
14985                 if ( GST_STATE_CHANGE_FAILURE == ret )
14986                 {
14987                         debug_error("fail to state change.\n");
14988                 }
14989         }
14990
14991         gst_element_set_base_time (textbin[MMPLAYER_T_BIN].gst, base_time);
14992         gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
14993
14994         if (curr_clock)
14995         {
14996                 gst_element_set_clock (textbin[MMPLAYER_T_BIN].gst, curr_clock);
14997                 gst_object_unref (curr_clock);
14998         }
14999
15000         // seek to current position
15001         if (!gst_element_query_position (mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time))
15002         {
15003                 result = MM_ERROR_PLAYER_INVALID_STATE;
15004                 debug_error("gst_element_query_position failed, invalid state\n");
15005                 goto EXIT;
15006         }
15007
15008         debug_log("seek time = %lld\n", time);
15009         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);
15010         if (event)
15011         {
15012                 __gst_send_event_to_sink(player, event);
15013         }
15014         else
15015         {
15016                 result = MM_ERROR_PLAYER_INTERNAL;
15017                 debug_error("gst_event_new_seek failed\n");
15018                 goto EXIT;
15019         }
15020
15021         // sync state with current pipeline
15022         gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
15023         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
15024         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
15025
15026 EXIT:
15027         return result;
15028 }
15029
15030 static int
15031 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
15032 {
15033         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
15034         GstState current_state = GST_STATE_VOID_PENDING;
15035
15036         MMHandleType attrs = 0;
15037         MMPlayerGstElement* mainbin = NULL;
15038         MMPlayerGstElement* textbin = NULL;
15039
15040         gchar* subtitle_uri = NULL;
15041         int result = MM_ERROR_NONE;
15042         const gchar *charset = NULL;
15043
15044         MMPLAYER_FENTER();
15045
15046         /* check player handle */
15047         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15048         return_val_if_fail( filepath, MM_ERROR_COMMON_INVALID_ARGUMENT );
15049
15050         if (!(player->pipeline) || !(player->pipeline->mainbin))
15051         {
15052                 result = MM_ERROR_PLAYER_INVALID_STATE;
15053                 debug_error("Pipeline is not in proper state\n");
15054                 goto EXIT;
15055         }
15056
15057         mainbin = player->pipeline->mainbin;
15058         textbin = player->pipeline->textbin;
15059
15060         current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
15061         if (current_state < GST_STATE_READY)
15062         {
15063                 result = MM_ERROR_PLAYER_INVALID_STATE;
15064                 debug_error("Pipeline is not in proper state\n");
15065                 goto EXIT;
15066         }
15067
15068         attrs = MMPLAYER_GET_ATTRS(player);
15069         if (!attrs)
15070         {
15071                 debug_error("cannot get content attribute\n");
15072                 result = MM_ERROR_PLAYER_INTERNAL;
15073                 goto EXIT;
15074         }
15075
15076         mm_attrs_get_string_by_name (attrs, "subtitle_uri", &subtitle_uri);
15077         if (!subtitle_uri || strlen(subtitle_uri) < 1)
15078         {
15079                 debug_error("subtitle uri is not proper filepath\n");
15080                 result = MM_ERROR_PLAYER_INVALID_URI;
15081                 goto EXIT;
15082         }
15083
15084         debug_log("old subtitle file path is [%s]\n", subtitle_uri);
15085         debug_log("new subtitle file path is [%s]\n", filepath);
15086
15087         if (!strcmp (filepath, subtitle_uri))
15088         {
15089                 debug_log("No need to swtich subtitle, as input filepath is same as current filepath\n");
15090                 goto EXIT;
15091         }
15092         else
15093         {
15094                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
15095                 if (mmf_attrs_commit(player->attrs))
15096                 {
15097                         debug_error("failed to commit.\n");
15098                         goto EXIT;
15099                 }
15100         }
15101
15102         //gst_pad_set_blocked_async(src-srcpad, TRUE)
15103
15104         ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
15105         if (ret != GST_STATE_CHANGE_SUCCESS)
15106         {
15107                 debug_error("failed to change state of textbin to READY");
15108                 result = MM_ERROR_PLAYER_INTERNAL;
15109                 goto EXIT;
15110         }
15111
15112         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_READY);
15113         if (ret != GST_STATE_CHANGE_SUCCESS)
15114         {
15115                 debug_error("failed to change state of subparse to READY");
15116                 result = MM_ERROR_PLAYER_INTERNAL;
15117                 goto EXIT;
15118         }
15119
15120         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
15121         if (ret != GST_STATE_CHANGE_SUCCESS)
15122         {
15123                 debug_error("failed to change state of filesrc to READY");
15124                 result = MM_ERROR_PLAYER_INTERNAL;
15125                 goto EXIT;
15126         }
15127
15128         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
15129
15130         charset = util_get_charset(filepath);
15131         if (charset)
15132         {
15133                 debug_log ("detected charset is %s\n", charset );
15134                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
15135         }
15136
15137         result = _mmplayer_sync_subtitle_pipeline(player);
15138
15139 EXIT:
15140         MMPLAYER_FLEAVE();
15141         return result;
15142 }
15143
15144 /* API to switch between external subtitles */
15145 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
15146 {
15147         int result = MM_ERROR_NONE;
15148         mm_player_t* player = (mm_player_t*)hplayer;
15149
15150         MMPLAYER_FENTER();
15151
15152         /* check player handle */
15153         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15154
15155         if (!player->pipeline)  // IDLE state
15156         {
15157                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
15158                 if (mmf_attrs_commit(player->attrs))
15159                 {
15160                         debug_error("failed to commit.\n");
15161                         result= MM_ERROR_PLAYER_INTERNAL;
15162                 }
15163         }
15164         else    // curr state <> IDLE (READY, PAUSE, PLAYING..)
15165         {
15166                 if ( filepath == NULL )
15167                         return MM_ERROR_COMMON_INVALID_ARGUMENT;
15168
15169                 if (!__mmplayer_check_subtitle(player))
15170                 {
15171                         mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
15172                         if (mmf_attrs_commit(player->attrs))
15173                         {
15174                                 debug_error("failed to commit.\n");
15175                                 result = MM_ERROR_PLAYER_INTERNAL;
15176                         }
15177
15178                         if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
15179                                 debug_error("fail to create subtitle src\n");
15180
15181                         result = _mmplayer_sync_subtitle_pipeline(player);
15182                 }
15183                 else
15184                 {
15185                         result = __mmplayer_change_external_subtitle_language(player, filepath);
15186                 }
15187         }
15188
15189         MMPLAYER_FLEAVE();
15190         return result;
15191 }
15192
15193 static int
15194 __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index)
15195 {
15196         int result = MM_ERROR_NONE;
15197         gchar* change_pad_name = NULL;
15198         GstPad* sinkpad = NULL;
15199         MMPlayerGstElement* mainbin = NULL;
15200         enum MainElementID elemId = MMPLAYER_M_NUM;
15201         GstCaps* caps = NULL;
15202         gint total_track_num = 0;
15203
15204         MMPLAYER_FENTER();
15205
15206         return_val_if_fail (player && player->pipeline && player->pipeline->mainbin,
15207                                                                                                         MM_ERROR_PLAYER_NOT_INITIALIZED);
15208
15209         debug_log ("Change Track(%d) to %d\n", type, index);
15210
15211         mainbin = player->pipeline->mainbin;
15212
15213         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
15214         {
15215                 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
15216         }
15217         else if (type == MM_PLAYER_TRACK_TYPE_TEXT)
15218         {
15219                 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
15220         }
15221         else
15222         {
15223                 debug_error ("Track Type Error\n");
15224                 goto EXIT;
15225         }
15226
15227         if (mainbin[elemId].gst == NULL)
15228         {
15229                 result = MM_ERROR_PLAYER_NO_OP;
15230                 debug_log ("Req track doesn't exist\n");
15231                 goto EXIT;
15232         }
15233
15234         total_track_num = player->selector[type].total_track_num;
15235         if (total_track_num <= 0)
15236         {
15237                 result = MM_ERROR_PLAYER_NO_OP;
15238                 debug_log ("Language list is not available \n");
15239                 goto EXIT;
15240         }
15241
15242         if ((index < 0) || (index >= total_track_num))
15243         {
15244                 result = MM_ERROR_INVALID_ARGUMENT;
15245                 debug_log ("Not a proper index : %d \n", index);
15246                 goto EXIT;
15247         }
15248
15249         /*To get the new pad from the selector*/
15250         change_pad_name = g_strdup_printf ("sink_%u", index);
15251         if (change_pad_name == NULL)
15252         {
15253                 result = MM_ERROR_PLAYER_INTERNAL;
15254                 debug_log ("Pad does not exists\n");
15255                 goto EXIT;
15256         }
15257
15258         debug_log ("new active pad name: %s\n", change_pad_name);
15259
15260         sinkpad = gst_element_get_static_pad (mainbin[elemId].gst, change_pad_name);
15261         if (sinkpad == NULL)
15262         {
15263                 debug_log ("sinkpad is NULL");
15264                 result = MM_ERROR_PLAYER_INTERNAL;
15265                 goto EXIT;
15266         }
15267
15268         debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
15269         g_object_set (mainbin[elemId].gst, "active-pad", sinkpad, NULL);
15270
15271         caps = gst_pad_get_current_caps(sinkpad);
15272         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
15273
15274         if (sinkpad)
15275                 gst_object_unref (sinkpad);
15276
15277         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
15278         {
15279                 __mmplayer_set_audio_attrs (player, caps);
15280         }
15281
15282 EXIT:
15283
15284         MMPLAYER_FREEIF(change_pad_name);
15285         return result;
15286 }
15287
15288 int _mmplayer_change_track_language (MMHandleType hplayer, MMPlayerTrackType type, int index)
15289 {
15290         int result = MM_ERROR_NONE;
15291         mm_player_t* player = NULL;
15292         MMPlayerGstElement* mainbin = NULL;
15293
15294         gint current_active_index = 0;
15295
15296         GstState current_state = GST_STATE_VOID_PENDING;
15297         GstEvent* event = NULL;
15298         gint64 time = 0;
15299
15300         MMPLAYER_FENTER();
15301
15302         player = (mm_player_t*)hplayer;
15303         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15304
15305         if (!player->pipeline)
15306         {
15307                 debug_error ("Track %d pre setting -> %d\n", type, index);
15308
15309                 player->selector[type].active_pad_index = index;
15310                 goto EXIT;
15311         }
15312
15313         mainbin = player->pipeline->mainbin;
15314
15315         current_active_index = player->selector[type].active_pad_index;
15316
15317         /*If index is same as running index no need to change the pad*/
15318         if (current_active_index == index)
15319         {
15320                 goto EXIT;
15321         }
15322
15323         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time))
15324         {
15325                 result = MM_ERROR_PLAYER_INVALID_STATE;
15326                 goto EXIT;
15327         }
15328
15329         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
15330         if (current_state < GST_STATE_PAUSED)
15331         {
15332                 result = MM_ERROR_PLAYER_INVALID_STATE;
15333                 debug_warning ("Pipeline not in porper state\n");
15334                 goto EXIT;
15335         }
15336
15337         result = __mmplayer_change_selector_pad(player, type, index);
15338         if (result != MM_ERROR_NONE)
15339         {
15340                 debug_error ("change selector pad error\n");
15341                 goto EXIT;
15342         }
15343
15344         player->selector[type].active_pad_index = index;
15345
15346         if (current_state == GST_STATE_PLAYING)
15347         {
15348                 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);
15349                 if (event)
15350                 {
15351                         __gst_send_event_to_sink (player, event);
15352                 }
15353                 else
15354                 {
15355                         result = MM_ERROR_PLAYER_INTERNAL;
15356                         goto EXIT;
15357                 }
15358         }
15359
15360 EXIT:
15361         return result;
15362 }
15363
15364 int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent)
15365 {
15366         mm_player_t* player = (mm_player_t*) hplayer;
15367
15368         MMPLAYER_FENTER();
15369
15370         /* check player handle */
15371         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15372
15373         *silent = player->set_mode.subtitle_off;
15374
15375         debug_log("subtitle is %s.\n", silent ? "ON" : "OFF");
15376
15377         MMPLAYER_FLEAVE();
15378
15379         return MM_ERROR_NONE;
15380 }
15381
15382 gboolean
15383 __is_es_buff_src( mm_player_t* player )
15384 {
15385         return_val_if_fail ( player, FALSE );
15386
15387         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF) ? TRUE : FALSE;
15388 }
15389
15390 gboolean
15391 __has_suffix(mm_player_t* player, const gchar* suffix)
15392 {
15393         return_val_if_fail( player, FALSE );
15394         return_val_if_fail( suffix, FALSE );
15395
15396         gboolean ret = FALSE;
15397         gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
15398         gchar* t_suffix = g_ascii_strdown(suffix, -1);
15399
15400         if ( g_str_has_suffix(player->profile.uri, suffix) )
15401         {
15402                 ret = TRUE;
15403         }
15404
15405         MMPLAYER_FREEIF(t_url);
15406         MMPLAYER_FREEIF(t_suffix);
15407
15408         return ret;
15409 }
15410
15411 int
15412 _mmplayer_set_display_zoom(MMHandleType hplayer, float level, int x, int y)
15413 {
15414         mm_player_t* player = (mm_player_t*) hplayer;
15415
15416         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15417
15418         MMPLAYER_VIDEO_SINK_CHECK(player);
15419
15420         debug_log("setting display zoom level = %f, offset = %d, %d", level, x, y);
15421
15422         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", level, "zoom-pos-x", x, "zoom-pos-y", y, NULL);
15423
15424         return MM_ERROR_NONE;
15425 }
15426 int
15427 _mmplayer_get_display_zoom(MMHandleType hplayer, float *level, int *x, int *y)
15428 {
15429
15430         mm_player_t* player = (mm_player_t*) hplayer;
15431         float _level = 0.0;
15432         int _x = 0;
15433         int _y = 0;
15434
15435         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15436
15437         MMPLAYER_VIDEO_SINK_CHECK(player);
15438
15439         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", &_level, "zoom-pos-x", &_x, "zoom-pos-y", &_y, NULL);
15440
15441         debug_log("display zoom level = %f, start off x = %d, y = %d", _level, _x, _y);
15442
15443         *level = _level;
15444         *x = _x;
15445         *y = _y;
15446
15447         return MM_ERROR_NONE;
15448 }
15449
15450 int
15451 _mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
15452 {
15453         mm_player_t* player = (mm_player_t*) hplayer;
15454
15455         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15456
15457         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL)
15458         {
15459                 MMPLAYER_PRINT_STATE(player);
15460                 debug_error("wrong-state : can't set the download mode to parse");
15461                 return MM_ERROR_PLAYER_INVALID_STATE;
15462         }
15463
15464         debug_log("set video hub download mode to %s", (mode)?"ON":"OFF");
15465         player->video_hub_download_mode = mode;
15466
15467         return MM_ERROR_NONE;
15468 }
15469
15470 int
15471 _mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
15472 {
15473         mm_player_t* player = (mm_player_t*) hplayer;
15474
15475         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15476
15477         debug_log("enable sync handler : %s", (enable)?"ON":"OFF");
15478         player->sync_handler = enable;
15479
15480         return MM_ERROR_NONE;
15481 }
15482
15483 int
15484 _mmplayer_set_video_share_master_clock( MMHandleType hplayer,
15485                                         long long clock,
15486                                         long long clock_delta,
15487                                         long long video_time,
15488                                         long long media_clock,
15489                                         long long audio_time)
15490 {
15491         mm_player_t* player = (mm_player_t*) hplayer;
15492         MMPlayerGstElement* mainbin = NULL;
15493         GstClockTime start_time_audio = 0, start_time_video = 0;
15494         GstClockTimeDiff base_time = 0, new_base_time = 0;
15495         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
15496         gint64 api_delta = 0;
15497         gint64 position = 0, position_delta = 0;
15498         gint64 adj_base_time = 0;
15499         GstClock *curr_clock = NULL;
15500         GstClockTime curr_time = 0;
15501         gboolean query_ret = TRUE;
15502         int result = MM_ERROR_NONE;
15503
15504         MMPLAYER_FENTER();
15505
15506         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
15507         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
15508         return_val_if_fail ( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
15509
15510         // debug_log("in(us) : %lld, %lld, %lld, %lld, %lld", clock, clock_delta, video_time, media_clock, audio_time);
15511
15512         if ((video_time < 0) || (player->doing_seek))
15513         {
15514                 debug_log("skip setting master clock.  %lld", video_time);
15515                 goto EXIT;
15516         }
15517
15518         mainbin = player->pipeline->mainbin;
15519
15520         curr_clock = gst_pipeline_get_clock (GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
15521         curr_time = gst_clock_get_time (curr_clock);
15522
15523         current_state = MMPLAYER_CURRENT_STATE(player);
15524
15525         if ( current_state == MM_PLAYER_STATE_PLAYING )
15526                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
15527
15528         if ( ( current_state != MM_PLAYER_STATE_PLAYING ) ||
15529                  ( !query_ret ))
15530         {
15531                 position = player->last_position;
15532                 debug_log ("query fail. %lld", position);
15533         }
15534
15535         clock*= GST_USECOND;
15536         clock_delta *= GST_USECOND;
15537
15538         api_delta = clock - curr_time;
15539         if ((player->video_share_api_delta == 0 ) || (player->video_share_api_delta > api_delta))
15540         {
15541                 player->video_share_api_delta = api_delta;
15542         }
15543         else
15544         {
15545                 clock_delta += (api_delta - player->video_share_api_delta);
15546         }
15547
15548         if ((player->video_share_clock_delta == 0 ) || (player->video_share_clock_delta > clock_delta))
15549         {
15550                 player->video_share_clock_delta = (gint64)clock_delta;
15551
15552                 position_delta = (position/GST_USECOND) - video_time;
15553                 position_delta *= GST_USECOND;
15554
15555                 adj_base_time = position_delta;
15556                 debug_log ("video_share_clock_delta = %lld, adj = %lld", player->video_share_clock_delta, adj_base_time);
15557
15558         }
15559         else
15560         {
15561                 gint64 new_play_time = 0;
15562                 gint64 network_delay =0;
15563
15564                 video_time *= GST_USECOND;
15565
15566                 network_delay = clock_delta - player->video_share_clock_delta;
15567                 new_play_time = video_time + network_delay;
15568
15569                 adj_base_time = position - new_play_time;
15570
15571                 debug_log ("%lld(delay) = %lld - %lld / %lld(adj) = %lld(slave_pos) - %lld(master_pos) - %lld(delay)",
15572                         network_delay, clock_delta, player->video_share_clock_delta, adj_base_time, position, video_time, network_delay);
15573         }
15574
15575         /* Adjust Current Stream Time with base_time of sink
15576          * 1. Set Start time to CLOCK NONE, to control the base time by MSL
15577          * 2. Set new base time
15578          *    if adj_base_time is positive value, the stream time will be decreased.
15579          * 3. If seek event is occurred, the start time will be reset. */
15580         if ((player->pipeline->audiobin) &&
15581                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
15582         {
15583                 start_time_audio = gst_element_get_start_time (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
15584
15585                 if (start_time_audio != GST_CLOCK_TIME_NONE)
15586                 {
15587                         debug_log ("audio sink : gst_element_set_start_time -> NONE");
15588                         gst_element_set_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, GST_CLOCK_TIME_NONE);
15589                 }
15590
15591                 base_time = gst_element_get_base_time (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
15592         }
15593
15594         if ((player->pipeline->videobin) &&
15595                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
15596         {
15597                 start_time_video = gst_element_get_start_time (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
15598
15599                 if (start_time_video != GST_CLOCK_TIME_NONE)
15600                 {
15601                         debug_log ("video sink : gst_element_set_start_time -> NONE");
15602                         gst_element_set_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst, GST_CLOCK_TIME_NONE);
15603                 }
15604
15605                 // if videobin exist, get base_time from videobin.
15606                 base_time = gst_element_get_base_time (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
15607         }
15608
15609         new_base_time = base_time + adj_base_time;
15610
15611         if ((player->pipeline->audiobin) &&
15612                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
15613                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), (GstClockTime)new_base_time);
15614
15615         if ((player->pipeline->videobin) &&
15616                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
15617                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), (GstClockTime)new_base_time);
15618
15619 EXIT:
15620         MMPLAYER_FLEAVE();
15621
15622         return result;
15623 }
15624
15625 int
15626 _mmplayer_get_video_share_master_clock( MMHandleType hplayer,
15627                                         long long *video_time,
15628                                         long long *media_clock,
15629                                         long long *audio_time)
15630 {
15631         mm_player_t* player = (mm_player_t*) hplayer;
15632         MMPlayerGstElement* mainbin = NULL;
15633         GstClock *curr_clock = NULL;
15634         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
15635         gint64 position = 0;
15636         gboolean query_ret = TRUE;
15637
15638         MMPLAYER_FENTER();
15639
15640         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
15641         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
15642         return_val_if_fail ( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
15643
15644         return_val_if_fail ( video_time, MM_ERROR_COMMON_INVALID_ARGUMENT );
15645         return_val_if_fail ( media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT );
15646         return_val_if_fail ( audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT );
15647
15648         mainbin = player->pipeline->mainbin;
15649
15650         curr_clock = gst_pipeline_get_clock (GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
15651
15652         current_state = MMPLAYER_CURRENT_STATE(player);
15653
15654         if ( current_state != MM_PLAYER_STATE_PAUSED )
15655                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
15656
15657         if ( ( current_state == MM_PLAYER_STATE_PAUSED ) ||
15658                  ( !query_ret ))
15659         {
15660                 position = player->last_position;
15661         }
15662
15663         *media_clock = *video_time = *audio_time = (position/GST_USECOND);
15664
15665         debug_log("media_clock: %lld, video_time: %lld (us)", *media_clock, *video_time);
15666
15667         if (curr_clock)
15668                 gst_object_unref (curr_clock);
15669
15670         MMPLAYER_FLEAVE();
15671
15672         return MM_ERROR_NONE;
15673 }
15674
15675 int
15676 _mmplayer_get_video_rotate_angle(MMHandleType hplayer, int *angle)
15677 {
15678         mm_player_t* player = (mm_player_t*) hplayer;
15679         int org_angle = 0;
15680
15681         MMPLAYER_FENTER();
15682
15683         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15684         return_val_if_fail ( angle, MM_ERROR_COMMON_INVALID_ARGUMENT );
15685
15686         if (player->v_stream_caps)
15687         {
15688                 GstStructure *str = NULL;
15689
15690                 str = gst_caps_get_structure (player->v_stream_caps, 0);
15691                 if ( !gst_structure_get_int (str, "orientation", &org_angle))
15692                 {
15693                         debug_log ("missing 'orientation' field in video caps");
15694                 }
15695         }
15696
15697         debug_log("orientation: %d", org_angle);
15698         *angle = org_angle;
15699
15700         MMPLAYER_FLEAVE();
15701         return MM_ERROR_NONE;
15702 }
15703
15704 gboolean
15705 __mmplayer_is_streaming(mm_player_t* player)
15706 {
15707         gboolean result = FALSE;
15708
15709         MMPLAYER_FENTER();
15710
15711         return_val_if_fail (player, FALSE);
15712         result = __is_streaming (player) ;
15713
15714         MMPLAYER_FLEAVE();
15715         return result;
15716 }
15717
15718 static gboolean
15719 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
15720 {
15721         return_val_if_fail (player, FALSE);
15722         return_val_if_fail (element, FALSE);
15723
15724         gchar *factory_name = GST_OBJECT_NAME (gst_element_get_factory(element));
15725         gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
15726
15727         int idx = 0;
15728
15729         for ( idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++ )
15730         {
15731                 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx]))
15732                 {
15733                         debug_log("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
15734                         mm_player_dump_t *dump_s;
15735                         dump_s = g_malloc (sizeof(mm_player_dump_t));
15736
15737                         if (dump_s == NULL)
15738                         {
15739                                 debug_error ("malloc fail");
15740                                 return FALSE;
15741                         }
15742
15743                         dump_s->dump_element_file = NULL;
15744                         dump_s->dump_pad = NULL;
15745                         dump_s->dump_pad = gst_element_get_static_pad (element, "sink");
15746
15747                         if (dump_s->dump_pad)
15748                         {
15749                                 memset (dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
15750                                 sprintf (dump_file_name, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
15751                                 dump_s->dump_element_file = fopen(dump_file_name,"w+");
15752                                 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);
15753                                 /* add list for removed buffer probe and close FILE */
15754                                 player->dump_list = g_list_append (player->dump_list, dump_s);
15755                                 debug_log ("%s sink pad added buffer probe for dump", factory_name);
15756                                 return TRUE;
15757                         }
15758                         else
15759                         {
15760                                 g_free(dump_s);
15761                                 dump_s = NULL;
15762                                 debug_error ("failed to get %s sink pad added", factory_name);
15763                         }
15764
15765
15766                 }
15767         }
15768         return FALSE;
15769 }
15770
15771 static GstPadProbeReturn
15772 __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data)
15773 {
15774         FILE *dump_data = (FILE *) u_data;
15775 //      int written = 0;
15776         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
15777         GstMapInfo probe_info = GST_MAP_INFO_INIT;
15778
15779         return_val_if_fail ( dump_data, FALSE );
15780
15781         gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
15782
15783 //      debug_log ("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS( GST_BUFFER_TIMESTAMP(buffer)));
15784
15785         fwrite ( probe_info.data, 1, probe_info.size , dump_data);
15786
15787         return GST_PAD_PROBE_OK;
15788 }
15789
15790 static void
15791 __mmplayer_release_dump_list (GList *dump_list)
15792 {
15793         if (dump_list)
15794         {
15795                 GList *d_list = dump_list;
15796                 for ( ;d_list ; d_list = g_list_next(d_list))
15797                 {
15798                         mm_player_dump_t *dump_s = d_list->data;
15799                         if (dump_s->dump_pad)
15800                         {
15801                                 if (dump_s->probe_handle_id)
15802                                 {
15803                                         gst_pad_remove_probe (dump_s->dump_pad, dump_s->probe_handle_id);
15804                                 }
15805
15806                         }
15807                         if (dump_s->dump_element_file)
15808                         {
15809                                 fclose(dump_s->dump_element_file);
15810                                 dump_s->dump_element_file = NULL;
15811                         }
15812                         MMPLAYER_FREEIF(dump_s);
15813                 }
15814                 g_list_free(dump_list);
15815                 dump_list = NULL;
15816         }
15817 }
15818
15819 int
15820 _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
15821 {
15822         mm_player_t* player = (mm_player_t*) hplayer;
15823
15824         MMPLAYER_FENTER();
15825
15826         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15827         return_val_if_fail ( exist, MM_ERROR_INVALID_ARGUMENT );
15828
15829         *exist = player->has_closed_caption;
15830
15831         MMPLAYER_FLEAVE();
15832
15833         return MM_ERROR_NONE;
15834 }
15835
15836 int
15837 _mmplayer_enable_media_packet_video_stream(MMHandleType hplayer, bool enable)
15838 {
15839         mm_player_t* player = (mm_player_t*) hplayer;
15840
15841         MMPLAYER_FENTER();
15842
15843         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15844         return_val_if_fail (enable == TRUE || enable == FALSE, MM_ERROR_INVALID_ARGUMENT);
15845         if(enable)
15846                 player->bufmgr = tbm_bufmgr_init(-1);
15847         else {
15848                 tbm_bufmgr_deinit(player->bufmgr);
15849                 player->bufmgr = NULL;
15850         }
15851
15852         player->set_mode.media_packet_video_stream = enable;
15853
15854         MMPLAYER_FLEAVE();
15855
15856         return MM_ERROR_NONE;
15857 }
15858
15859 void * _mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer)
15860 {
15861         void * ret = NULL
15862         MMPLAYER_FENTER();
15863         /* increase ref count of gst buffer */
15864         if (buffer)
15865                 ret = gst_buffer_ref((GstBuffer *)buffer);
15866
15867         MMPLAYER_FLEAVE();
15868         return ret;
15869 }
15870
15871 void _mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer)
15872 {
15873         MMPLAYER_FENTER();
15874         if (buffer) {
15875                 gst_buffer_unref((GstBuffer *)buffer);
15876                 buffer = NULL;
15877         }
15878         MMPLAYER_FLEAVE();
15879 }
15880
15881 void
15882 __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data)
15883 {
15884         mm_player_t *player  = (mm_player_t*)user_data;
15885         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
15886
15887         return_if_fail ( player );
15888
15889         debug_msg("app-src: feed audio\n");
15890
15891         if (player->media_stream_buffer_status_cb[type])
15892         {
15893                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
15894         }
15895 }
15896
15897 void
15898 __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data)
15899 {
15900         mm_player_t *player  = (mm_player_t*)user_data;
15901         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
15902
15903         return_if_fail ( player );
15904
15905         debug_msg("app-src: feed video\n");
15906
15907         if (player->media_stream_buffer_status_cb[type])
15908         {
15909                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
15910         }
15911 }
15912
15913 void
15914 __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data)
15915 {
15916         mm_player_t *player  = (mm_player_t*)user_data;
15917         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
15918
15919         return_if_fail ( player );
15920
15921         debug_msg("app-src: feed subtitle\n");
15922
15923         if (player->media_stream_buffer_status_cb[type])
15924         {
15925                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
15926         }
15927 }
15928
15929 void
15930 __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data)
15931 {
15932         mm_player_t *player  = (mm_player_t*)user_data;
15933         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
15934
15935         return_if_fail ( player );
15936
15937         debug_msg("app-src: audio buffer is full.\n");
15938
15939         if (player->media_stream_buffer_status_cb[type])
15940         {
15941                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
15942         }
15943 }
15944
15945 void
15946 __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data)
15947 {
15948         mm_player_t *player  = (mm_player_t*)user_data;
15949         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
15950
15951         return_if_fail ( player );
15952
15953         debug_msg("app-src: video buffer is full.\n");
15954
15955         if (player->media_stream_buffer_status_cb[type])
15956         {
15957                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
15958         }
15959 }
15960
15961 gboolean
15962 __gst_seek_audio_data (GstElement * appsrc, guint64 position, gpointer user_data)
15963 {
15964         mm_player_t *player  = (mm_player_t*)user_data;
15965         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
15966
15967         return_val_if_fail( player, FALSE );
15968
15969         debug_log("app-src: seek audio data\n");
15970
15971         if (player->media_stream_seek_data_cb[type])
15972         {
15973                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
15974         }
15975
15976         return TRUE;
15977 }
15978
15979 gboolean
15980 __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data)
15981 {
15982         mm_player_t *player  = (mm_player_t*)user_data;
15983         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
15984
15985         return_val_if_fail( player, FALSE );
15986
15987         debug_log("app-src: seek video data\n");
15988
15989         if (player->media_stream_seek_data_cb[type])
15990         {
15991                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
15992         }
15993
15994         return TRUE;
15995 }
15996
15997 gboolean
15998 __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data)
15999 {
16000         mm_player_t *player  = (mm_player_t*)user_data;
16001         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
16002
16003         return_val_if_fail( player, FALSE );
16004
16005         debug_log("app-src: seek subtitle data\n");
16006
16007         if (player->media_stream_seek_data_cb[type])
16008         {
16009                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
16010         }
16011
16012         return TRUE;
16013 }
16014
16015 int
16016 _mmplayer_set_pcm_spec(MMHandleType hplayer, int samplerate, int channel)
16017 {
16018         mm_player_t* player = (mm_player_t*) hplayer;
16019
16020         MMPLAYER_FENTER();
16021
16022         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16023
16024         player->pcm_samplerate = samplerate;
16025         player->pcm_channel = channel;
16026
16027         MMPLAYER_FLEAVE();
16028         return MM_ERROR_NONE;
16029 }
16030
16031 int _mmplayer_get_raw_video_caps(mm_player_t *player, char **caps)
16032 {
16033         GstCaps *v_caps = NULL;
16034         GstPad *pad = NULL;
16035         GstElement *gst;
16036         gint stype = 0;
16037
16038         if(!player->videosink_linked) {
16039                 debug_log("No video sink");
16040                 return MM_ERROR_NONE;
16041         }
16042         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
16043
16044         if (stype == MM_DISPLAY_SURFACE_NULL) {
16045                 debug_log("Display type is NULL");
16046                 if(!player->video_fakesink) {
16047                         debug_error("No fakesink");
16048                         return MM_ERROR_PLAYER_INVALID_STATE;
16049                 }
16050                 gst = player->video_fakesink;
16051         }
16052         else {
16053                 if ( !player->pipeline || !player->pipeline->videobin ||
16054                                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst ) {
16055                         debug_error("No video pipeline");
16056                         return MM_ERROR_PLAYER_INVALID_STATE;
16057                 }
16058                 gst = player->pipeline->videobin[MMPLAYER_V_SINK].gst;
16059         }
16060         pad = gst_element_get_static_pad(gst, "sink");
16061         if(!pad) {
16062                 debug_error("static pad is NULL");
16063                 return MM_ERROR_PLAYER_INVALID_STATE;
16064         }
16065         v_caps = gst_pad_get_current_caps(pad);
16066         gst_object_unref( pad );
16067
16068         if(!v_caps) {
16069                 debug_error("fail to get caps");
16070                 return MM_ERROR_PLAYER_INVALID_STATE;
16071         }
16072
16073         *caps = gst_caps_to_string(v_caps);
16074
16075         gst_caps_unref(v_caps);
16076
16077         return MM_ERROR_NONE;
16078 }