to resolve the Prevent issues
[platform/core/multimedia/libmm-player.git] / src / mm_player_priv.c
1 /*
2  * libmm-player
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
7  * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 /*===========================================================================================
24 |                                                                                                                                                                                       |
25 |  INCLUDE FILES                                                                                                                                                        |
26 |                                                                                                                                                                                       |
27 ========================================================================================== */
28 #include <glib.h>
29 #include <gst/gst.h>
30 #include <gst/app/gstappsrc.h>
31 #include <gst/video/videooverlay.h>
32 #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
57 #define MM_SMOOTH_STREAMING
58
59 /*===========================================================================================
60 |                                                                                                                                                                                       |
61 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
62 |                                                                                                                                                                                       |
63 ========================================================================================== */
64
65 /*---------------------------------------------------------------------------
66 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
67 ---------------------------------------------------------------------------*/
68
69 /*---------------------------------------------------------------------------
70 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
71 ---------------------------------------------------------------------------*/
72
73 /*---------------------------------------------------------------------------
74 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
75 ---------------------------------------------------------------------------*/
76
77 /*---------------------------------------------------------------------------
78 |    LOCAL #defines:                                                                                                            |
79 ---------------------------------------------------------------------------*/
80 #define TRICK_PLAY_MUTE_THRESHOLD_MAX   2.0
81 #define TRICK_PLAY_MUTE_THRESHOLD_MIN   0.0
82
83 #define MM_VOLUME_FACTOR_DEFAULT                1.0
84 #define MM_VOLUME_FACTOR_MIN                    0
85 #define MM_VOLUME_FACTOR_MAX                    1.0
86
87 #define MM_PLAYER_FADEOUT_TIME_DEFAULT  700000 // 700 msec
88
89 #define MM_PLAYER_MPEG_VNAME                            "mpegversion"
90 #define MM_PLAYER_DIVX_VNAME                            "divxversion"
91 #define MM_PLAYER_WMV_VNAME                             "wmvversion"
92 #define MM_PLAYER_WMA_VNAME                             "wmaversion"
93
94 #define DEFAULT_PLAYBACK_RATE                   1.0
95 #define PLAYBACK_RATE_EX_AUDIO_MIN              0.5
96 #define PLAYBACK_RATE_EX_AUDIO_MAX              2.0
97 #define PLAYBACK_RATE_EX_VIDEO_MIN              0.5
98 #define PLAYBACK_RATE_EX_VIDEO_MAX              1.5
99
100 #define GST_QUEUE_DEFAULT_TIME                  4
101 #define GST_QUEUE_HLS_TIME                              8
102
103 #define DEFAULT_AUDIO_CH                                0
104
105 #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) )
106
107 #define LAZY_PAUSE_TIMEOUT_MSEC 700
108 #define MM_PLAYER_NAME  "mmplayer"
109
110 #define SMOOTH_STREAMING_DEMUX "mssdemux"
111 /*
112  * g_array_index(a,t,i) does not calculate gst private structure.
113  * It replaces the g_array_index(a,t,i)
114  */
115 #define g_array_undef_struct_idx_p(a,t,i)       ((t *)(void *)((a)->data + ((i) * (a)->len)))
116
117 //#define ENABLE_DRMSRC
118
119 /*---------------------------------------------------------------------------
120 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
121 ---------------------------------------------------------------------------*/
122
123 /*---------------------------------------------------------------------------
124 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
125 ---------------------------------------------------------------------------*/
126
127 /*---------------------------------------------------------------------------
128 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
129 ---------------------------------------------------------------------------*/
130
131 /*---------------------------------------------------------------------------
132 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
133 ---------------------------------------------------------------------------*/
134
135 /*---------------------------------------------------------------------------
136 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
137 ---------------------------------------------------------------------------*/
138 static int              __mmplayer_set_state(mm_player_t* player, int state);
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 gboolean __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data);
148 static GstPadProbeReturn        __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data);
149 static void             __mmplayer_gst_decode_pad_added(GstElement* elem, GstPad* pad, gpointer data);
150 static void     __mmplayer_gst_decode_no_more_pads(GstElement* elem, gpointer data);
151 static void     __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gpointer data);
152 static void             __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad, GstCaps *caps, gpointer data);
153 static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
154 static gint __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad, GstCaps * caps, GstElementFactory* factory, gpointer data);
155 //static GValueArray* __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
156 static GValueArray* __mmplayer_gst_decode_autoplug_sort(GstElement *bin,  GstPad* pad, GstCaps * caps, GValueArray *factories, gpointer data);
157 static void __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad, gpointer data);
158 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
159 static void     __mmplayer_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
160 static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
161 static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
162
163 static void     __mmplayer_typefind_have_type(  GstElement *tf, guint probability, GstCaps *caps, gpointer data);
164 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
165 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
166 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
167 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
168 static gboolean __mmplayer_is_omx_decoder_type(mm_player_t* player); // mp3
169 static void     __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
170 //static void   __mmplayer_check_video_zero_cpoy(mm_player_t* player, GstElementFactory* factory);
171
172 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
173 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
174 static void     __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
175
176 static void             __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data);
177 //static void    __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
178 static void             __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
179 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player );
180 static gboolean __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
181
182
183 static void     __mmplayer_init_factories(mm_player_t* player);
184 static void     __mmplayer_release_factories(mm_player_t* player);
185 static void             __mmplayer_release_misc(mm_player_t* player);
186 static void             __mmplayer_release_misc_post(mm_player_t* player);
187 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
188
189 static int              __mmplayer_gst_set_state (mm_player_t* player, GstElement * pipeline,  GstState state, gboolean async, gint timeout );
190 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
191 static gboolean      __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
192
193 int             __mmplayer_switch_audio_sink (mm_player_t* player);
194 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
195 static int              __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
196 static GstPadProbeReturn __mmplayer_audio_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
197 static GstPadProbeReturn __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
198 static GstPadProbeReturn __mmplayer_subtitle_adjust_position_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
199 static int __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index);
200
201 static gboolean __mmplayer_dump_pipeline_state( mm_player_t* player );
202 static gboolean __mmplayer_check_subtitle( mm_player_t* player );
203 static gboolean __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error );
204 static gboolean __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message );
205 static void             __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms );
206 static void     __mmplayer_cancel_eos_timer( mm_player_t* player );
207 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
208 static gboolean __mmplayer_link_decoder( mm_player_t* player,GstPad *srcpad);
209 static gboolean __mmplayer_link_sink( mm_player_t* player,GstPad *srcpad);
210 static int      __mmplayer_handle_missed_plugin(mm_player_t* player);
211 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
212 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
213 static void     __mmplayer_add_sink( mm_player_t* player, GstElement* sink);
214 static void     __mmplayer_del_sink( mm_player_t* player, GstElement* sink);
215 static void     __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
216 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force);
217 static gpointer __mmplayer_next_play_thread(gpointer data);
218 static gpointer __mmplayer_repeat_thread(gpointer data);
219 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
220
221
222 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
223 //static gboolean __mmplayer_dump_buffer_probe_cb(GstPad *pad, GstBuffer *buffer, gpointer u_data);
224 static void __mmplayer_release_dump_list (GList *dump_list);
225
226 static int              __gst_realize(mm_player_t* player);
227 static int              __gst_unrealize(mm_player_t* player);
228 static int              __gst_start(mm_player_t* player);
229 static int              __gst_stop(mm_player_t* player);
230 static int              __gst_pause(mm_player_t* player, gboolean async);
231 static int              __gst_resume(mm_player_t* player, gboolean async);
232 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
233                                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
234                                         gint64 cur, GstSeekType stop_type, gint64 stop );
235 static int __gst_pending_seek ( mm_player_t* player );
236
237 static int              __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called);
238 static int              __gst_get_position(mm_player_t* player, int format, unsigned long *position);
239 static int              __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
240 static int              __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
241 static int              __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
242
243 static gint     __gst_handle_core_error( mm_player_t* player, int code );
244 static gint     __gst_handle_library_error( mm_player_t* player, int code );
245 static gint     __gst_handle_resource_error( mm_player_t* player, int code );
246 static gint     __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message );
247 static gint             __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error);
248 static gboolean __gst_send_event_to_sink( mm_player_t* player, GstEvent* event );
249
250 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
251 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
252
253 /*fadeout */
254 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
255 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
256
257 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
258 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
259
260 /* util */
261 const gchar * __get_state_name ( int state );
262 static gboolean __is_streaming( mm_player_t* player );
263 static gboolean __is_rtsp_streaming( mm_player_t* player );
264 static gboolean __is_wfd_streaming( mm_player_t* player );
265 static gboolean __is_live_streaming ( mm_player_t* player );
266 static gboolean __is_http_streaming( mm_player_t* player );
267 static gboolean __is_http_live_streaming( mm_player_t* player );
268 static gboolean __is_dash_streaming( mm_player_t* player );
269 static gboolean __is_smooth_streaming( mm_player_t* player );
270 static gboolean __is_http_progressive_down(mm_player_t* player);
271 #ifdef TEST_ES
272 static gboolean __is_es_buff_src(mm_player_t* player);
273 #endif
274 static gboolean __has_suffix(mm_player_t * player, const gchar * suffix);
275
276 static GstBusSyncReply __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data);
277
278 static int  __mmplayer_realize_streaming_ext(mm_player_t* player);
279 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
280 static int __mmplayer_start_streaming_ext(mm_player_t *player);
281 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
282 static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
283 static void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id);
284
285 static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
286 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
287 static void __mmplayer_check_pipeline(mm_player_t* player);
288 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
289 static void __mmplayer_deactivate_old_path(mm_player_t *player);
290 #if 0 // We'll need this in future.
291 static int __mmplayer_gst_switching_element(mm_player_t *player, GstElement *search_from, const gchar *removal_name, const gchar *new_element_name);
292 #endif
293
294 static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg);
295 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
296 static gboolean __mmplayer_can_do_interrupt(mm_player_t *player);
297
298 /* device change post proc */
299 void __mmplayer_device_change_post_process(gpointer user);
300 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score);
301 void __mmplayer_inc_cb_score(mm_player_t* player);
302 void __mmplayer_post_proc_reset(mm_player_t* player);
303 void __mmplayer_device_change_trigger_post_process(mm_player_t* player);
304 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
305 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name);
306
307 #ifdef TEST_ES
308 static void             __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data);
309 static void             __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data);
310 static void     __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data);
311 static void             __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data);
312 static void             __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data);
313 static gboolean __gst_seek_audio_data (GstElement * appsrc, guint64 position, gpointer user_data);
314 static gboolean __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data);
315 static gboolean __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data);
316 #endif
317 /*===========================================================================================
318 |                                                                                                                                                                                       |
319 |  FUNCTION DEFINITIONS                                                                                                                                         |
320 |                                                                                                                                                                                       |
321 ========================================================================================== */
322
323 #if 0 //debug
324 static void
325 print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
326 {
327   gint i, count;
328
329   count = gst_tag_list_get_tag_size (list, tag);
330
331   debug_log("count = %d", count);
332
333   for (i = 0; i < count; i++) {
334     gchar *str;
335
336     if (gst_tag_get_type (tag) == G_TYPE_STRING) {
337       if (!gst_tag_list_get_string_index (list, tag, i, &str))
338         g_assert_not_reached ();
339     } else {
340       str =
341           g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
342     }
343
344     if (i == 0) {
345       g_print ("  %15s: %s\n", gst_tag_get_nick (tag), str);
346     } else {
347       g_print ("                 : %s\n", str);
348     }
349
350     g_free (str);
351   }
352 }
353 #endif
354
355 /* implementing player FSM */
356 /* FIXIT : We need to handle state transition also at here since start api is no more sync */
357 static int
358 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
359 {
360         MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
361         MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
362 //      MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
363 //      MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
364
365         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
366
367         //debug_log("incomming command : %d \n", command );
368
369         current_state = MMPLAYER_CURRENT_STATE(player);
370         pending_state = MMPLAYER_PENDING_STATE(player);
371 //      target_state = MMPLAYER_TARGET_STATE(player);
372 //      prev_state = MMPLAYER_PREV_STATE(player);
373
374         MMPLAYER_PRINT_STATE(player);
375
376         switch( command )
377         {
378                 case MMPLAYER_COMMAND_CREATE:
379                 {
380                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
381
382                         if ( current_state == MM_PLAYER_STATE_NULL ||
383                                 current_state == MM_PLAYER_STATE_READY ||
384                                 current_state == MM_PLAYER_STATE_PAUSED ||
385                                 current_state == MM_PLAYER_STATE_PLAYING )
386                                 goto NO_OP;
387                 }
388                 break;
389
390                 case MMPLAYER_COMMAND_DESTROY:
391                 {
392                         /* destroy can called anytime */
393
394                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
395                 }
396                 break;
397
398                 case MMPLAYER_COMMAND_REALIZE:
399                 {
400                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
401
402                         if ( pending_state != MM_PLAYER_STATE_NONE )
403                         {
404                                 goto INVALID_STATE;
405                         }
406                         else
407                         {
408                                 /* need ready state to realize */
409                                 if ( current_state == MM_PLAYER_STATE_READY )
410                                         goto NO_OP;
411
412                                 if ( current_state != MM_PLAYER_STATE_NULL )
413                                         goto INVALID_STATE;
414                         }
415                 }
416                 break;
417
418                 case MMPLAYER_COMMAND_UNREALIZE:
419                 {
420                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
421
422                         if ( current_state == MM_PLAYER_STATE_NULL )
423                                 goto NO_OP;
424                 }
425                 break;
426
427                 case MMPLAYER_COMMAND_START:
428                 {
429                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
430
431                         if ( pending_state == MM_PLAYER_STATE_NONE )
432                         {
433                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
434                                         goto NO_OP;
435                                 else if ( current_state  != MM_PLAYER_STATE_READY &&
436                                         current_state != MM_PLAYER_STATE_PAUSED )
437                                         goto INVALID_STATE;
438                         }
439                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
440                         {
441                                 goto ALREADY_GOING;
442                         }
443                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
444                         {
445                                 debug_log("player is going to paused state, just change the pending state as playing");
446                         }
447                         else
448                         {
449                                 goto INVALID_STATE;
450                         }
451                 }
452                 break;
453
454                 case MMPLAYER_COMMAND_STOP:
455                 {
456                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
457
458                         if ( current_state == MM_PLAYER_STATE_READY )
459                                 goto NO_OP;
460
461                         /* need playing/paused state to stop */
462                         if ( current_state != MM_PLAYER_STATE_PLAYING &&
463                                  current_state != MM_PLAYER_STATE_PAUSED )
464                                 goto INVALID_STATE;
465                 }
466                 break;
467
468                 case MMPLAYER_COMMAND_PAUSE:
469                 {
470                         if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
471                                 goto NO_OP;
472
473                         if (player->doing_seek)
474                                 goto NOT_COMPLETED_SEEK;
475
476                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
477
478                         if ( pending_state == MM_PLAYER_STATE_NONE )
479                         {
480                                 if ( current_state == MM_PLAYER_STATE_PAUSED )
481                                         goto NO_OP;
482                                 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
483                                         goto INVALID_STATE;
484                         }
485                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
486                         {
487                                 goto ALREADY_GOING;
488                         }
489                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
490                         {
491                                 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
492                                         debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
493                                 } else {
494                                         goto INVALID_STATE;
495                                 }
496                         }
497                 }
498                 break;
499
500                 case MMPLAYER_COMMAND_RESUME:
501                 {
502
503                         if (player->doing_seek)
504                                 goto NOT_COMPLETED_SEEK;
505
506                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
507
508                         if ( pending_state == MM_PLAYER_STATE_NONE )
509                         {
510                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
511                                         goto NO_OP;
512                                 else if (  current_state != MM_PLAYER_STATE_PAUSED )
513                                         goto INVALID_STATE;
514                         }
515                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
516                         {
517                                 goto ALREADY_GOING;
518                         }
519                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
520                         {
521                                 debug_log("player is going to paused state, just change the pending state as playing");
522                         }
523                         else
524                         {
525                                 goto INVALID_STATE;
526                         }
527                 }
528                 break;
529
530                 default:
531                 break;
532         }
533         player->cmd = command;
534
535         return MM_ERROR_NONE;
536
537 INVALID_STATE:
538         debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
539                 MMPLAYER_STATE_GET_NAME(current_state), command);
540         return MM_ERROR_PLAYER_INVALID_STATE;
541
542 NOT_COMPLETED_SEEK:
543         debug_warning("not completed seek");
544         return MM_ERROR_PLAYER_DOING_SEEK;
545
546 NO_OP:
547         debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
548         return MM_ERROR_PLAYER_NO_OP;
549
550 ALREADY_GOING:
551         debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
552         return MM_ERROR_PLAYER_NO_OP;
553 }
554
555 int
556 __mmplayer_gst_set_state (mm_player_t* player, GstElement * element,  GstState state, gboolean async, gint timeout) // @
557 {
558         GstState element_state = GST_STATE_VOID_PENDING;
559         GstState element_pending_state = GST_STATE_VOID_PENDING;
560         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
561
562         MMPLAYER_FENTER();
563
564         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
565         return_val_if_fail ( element, MM_ERROR_INVALID_ARGUMENT );
566
567         debug_log("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
568
569         /* set state */
570         ret = gst_element_set_state(element, state);
571
572         if ( ret == GST_STATE_CHANGE_FAILURE )
573         {
574                 debug_error("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
575
576                 /* dump state of all element */
577                 __mmplayer_dump_pipeline_state( player );
578
579                 return MM_ERROR_PLAYER_INTERNAL;
580         }
581
582         /* return here so state transition to be done in async mode */
583         if ( async )
584         {
585                 debug_log("async state transition. not waiting for state complete.\n");
586                 return MM_ERROR_NONE;
587         }
588
589         /* wait for state transition */
590         ret = gst_element_get_state( element, &element_state, &element_pending_state, timeout * GST_SECOND );
591
592         if ( ret == GST_STATE_CHANGE_FAILURE || ( state != element_state ) )
593         {
594                 debug_error("failed to change [%s] element state to [%s] within %d sec\n",
595                         GST_ELEMENT_NAME(element),
596                         gst_element_state_get_name(state), timeout );
597
598                 debug_error(" [%s] state : %s   pending : %s \n",
599                         GST_ELEMENT_NAME(element),
600                         gst_element_state_get_name(element_state),
601                         gst_element_state_get_name(element_pending_state) );
602
603                 /* dump state of all element */
604                 __mmplayer_dump_pipeline_state( player );
605
606                 return MM_ERROR_PLAYER_INTERNAL;
607         }
608
609         debug_log("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
610
611         MMPLAYER_FLEAVE();
612
613         return MM_ERROR_NONE;
614 }
615
616 static void
617 __mmplayer_videostream_cb(GstElement *element, void *data,
618 int width, int height, gpointer user_data) // @
619 {
620         mm_player_t* player = (mm_player_t*)user_data;
621
622         return_if_fail ( player );
623
624         MMPLAYER_FENTER();
625
626         if (player->is_drm_file)
627         {
628                 MMMessageParamType msg_param = { 0, };
629                 debug_warning("not supported in drm file");
630                 msg_param.code = MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
631                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
632         }
633         else if ( !player->set_mode.media_packet_video_stream && player->video_stream_cb)
634         {
635                 MMPlayerVideoStreamDataType stream;
636
637                 /* clear stream data structure */
638                 memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
639
640                 stream.data[0] = data;
641                 stream.length_total = width * height * 4; // for rgb 32bit
642                 stream.height = height;
643                 stream.width = width;
644                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
645         }
646
647         MMPLAYER_FLEAVE();
648 }
649
650 static void
651 __mmplayer_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer data)
652 {
653         mm_player_t* player = (mm_player_t*)data;
654
655         return_if_fail ( player );
656
657         MMPLAYER_FENTER();
658
659         if (player->video_frame_render_error_cb )
660         {
661                 if (player->attrs)
662                 {
663                         int surface_type = 0;
664                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
665                         switch (surface_type)
666                         {
667                         case MM_DISPLAY_SURFACE_X_EXT:
668                                 player->video_frame_render_error_cb((unsigned int*)error_id, player->video_frame_render_error_cb_user_param);
669                                 debug_log("display surface type(X_EXT) : render error callback(%p) is finished", player->video_frame_render_error_cb);
670                                 break;
671                         default:
672                                 debug_error("video_frame_render_error_cb was set, but this surface type(%d) is not supported", surface_type);
673                                 break;
674                         }
675                 }
676                 else
677                 {
678                         debug_error("could not get surface type");
679                 }
680         }
681         else
682         {
683                 debug_warning("video_frame_render_error_cb was not set");
684         }
685
686         MMPLAYER_FLEAVE();
687 }
688
689 void
690 __mmplayer_device_change_post_process(gpointer user)
691 {
692         mm_player_t* player = (mm_player_t*)user;
693         unsigned long position = 0;
694         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
695         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
696
697         MMPLAYER_FENTER();
698
699         if (! player ||
700                 ! player->pipeline ||
701                 ! player->pipeline->mainbin ||
702                 ! player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
703         {
704                 goto EXIT;
705         }
706
707         current_state = MMPLAYER_CURRENT_STATE(player);
708         pending_state = MMPLAYER_PENDING_STATE(player);
709
710         if (player->post_proc.need_pause_and_resume)
711         {
712                 debug_log("pausing");
713                 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
714                         ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
715                         gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED);
716         }
717
718         /* seek should be done within pause and resume */
719         if (player->post_proc.need_seek)
720         {
721                 debug_log("seeking");
722                 __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position);
723                 debug_log(">> seek to current position = %ld ms", position);
724                 __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE);
725         }
726
727         if (player->post_proc.need_pause_and_resume)
728         {
729                 debug_log("resuming");
730                 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
731                         ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
732                         gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING);
733         }
734
735         /* async */
736         if (player->post_proc.need_async)
737         {
738                 debug_log("setting async");
739
740                 /* TODO : need some comment here */
741                 if (player->pipeline->textbin && player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst)
742                         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
743         }
744
745 EXIT:
746         /* reset all */
747         __mmplayer_post_proc_reset(player);
748         return;
749 }
750
751 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score)
752 {
753         return_if_fail(player);
754         player->post_proc.required_cb_score = score;
755         debug_log("set required score to : %d", score);
756 }
757
758 void __mmplayer_inc_cb_score(mm_player_t* player)
759 {
760         return_if_fail(player);
761         player->post_proc.cb_score++;
762         debug_log("post proc cb score increased to %d", player->post_proc.cb_score);
763 }
764
765 void __mmplayer_post_proc_reset(mm_player_t* player)
766 {
767         return_if_fail(player);
768
769         /* check if already triggered */
770         if (player->post_proc.id)
771         {
772                 /* TODO : need to consider multiple main context. !!!! */
773                 if (FALSE == g_source_remove(player->post_proc.id) )
774                 {
775                         debug_error("failed to remove exist post_proc item");
776                 }
777                 player->post_proc.id = 0;
778         }
779
780         memset(&player->post_proc, 0, sizeof(mm_player_post_proc_t));
781
782         /* set default required cb score 1 as only audio device has changed in this case.
783            if display status is changed with audio device, required cb score is set 2 in display status callback.
784            this logic bases on the assumption which audio device callback is called after calling display status callback. */
785         player->post_proc.required_cb_score = 1;
786 }
787
788 void
789 __mmplayer_device_change_trigger_post_process(mm_player_t* player)
790 {
791         return_if_fail(player);
792
793         /* check score */
794         if ( player->post_proc.cb_score < player->post_proc.required_cb_score )
795         {
796                 /* wait for next turn */
797                 debug_log("wait for next turn. required cb score : %d   current score : %d\n",
798                         player->post_proc.required_cb_score, player->post_proc.cb_score);
799                 return;
800         }
801
802         /* check if already triggered */
803         if (player->post_proc.id)
804         {
805                 /* TODO : need to consider multiple main context. !!!! */
806                 if (FALSE == g_source_remove(player->post_proc.id) )
807                 {
808                         debug_error("failed to remove exist post_proc item");
809                 }
810                 player->post_proc.id = 0;
811         }
812
813         player->post_proc.id = g_idle_add((GSourceFunc)__mmplayer_device_change_post_process, (gpointer)player);
814 }
815
816 /* NOTE : Sound module has different latency according to output device So,
817  * synchronization problem can be happened whenever device is changed.
818  * To avoid this issue, we do reset avsystem or seek as workaroud.
819  */
820 static void
821 __mmplayer_sound_device_info_changed_cb_func (MMSoundDevice_t device_h, int changed_info_type, void *user_data)
822 {
823     int ret;
824     mm_sound_device_type_e device_type;
825         mm_player_t* player = (mm_player_t*) user_data;
826
827         return_if_fail( player );
828
829         debug_warning("device_info_changed_cb is called, device_h[0x%x], changed_info_type[%d]\n", device_h, changed_info_type);
830
831         __mmplayer_inc_cb_score(player);
832
833         /* get device type with device_h*/
834         ret = mm_sound_get_device_type(device_h, &device_type);
835         if (ret) {
836                 debug_error("failed to mm_sound_get_device_type()\n");
837         }
838
839         /* do pause and resume only if video is playing  */
840         if ( player->videodec_linked && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING )
841         {
842                 switch (device_type)
843                 {
844                         case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
845                         case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
846                         case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
847                         case MM_SOUND_DEVICE_TYPE_HDMI:
848                         case MM_SOUND_DEVICE_TYPE_MIRRORING:
849                         {
850                                 player->post_proc.need_pause_and_resume = TRUE;
851                         }
852                         break;
853
854                         default:
855                                 debug_log("do nothing");
856                 }
857         }
858         debug_warning("dispatched");
859
860         __mmplayer_device_change_trigger_post_process(player);
861 }
862
863 /* This function should be called after the pipeline goes PAUSED or higher
864 state. */
865 gboolean
866 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
867 {
868         static gboolean has_duration = FALSE;
869         static gboolean has_video_attrs = FALSE;
870         static gboolean has_audio_attrs = FALSE;
871         static gboolean has_bitrate = FALSE;
872         gboolean missing_only = FALSE;
873         gboolean all = FALSE;
874         gint64 dur_nsec = 0;
875         GstStructure* p = NULL;
876         MMHandleType attrs = 0;
877         gchar *path = NULL;
878         gint stream_service_type = STREAMING_SERVICE_NONE;
879         struct stat sb;
880
881         MMPLAYER_FENTER();
882
883         return_val_if_fail ( player, FALSE );
884
885         /* check player state here */
886         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
887                 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING )
888         {
889                 /* give warning now only */
890                 debug_warning("be careful. content attributes may not available in this state ");
891         }
892
893         /* get content attribute first */
894         attrs = MMPLAYER_GET_ATTRS(player);
895         if ( !attrs )
896         {
897                 debug_error("cannot get content attribute");
898                 return FALSE;
899         }
900
901         /* get update flag */
902
903         if ( flag & ATTR_MISSING_ONLY )
904         {
905                 missing_only = TRUE;
906                 debug_log("updating missed attr only");
907         }
908
909         if ( flag & ATTR_ALL )
910         {
911                 all = TRUE;
912                 has_duration = FALSE;
913                 has_video_attrs = FALSE;
914                 has_audio_attrs = FALSE;
915                 has_bitrate = FALSE;
916
917                 debug_log("updating all attrs");
918         }
919
920         if ( missing_only && all )
921         {
922                 debug_warning("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
923                 missing_only = FALSE;
924         }
925
926         if (  (flag & ATTR_DURATION) || (!has_duration && missing_only) || all )
927         {
928                 debug_log("try to update duration");
929                 has_duration = FALSE;
930
931                 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
932                 {
933                         player->duration = dur_nsec;
934                         debug_warning("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
935                 }
936
937                 /* try to get streaming service type */
938                 stream_service_type = __mmplayer_get_stream_service_type( player );
939                 mm_attrs_set_int_by_name ( attrs, "streaming_type", stream_service_type );
940
941                 /* check duration is OK */
942                 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
943                 {
944                         /* FIXIT : find another way to get duration here. */
945                         debug_error("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
946                 }
947                 else
948                 {
949                         /*update duration */
950                         mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
951                         has_duration = TRUE;
952                 }
953         }
954
955         if (  (flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all )
956         {
957                 /* update audio params
958                 NOTE : We need original audio params and it can be only obtained from src pad of audio
959                 decoder. Below code only valid when we are not using 'resampler' just before
960                 'audioconverter'. */
961
962                 debug_log("try to update audio attrs");
963                 has_audio_attrs = FALSE;
964
965                 if ( player->pipeline->audiobin &&
966                          player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
967                 {
968                         GstCaps *caps_a = NULL;
969                         GstPad* pad = NULL;
970                         gint samplerate = 0, channels = 0;
971
972                         pad = gst_element_get_static_pad(
973                                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
974
975                         if ( pad )
976                         {
977                                 caps_a = gst_pad_get_current_caps( pad );
978
979                                 if ( caps_a )
980                                 {
981                                         p = gst_caps_get_structure (caps_a, 0);
982
983                                         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
984
985                                         gst_structure_get_int (p, "rate", &samplerate);
986                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
987
988                                         gst_structure_get_int (p, "channels", &channels);
989                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
990
991                                         secure_debug_log("samplerate : %d       channels : %d", samplerate, channels);
992
993                                         gst_caps_unref( caps_a );
994                                         caps_a = NULL;
995
996                                         has_audio_attrs = TRUE;
997                                 }
998                                 else
999                                 {
1000                                         debug_warning("not ready to get audio caps");
1001                                 }
1002
1003                                 gst_object_unref( pad );
1004                         }
1005                         else
1006                         {
1007                                 debug_warning("failed to get pad from audiosink");
1008                         }
1009                 }
1010         }
1011
1012         if ( (flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all )
1013         {
1014                 debug_log("try to update video attrs");
1015                 has_video_attrs = FALSE;
1016
1017                 if ( player->pipeline->videobin &&
1018                          player->pipeline->videobin[MMPLAYER_V_SINK].gst )
1019                 {
1020                         GstCaps *caps_v = NULL;
1021                         GstPad* pad = NULL;
1022                         gint tmpNu, tmpDe;
1023                         gint width, height;
1024
1025                         pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
1026                         if ( pad )
1027                         {
1028                                 caps_v = gst_pad_get_current_caps( pad );
1029
1030                                 /* Use v_stream_caps, if fail to get video_sink sink pad*/
1031                                 if (!caps_v && player->v_stream_caps)
1032                                 {
1033                                         caps_v = player->v_stream_caps;
1034                                         gst_caps_ref(caps_v);
1035                                 }
1036
1037                                 if (caps_v)
1038                                 {
1039                                         p = gst_caps_get_structure (caps_v, 0);
1040                                         gst_structure_get_int (p, "width", &width);
1041                                         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
1042
1043                                         gst_structure_get_int (p, "height", &height);
1044                                         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
1045
1046                                         gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
1047
1048                                         secure_debug_log("width : %d     height : %d", width, height );
1049
1050                                         gst_caps_unref( caps_v );
1051                                         caps_v = NULL;
1052
1053                                         if (tmpDe > 0)
1054                                         {
1055                                                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
1056                                                 secure_debug_log("fps : %d", tmpNu / tmpDe);
1057                                         }
1058
1059                                         has_video_attrs = TRUE;
1060                                 }
1061                                 else
1062                                 {
1063                                         debug_log("no negitiated caps from videosink");
1064                                 }
1065                                 gst_object_unref( pad );
1066                                 pad = NULL;
1067                         }
1068                         else
1069                         {
1070                                 debug_log("no videosink sink pad");
1071                         }
1072                 }
1073         }
1074
1075
1076         if ( (flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all )
1077         {
1078                 has_bitrate = FALSE;
1079
1080                 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
1081                 if (player->duration)
1082                 {
1083                         guint64 data_size = 0;
1084
1085                         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1086                         {
1087                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1088
1089                                 if (stat(path, &sb) == 0)
1090                                 {
1091                                         data_size = (guint64)sb.st_size;
1092                                 }
1093                         }
1094                         else if (MMPLAYER_IS_HTTP_STREAMING(player))
1095                         {
1096                                 data_size = player->http_content_size;
1097                         }
1098                         debug_log("try to update bitrate : data_size = %lld", data_size);
1099
1100                         if (data_size)
1101                         {
1102                                 guint64 bitrate = 0;
1103                                 guint64 msec_dur = 0;
1104
1105                                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
1106                                 bitrate = data_size * 8 * 1000 / msec_dur;
1107                                 secure_debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
1108                                 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
1109
1110                                 has_bitrate = TRUE;
1111                         }
1112
1113                         if (MMPLAYER_IS_RTSP_STREAMING(player))
1114                         {
1115                                 if(player->total_bitrate)
1116                                 {
1117                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
1118                                         has_bitrate = TRUE;
1119                                 }
1120                         }
1121                 }
1122         }
1123
1124         /* validate all */
1125         if (  mmf_attrs_commit ( attrs ) )
1126         {
1127                 debug_error("failed to update attributes\n");
1128                 return FALSE;
1129         }
1130
1131         MMPLAYER_FLEAVE();
1132
1133         return TRUE;
1134 }
1135
1136 gint __mmplayer_get_stream_service_type( mm_player_t* player )
1137 {
1138         gint streaming_type = STREAMING_SERVICE_NONE;
1139
1140         MMPLAYER_FENTER();
1141
1142         return_val_if_fail ( player &&
1143                         player->pipeline &&
1144                         player->pipeline->mainbin &&
1145                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
1146                         FALSE );
1147
1148         /* streaming service type if streaming */
1149         if ( ! MMPLAYER_IS_STREAMING(player) )
1150                 return STREAMING_SERVICE_NONE;
1151
1152         if (MMPLAYER_IS_HTTP_STREAMING(player))
1153         {
1154                 streaming_type = (player->duration == 0) ?
1155                         STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
1156         }
1157
1158         switch ( streaming_type )
1159         {
1160                 case STREAMING_SERVICE_LIVE:
1161                         debug_log("it's live streaming");
1162                 break;
1163                 case STREAMING_SERVICE_VOD:
1164                         debug_log("it's vod streaming");
1165                 break;
1166                 case STREAMING_SERVICE_NONE:
1167                         debug_error("should not get here");
1168                 break;
1169                 default:
1170                         debug_error("should not get here");
1171         }
1172
1173         player->streaming_type = streaming_type;
1174         MMPLAYER_FLEAVE();
1175
1176         return streaming_type;
1177 }
1178
1179
1180 /* this function sets the player state and also report
1181  * it to applicaton by calling callback function
1182  */
1183 static int
1184 __mmplayer_set_state(mm_player_t* player, int state) // @
1185 {
1186         MMMessageParamType msg = {0, };
1187         int asm_result = MM_ERROR_NONE;
1188         gboolean post_bos = FALSE;
1189         gboolean interrupted_by_asm = FALSE;
1190         int ret = MM_ERROR_NONE;
1191
1192         return_val_if_fail ( player, FALSE );
1193
1194         if ( MMPLAYER_CURRENT_STATE(player) == state )
1195         {
1196                 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
1197                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1198                 return ret;
1199         }
1200
1201         /* update player states */
1202         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
1203         MMPLAYER_CURRENT_STATE(player) = state;
1204
1205         /* FIXIT : it's better to do like below code
1206         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player) )
1207                         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1208         and add more code to handling PENDING_STATE.
1209         */
1210         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
1211                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1212
1213         /* print state */
1214         MMPLAYER_PRINT_STATE(player);
1215
1216         /* do some FSM stuffs before posting new state to application  */
1217         interrupted_by_asm = player->sm.by_asm_cb;
1218
1219         switch ( MMPLAYER_CURRENT_STATE(player) )
1220         {
1221                 case MM_PLAYER_STATE_NULL:
1222                 case MM_PLAYER_STATE_READY:
1223                 {
1224                         if (player->cmd == MMPLAYER_COMMAND_STOP)
1225                         {
1226                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP, FALSE);
1227                                 if ( asm_result != MM_ERROR_NONE )
1228                                 {
1229                                         debug_error("failed to set asm state to stop\n");
1230                                         return MM_ERROR_POLICY_INTERNAL;
1231                                 }
1232                         }
1233                 }
1234                 break;
1235
1236                 case MM_PLAYER_STATE_PAUSED:
1237                 {
1238                          if ( ! player->sent_bos )
1239                          {
1240                                 int found = 0;
1241                                 #define MMPLAYER_MAX_SOUND_PRIORITY     3
1242
1243                                 /* it's first time to update all content attrs. */
1244                                 _mmplayer_update_content_attrs( player, ATTR_ALL );
1245                                 /* set max sound priority to keep own sound and not to mute other's one */
1246                                 mm_attrs_get_int_by_name(player->attrs, "content_video_found", &found);
1247                                 if (found)
1248                                 {
1249                                         mm_attrs_get_int_by_name(player->attrs, "content_audio_found", &found);
1250                                         if (found)
1251                                         {
1252                                                 debug_log("set max audio priority");
1253                                                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "priority", MMPLAYER_MAX_SOUND_PRIORITY, NULL);
1254                                         }
1255                                 }
1256
1257                          }
1258
1259                         /* add audio callback probe if condition is satisfied */
1260                         if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
1261                         {
1262                                 __mmplayer_configure_audio_callback(player);
1263                                 /* FIXIT : handle return value */
1264                         }
1265
1266                         if (!MMPLAYER_IS_STREAMING(player) || (player->streamer && !player->streamer->is_buffering))
1267                         {
1268                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE, FALSE);
1269                                 if ( asm_result )
1270                                 {
1271                                         debug_error("failed to set asm state to PAUSE\n");
1272                                         return MM_ERROR_POLICY_INTERNAL;
1273                                 }
1274                         }
1275                 }
1276                 break;
1277
1278                 case MM_PLAYER_STATE_PLAYING:
1279                 {
1280                         /* try to get content metadata */
1281                         if ( ! player->sent_bos )
1282                         {
1283                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
1284                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
1285                                  * legacy mmfw-player api */
1286                                 _mmplayer_update_content_attrs( player, ATTR_MISSING_ONLY);
1287                         }
1288
1289                         if ( (player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME) )
1290                         {
1291                                 if (!player->sent_bos)
1292                                 {
1293                                         __mmplayer_handle_missed_plugin ( player );
1294                                 }
1295
1296                                 /* update ASM state for video and streaming buffering */
1297                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING, TRUE);
1298                                 if (asm_result != MM_ERROR_NONE)
1299                                 {
1300                                         if (player->pipeline->videobin)
1301                                         {
1302                                                 MMMessageParamType msg = {0, };
1303
1304                                                 debug_error("failed to go ahead because of video conflict\n");
1305
1306                                                 msg.union_type = MM_MSG_UNION_CODE;
1307                                                 msg.code = MM_ERROR_POLICY_INTERRUPTED;
1308                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
1309
1310                                                 _mmplayer_unrealize((MMHandleType)player);
1311                                         }
1312                                         else
1313                                         {
1314                                                 debug_error("failed to play by ASM error : 0x%X\n", asm_result);
1315                                                 _mmplayer_pause((MMHandleType)player);
1316                                                 return asm_result;
1317                                         }
1318
1319                                         return MM_ERROR_POLICY_INTERNAL;
1320                                 }
1321                         }
1322
1323                         if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
1324                         {
1325                                 /* initialize because auto resume is done well. */
1326                                 player->resumed_by_rewind = FALSE;
1327                                 player->playback_rate = 1.0;
1328                         }
1329
1330                         if ( !player->sent_bos )
1331                         {
1332                                 /* check audio codec field is set or not
1333                                  * we can get it from typefinder or codec's caps.
1334                                  */
1335                                 gchar *audio_codec = NULL;
1336                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
1337
1338                                 /* The codec format can't be sent for audio only case like amr, mid etc.
1339                                  * Because, parser don't make related TAG.
1340                                  * So, if it's not set yet, fill it with found data.
1341                                  */
1342                                 if ( ! audio_codec )
1343                                 {
1344                                         if ( g_strrstr(player->type, "audio/midi"))
1345                                         {
1346                                                 audio_codec = g_strdup("MIDI");
1347
1348                                         }
1349                                         else if ( g_strrstr(player->type, "audio/x-amr"))
1350                                         {
1351                                                 audio_codec = g_strdup("AMR");
1352                                         }
1353                                         else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
1354                                         {
1355                                                 audio_codec = g_strdup("AAC");
1356                                         }
1357                                         else
1358                                         {
1359                                                 audio_codec = g_strdup("unknown");
1360                                         }
1361                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1362
1363                                         MMPLAYER_FREEIF(audio_codec);
1364                                         mmf_attrs_commit(player->attrs);
1365                                         debug_log("set audio codec type with caps\n");
1366                                 }
1367
1368                                 post_bos = TRUE;
1369                         }
1370                 }
1371                 break;
1372
1373                 case MM_PLAYER_STATE_NONE:
1374                 default:
1375                         debug_warning("invalid target state, there is nothing to do.\n");
1376                         break;
1377         }
1378
1379
1380         /* post message to application */
1381         if (MMPLAYER_TARGET_STATE(player) == state)
1382         {
1383                 /* fill the message with state of player */
1384                 msg.state.previous = MMPLAYER_PREV_STATE(player);
1385                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
1386
1387                 debug_log ("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
1388
1389                 /* state changed by asm callback */
1390                 if ( interrupted_by_asm )
1391                 {
1392       msg.union_type = MM_MSG_UNION_CODE;
1393       msg.code = player->sm.event_src;
1394                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
1395                 }
1396                 /* state changed by usecase */
1397                 else
1398                 {
1399                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
1400                 }
1401         }
1402         else
1403         {
1404                 debug_log ("intermediate state, do nothing.\n");
1405                 MMPLAYER_PRINT_STATE(player);
1406                 return ret;
1407         }
1408
1409         if ( post_bos )
1410         {
1411                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
1412                 player->sent_bos = TRUE;
1413         }
1414
1415         return ret;
1416 }
1417
1418 gboolean
1419 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
1420 {
1421         return_val_if_fail( player, FALSE );
1422
1423         if ( !player->msg_cb )
1424         {
1425                 return FALSE;
1426         }
1427
1428         //debug_log("Message (type : %d)  will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
1429
1430         player->msg_cb(msgtype, param, player->msg_cb_param);
1431
1432         return TRUE;
1433 }
1434
1435 static gpointer __mmplayer_next_play_thread(gpointer data)
1436 {
1437         mm_player_t* player = (mm_player_t*) data;
1438         MMPlayerGstElement *mainbin = NULL;
1439
1440         return_val_if_fail ( player, NULL );
1441
1442         g_mutex_lock(&player->next_play_thread_mutex);
1443         while ( ! player->next_play_thread_exit )
1444         {
1445                 debug_log("next play thread started. waiting for signal.\n");
1446                 g_cond_wait(&player->next_play_thread_cond, &player->next_play_thread_mutex );
1447
1448                 debug_log("re building pipeline for next play.\n");
1449
1450                 if ( player->next_play_thread_exit )
1451                 {
1452                         if(player->pp_rebuilding)
1453                         {
1454                                 player->pp_rebuilding = false;
1455                                 MMPLAYER_PLAYBACK_UNLOCK(player);
1456                         }
1457                         debug_log("exiting next play thread\n");
1458                         break;
1459                 }
1460
1461                 mainbin = player->pipeline->mainbin;
1462
1463                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
1464                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
1465                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
1466                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
1467                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
1468
1469                 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
1470         }
1471         g_mutex_unlock(&player->next_play_thread_mutex);
1472
1473         return NULL;
1474 }
1475
1476 static gpointer __mmplayer_repeat_thread(gpointer data)
1477 {
1478         mm_player_t* player = (mm_player_t*) data;
1479         gboolean ret_value = FALSE;
1480         MMHandleType attrs = 0;
1481         gint count = 0;
1482
1483         return_val_if_fail ( player, NULL );
1484
1485         g_mutex_lock(&player->repeat_thread_mutex);
1486         while ( ! player->repeat_thread_exit )
1487         {
1488                 debug_log("repeat thread started. waiting for signal.\n");
1489                 g_cond_wait(&player->repeat_thread_cond, &player->repeat_thread_mutex );
1490
1491                 if ( player->repeat_thread_exit )
1492                 {
1493                         debug_log("exiting repeat thread\n");
1494                         break;
1495                 }
1496
1497
1498                 /* lock */
1499                 g_mutex_lock(&player->cmd_lock);
1500
1501                 attrs = MMPLAYER_GET_ATTRS(player);
1502
1503                 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1504                 {
1505                         debug_error("can not get play count\n");
1506                         break;
1507                 }
1508
1509                 if ( player->section_repeat )
1510                 {
1511                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1512                 }
1513                 else
1514                 {
1515                         if ( player->playback_rate < 0.0 )
1516                         {
1517                                 player->resumed_by_rewind = TRUE;
1518                                 _mmplayer_set_mute((MMHandleType)player, 0);
1519                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1520                         }
1521
1522                         ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
1523                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1524                                 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1525
1526                         /* initialize */
1527                         player->sent_bos = FALSE;
1528                 }
1529
1530                 if ( ! ret_value )
1531                 {
1532                         debug_error("failed to set position to zero for rewind\n");
1533                         continue;
1534                 }
1535
1536                 /* decrease play count */
1537                 if ( count > 1 )
1538                 {
1539                         /* we successeded to rewind. update play count and then wait for next EOS */
1540                         count--;
1541
1542                         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1543
1544                         /* commit attribute */
1545                         if ( mmf_attrs_commit ( attrs ) )
1546                         {
1547                                 debug_error("failed to commit attribute\n");
1548                         }
1549                 }
1550
1551                 /* unlock */
1552                 g_mutex_unlock(&player->cmd_lock);
1553         }
1554
1555         g_mutex_unlock(&player->repeat_thread_mutex);
1556         return NULL;
1557 }
1558
1559 static void
1560 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
1561 {
1562         MMHandleType attrs = 0;
1563         guint64 data_size = 0;
1564         gchar* path = NULL;
1565         unsigned long pos_msec = 0;
1566         struct stat sb;
1567
1568         return_if_fail( player && player->pipeline && player->pipeline->mainbin);
1569
1570         __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_msec);       // update last_position
1571
1572         attrs = MMPLAYER_GET_ATTRS(player);
1573         if ( !attrs )
1574         {
1575                 debug_error("fail to get attributes.\n");
1576                 return;
1577         }
1578
1579         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1580         {
1581                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1582
1583                 if (stat(path, &sb) == 0)
1584                 {
1585                         data_size = (guint64)sb.st_size;
1586                 }
1587         }
1588         else if (MMPLAYER_IS_HTTP_STREAMING(player))
1589         {
1590                 data_size = player->http_content_size;
1591         }
1592
1593         __mm_player_streaming_buffering(        player->streamer,
1594                                                                                 buffering_msg,
1595                                                                                 data_size,
1596                                                                                 player->last_position,
1597                                                                                 player->duration);
1598
1599         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
1600
1601         return;
1602 }
1603
1604
1605 static void
1606 __mmplayer_handle_buffering_message ( mm_player_t* player )
1607 {
1608         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1609         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1610         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1611         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1612
1613         return_if_fail ( player );
1614
1615         prev_state = MMPLAYER_PREV_STATE(player);
1616         current_state = MMPLAYER_CURRENT_STATE(player);
1617         target_state = MMPLAYER_TARGET_STATE(player);
1618         pending_state = MMPLAYER_PENDING_STATE(player);
1619
1620         if (MMPLAYER_IS_LIVE_STREAMING(player))
1621                 return;
1622
1623         if ( !player->streamer->is_buffering )
1624         {
1625                 debug_log( "player state : prev %s, current %s, pending %s, target %s \n",
1626                         MMPLAYER_STATE_GET_NAME(prev_state),
1627                         MMPLAYER_STATE_GET_NAME(current_state),
1628                         MMPLAYER_STATE_GET_NAME(pending_state),
1629                         MMPLAYER_STATE_GET_NAME(target_state));
1630
1631                 /* NOTE : if buffering has done, player has to go to target state. */
1632                 switch ( target_state )
1633                 {
1634                         case MM_PLAYER_STATE_PAUSED :
1635                         {
1636                                 switch ( pending_state )
1637                                 {
1638                                         case MM_PLAYER_STATE_PLAYING:
1639                                         {
1640                                                 __gst_pause ( player, TRUE );
1641                                         }
1642                                         break;
1643
1644                                         case MM_PLAYER_STATE_PAUSED:
1645                                         {
1646                                                  debug_log("player is already going to paused state, there is nothing to do.\n");
1647                                         }
1648                                         break;
1649
1650                                         case MM_PLAYER_STATE_NONE:
1651                                         case MM_PLAYER_STATE_NULL:
1652                                         case MM_PLAYER_STATE_READY:
1653                                         default :
1654                                         {
1655                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1656                                         }
1657                                                 break;
1658                                 }
1659                         }
1660                         break;
1661
1662                         case MM_PLAYER_STATE_PLAYING :
1663                         {
1664                                 switch ( pending_state )
1665                                 {
1666                                         case MM_PLAYER_STATE_NONE:
1667                                         {
1668                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
1669                                                         __gst_resume ( player, TRUE );
1670                                         }
1671                                         break;
1672
1673                                         case MM_PLAYER_STATE_PAUSED:
1674                                         {
1675                                                 /* NOTE: It should be worked as asynchronously.
1676                                                  * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1677                                                  */
1678                                                 __gst_resume ( player, TRUE );
1679                                         }
1680                                         break;
1681
1682                                         case MM_PLAYER_STATE_PLAYING:
1683                                         {
1684                                                  debug_log("player is already going to playing state, there is nothing to do.\n");
1685                                         }
1686                                         break;
1687
1688                                         case MM_PLAYER_STATE_NULL:
1689                                         case MM_PLAYER_STATE_READY:
1690                                         default :
1691                                         {
1692                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1693                                         }
1694                                                 break;
1695                                 }
1696                         }
1697                         break;
1698
1699                         case MM_PLAYER_STATE_NULL :
1700                         case MM_PLAYER_STATE_READY :
1701                         case MM_PLAYER_STATE_NONE :
1702                         default:
1703                         {
1704                                 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1705                         }
1706                                 break;
1707                 }
1708         }
1709         else
1710         {
1711                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1712                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
1713                  */
1714                 switch ( pending_state )
1715                 {
1716                         case MM_PLAYER_STATE_NONE:
1717                         {
1718                                 if (current_state != MM_PLAYER_STATE_PAUSED)
1719                                 {
1720                                         debug_log("set pause state during buffering\n");
1721                                         __gst_pause ( player, TRUE );
1722
1723                                         // to cover the weak-signal environment.
1724                                         if (MMPLAYER_IS_RTSP_STREAMING(player))
1725                                         {
1726                                                 unsigned long position = 0;
1727                                                 gint64 pos_msec = 0;
1728
1729                                                 debug_log("[RTSP] seek to the buffering start point\n");
1730
1731                                                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
1732                                                 {
1733                                                         debug_error("failed to get position\n");
1734                                                         break;
1735                                                 }
1736
1737                                                 /* key unit seek */
1738                                                 pos_msec = position * G_GINT64_CONSTANT(1000000);
1739
1740                                                 __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
1741                                                                         GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1742                                                                         pos_msec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1743                                         }
1744                                 }
1745                         }
1746                         break;
1747
1748                         case MM_PLAYER_STATE_PLAYING:
1749                         {
1750                                 __gst_pause ( player, TRUE );
1751                         }
1752                         break;
1753
1754                         case MM_PLAYER_STATE_PAUSED:
1755                         {
1756                         }
1757                         break;
1758
1759                         case MM_PLAYER_STATE_NULL:
1760                         case MM_PLAYER_STATE_READY:
1761                         default :
1762                         {
1763                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1764                         }
1765                                 break;
1766                 }
1767         }
1768 }
1769
1770 static void
1771 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
1772 {
1773         MMPlayerGstElement *textbin;
1774         MMPLAYER_FENTER();
1775
1776         return_if_fail ( player &&
1777                                         player->pipeline &&
1778                                         player->pipeline->textbin);
1779
1780         return_if_fail (player->pipeline->textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst);
1781
1782         textbin = player->pipeline->textbin;
1783
1784         if (is_drop)
1785         {
1786                 debug_log("Drop subtitle text after getting EOS\n");
1787
1788                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
1789                 g_object_set(textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1790
1791                 player->is_subtitle_force_drop = TRUE;
1792         }
1793         else
1794         {
1795                 if (player->is_subtitle_force_drop == TRUE)
1796                 {
1797                         debug_log("Enable subtitle data path without drop\n");
1798
1799                         // player->display_stat = util_get_is_connected_external_display();
1800
1801                         g_object_set(textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1802                         g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
1803
1804                         debug_log ("non-connected with external display");
1805
1806                         player->is_subtitle_force_drop = FALSE;
1807                 }
1808         }
1809 }
1810
1811 static gboolean
1812 __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
1813 {
1814         mm_player_t* player = (mm_player_t*) data;
1815         gboolean ret = TRUE;
1816         static gboolean async_done = FALSE;
1817
1818         return_val_if_fail ( player, FALSE );
1819         return_val_if_fail ( msg && GST_IS_MESSAGE(msg), FALSE );
1820
1821         switch ( GST_MESSAGE_TYPE( msg ) )
1822         {
1823                 case GST_MESSAGE_UNKNOWN:
1824                         debug_log("unknown message received\n");
1825                 break;
1826
1827                 case GST_MESSAGE_EOS:
1828                 {
1829                         MMHandleType attrs = 0;
1830                         gint count = 0;
1831
1832                         debug_log("GST_MESSAGE_EOS received\n");
1833
1834                         /* NOTE : EOS event is comming multiple time. watch out it */
1835                         /* check state. we only process EOS when pipeline state goes to PLAYING */
1836                         if ( ! (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) )
1837                         {
1838                                 debug_log("EOS received on non-playing state. ignoring it\n");
1839                                 break;
1840                         }
1841
1842                         __mmplayer_drop_subtitle(player, TRUE);
1843
1844                         if ( (player->audio_stream_cb) && (player->set_mode.pcm_extraction) && (!player->audio_stream_render_cb_ex))
1845                         {
1846                                 GstPad *pad = NULL;
1847
1848                                 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1849
1850                                 debug_log("release audio callback\n");
1851
1852                                 /* release audio callback */
1853                                 gst_pad_remove_probe (pad, player->audio_cb_probe_id);
1854                                 player->audio_cb_probe_id = 0;
1855                                 /* audio callback should be free because it can be called even though probe remove.*/
1856                                 player->audio_stream_cb = NULL;
1857                                 player->audio_stream_cb_user_param = NULL;
1858
1859                         }
1860
1861                         /* rewind if repeat count is greater then zero */
1862                         /* get play count */
1863                         attrs = MMPLAYER_GET_ATTRS(player);
1864
1865                         if ( attrs )
1866                         {
1867                                 gboolean smooth_repeat = FALSE;
1868
1869                                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1870                                 mm_attrs_get_int_by_name(attrs, "profile_smooth_repeat", &smooth_repeat);
1871
1872                                 player->play_count = count;
1873
1874                                 debug_log("remaining play count: %d, playback rate: %f\n", count, player->playback_rate);
1875
1876                                 if ( count > 1 || count == -1 || player->playback_rate < 0.0 ) /* default value is 1 */
1877                                 {
1878                                         if ( smooth_repeat )
1879                                         {
1880                                                 debug_log("smooth repeat enabled. seeking operation will be excuted in new thread\n");
1881
1882                                                 g_cond_signal( &player->repeat_thread_cond );
1883
1884                                                 break;
1885                                         }
1886                                         else
1887                                         {
1888                                                 gint ret_value = 0;
1889
1890                                                 if ( player->section_repeat )
1891                                                 {
1892                                                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1893                                                 }
1894                                                 else
1895                                                 {
1896                                                         if ( player->playback_rate < 0.0 )
1897                                                         {
1898                                                                 player->resumed_by_rewind = TRUE;
1899                                                                 _mmplayer_set_mute((MMHandleType)player, 0);
1900                                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1901                                                         }
1902
1903                                                         __mmplayer_handle_eos_delay( player, player->ini.delay_before_repeat );
1904
1905                                                         /* initialize */
1906                                                         player->sent_bos = FALSE;
1907                                                 }
1908
1909                                                 if ( MM_ERROR_NONE != ret_value )
1910                                                 {
1911                                                         debug_error("failed to set position to zero for rewind\n");
1912                                                 }
1913
1914                                                 /* not posting eos when repeating */
1915                                                 break;
1916                                         }
1917                                 }
1918                         }
1919
1920                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-eos" );
1921
1922                         /* post eos message to application */
1923                         __mmplayer_handle_eos_delay( player, player->ini.eos_delay );
1924
1925                         /* reset last position */
1926                         player->last_position = 0;
1927                 }
1928                 break;
1929
1930                 case GST_MESSAGE_ERROR:
1931                 {
1932                         GError *error = NULL;
1933                         gchar* debug = NULL;
1934
1935                         /* generating debug info before returning error */
1936                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-error" );
1937
1938                         /* get error code */
1939                         gst_message_parse_error( msg, &error, &debug );
1940
1941                         if ( gst_structure_has_name ( gst_message_get_structure(msg), "streaming_error" ) )
1942                         {
1943                                 /* Note : the streaming error from the streaming source is handled
1944                                  *   using __mmplayer_handle_streaming_error.
1945                                  */
1946                                 __mmplayer_handle_streaming_error ( player, msg );
1947
1948                                 /* dump state of all element */
1949                                 __mmplayer_dump_pipeline_state( player );
1950                         }
1951                         else
1952                         {
1953                                 /* traslate gst error code to msl error code. then post it
1954                                  * to application if needed
1955                                  */
1956                                 __mmplayer_handle_gst_error( player, msg, error );
1957
1958                                 if (debug)
1959                                 {
1960                                         debug_error ("error debug : %s", debug);
1961                                 }
1962
1963                         }
1964
1965                         if (MMPLAYER_IS_HTTP_PD(player))
1966                         {
1967                                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
1968                         }
1969
1970                         MMPLAYER_FREEIF( debug );
1971                         g_error_free( error );
1972                 }
1973                 break;
1974
1975                 case GST_MESSAGE_WARNING:
1976                 {
1977                         char* debug = NULL;
1978                         GError* error = NULL;
1979
1980                         gst_message_parse_warning(msg, &error, &debug);
1981
1982                         debug_log("warning : %s\n", error->message);
1983                         debug_log("debug : %s\n", debug);
1984
1985                         MMPLAYER_POST_MSG( player, MM_MESSAGE_WARNING, NULL );
1986
1987                         MMPLAYER_FREEIF( debug );
1988                         g_error_free( error );
1989                 }
1990                 break;
1991
1992                 case GST_MESSAGE_TAG:
1993                 {
1994                         debug_log("GST_MESSAGE_TAG\n");
1995                         if ( ! __mmplayer_gst_extract_tag_from_msg( player, msg ) )
1996                         {
1997                                 debug_warning("failed to extract tags from gstmessage\n");
1998                         }
1999                 }
2000                 break;
2001
2002                 case GST_MESSAGE_BUFFERING:
2003                 {
2004                         MMMessageParamType msg_param = {0, };
2005                         int asm_result = MM_ERROR_NONE;
2006
2007                         if (!MMPLAYER_IS_STREAMING(player))
2008                                 break;
2009
2010                         /* ignore the prev buffering message */
2011                         if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (player->streamer->is_buffering_done == TRUE))
2012                         {
2013                                 gint buffer_percent = 0;
2014
2015                                 gst_message_parse_buffering (msg, &buffer_percent);
2016
2017                                 if (buffer_percent == MAX_BUFFER_PERCENT)
2018                                 {
2019                                         debug_log ("Ignored all the previous buffering msg! (got %d%%)\n", buffer_percent);
2020                                         player->streamer->is_buffering_done = FALSE;
2021                                 }
2022
2023                                 break;
2024                         }
2025
2026                         /* update ASM state to ASM_STATE_PLAYING */
2027                         /* fixed ASM_STATE_WAITING -> ASM_STATE_PLAYING for Samsunlink issue*/
2028                         if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED))
2029                         {
2030                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_WAITING, TRUE);
2031                                 if ( asm_result != MM_ERROR_NONE )
2032                                 {
2033                                         debug_warning("failed to set asm state to waiting, but keep going...\n");
2034                                 }
2035                         }
2036
2037                         __mmplayer_update_buffer_setting(player, msg);
2038
2039                         __mmplayer_handle_buffering_message ( player );
2040
2041                         msg_param.connection.buffering = player->streamer->buffering_percent;
2042                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param );
2043                         if (MMPLAYER_IS_RTSP_STREAMING(player) && (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT))
2044                         {
2045                                 if (player->doing_seek)
2046                                 {
2047                                         if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2048                                         {
2049                                                 player->doing_seek = FALSE;
2050                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2051                                         }
2052                                         else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2053                                         {
2054                                                 async_done = TRUE;
2055                                         }
2056                                 }
2057                         }
2058                 }
2059                 break;
2060
2061                 case GST_MESSAGE_STATE_CHANGED:
2062                 {
2063                         MMPlayerGstElement *mainbin;
2064                         const GValue *voldstate, *vnewstate, *vpending;
2065                         GstState oldstate, newstate, pending;
2066
2067                         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
2068                         {
2069                                 debug_error("player pipeline handle is null");
2070                                 break;
2071                         }
2072
2073                         mainbin = player->pipeline->mainbin;
2074
2075                         /* we only handle messages from pipeline */
2076                         if( msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst )
2077                                 break;
2078
2079                         /* get state info from msg */
2080                         voldstate = gst_structure_get_value (gst_message_get_structure(msg), "old-state");
2081                         vnewstate = gst_structure_get_value (gst_message_get_structure(msg), "new-state");
2082                         vpending = gst_structure_get_value (gst_message_get_structure(msg), "pending-state");
2083
2084                         oldstate = (GstState)voldstate->data[0].v_int;
2085                         newstate = (GstState)vnewstate->data[0].v_int;
2086                         pending = (GstState)vpending->data[0].v_int;
2087
2088                         debug_log("state changed [%s] : %s ---> %s     final : %s\n",
2089                                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
2090                                 gst_element_state_get_name( (GstState)oldstate ),
2091                                 gst_element_state_get_name( (GstState)newstate ),
2092                                 gst_element_state_get_name( (GstState)pending ) );
2093
2094                         if (oldstate == newstate)
2095                         {
2096                                 debug_log("pipeline reports state transition to old state");
2097                                 break;
2098                         }
2099
2100                         switch(newstate)
2101                         {
2102                                 case GST_STATE_VOID_PENDING:
2103                                 break;
2104
2105                                 case GST_STATE_NULL:
2106                                 break;
2107
2108                                 case GST_STATE_READY:
2109                                 break;
2110
2111                                 case GST_STATE_PAUSED:
2112                                 {
2113                                         gboolean prepare_async = FALSE;
2114                                         gboolean is_drm = FALSE;
2115
2116                                         if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
2117                                                 __mmplayer_configure_audio_callback(player);
2118
2119                                         if ( ! player->sent_bos && oldstate == GST_STATE_READY) // managed prepare async case
2120                                         {
2121                                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
2122                                                 debug_log("checking prepare mode for async transition - %d", prepare_async);
2123                                         }
2124
2125                                         if ( MMPLAYER_IS_STREAMING(player) || prepare_async )
2126                                         {
2127                                                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
2128
2129                                                 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
2130                                                 {
2131                                                         __mm_player_streaming_set_content_bitrate(player->streamer,
2132                                                                 player->total_maximum_bitrate, player->total_bitrate);
2133                                                 }
2134                                         }
2135
2136                                         /* NOTE : should consider streaming case */
2137                                         /* check if drm file */
2138                                         if ((player->pipeline->mainbin[MMPLAYER_M_SRC].gst) &&
2139                                                 (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm")))
2140                                         {
2141                                                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
2142
2143                                                 if (is_drm)
2144                                                 {
2145                                                         player->is_drm_file = TRUE;
2146                                                 }
2147                                         }
2148                                 }
2149                                 break;
2150
2151                                 case GST_STATE_PLAYING:
2152                                 {
2153 /* for audio tunning */
2154 #ifndef IS_SDK
2155                                         if (player->can_support_codec == 0x03) {
2156                                                 gint volume_type;
2157                                                 mm_attrs_get_int_by_name(player->attrs, "sound_volume_type", &volume_type);
2158                                                 volume_type |= MM_SOUND_VOLUME_GAIN_VIDEO;
2159                                                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "volumetype", volume_type, NULL);
2160                                         }
2161 #endif
2162                                         if ( MMPLAYER_IS_STREAMING(player) ) // managed prepare async case when buffering is completed
2163                                         {
2164                                                 // pending state should be reset oyherwise, it's still playing even though it's resumed after bufferging.
2165                                                 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
2166                                                         (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
2167                                                 {
2168                                                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING);
2169                                                 }
2170                                         }
2171
2172                                         if (player->src_changed)
2173                                         {
2174                                                 _mmplayer_update_content_attrs(player, ATTR_ALL);
2175                                                 player->src_changed = FALSE;
2176                                         }
2177
2178                                         if (player->doing_seek && async_done)
2179                                         {
2180                                                 player->doing_seek = FALSE;
2181                                                 async_done = FALSE;
2182                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2183                                         }
2184                                 }
2185                                 break;
2186
2187                                 default:
2188                                 break;
2189                         }
2190                 }
2191                 break;
2192
2193                 case GST_MESSAGE_CLOCK_LOST:
2194                         {
2195                                 GstClock *clock = NULL;
2196                                 gst_message_parse_clock_lost (msg, &clock);
2197                                 debug_log("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2198                                 g_print ("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2199
2200                                 if (((player->ini.provide_clock_for_music) && (!player->videodec_linked)) ||
2201                                         ((player->ini.provide_clock_for_movie) && (player->videodec_linked)))
2202                                 {
2203                                         debug_log ("Provide clock is TRUE, do pause->resume\n");
2204                                         __gst_pause(player, FALSE);
2205                                         __gst_resume(player, FALSE);
2206                                 }
2207                         }
2208                         break;
2209
2210                 case GST_MESSAGE_NEW_CLOCK:
2211                         {
2212                                 GstClock *clock = NULL;
2213                                 gst_message_parse_new_clock (msg, &clock);
2214                                 debug_log("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2215                         }
2216                         break;
2217
2218                 case GST_MESSAGE_ELEMENT:
2219                         {
2220                                 const gchar *structure_name;
2221                                 gint count = 0;
2222                                 MMHandleType attrs = 0;
2223
2224                                 attrs = MMPLAYER_GET_ATTRS(player);
2225                                 if ( !attrs )
2226                                 {
2227                                         debug_error("cannot get content attribute");
2228                                         ret = FALSE;
2229                                         break;
2230                                 }
2231
2232                                 if(gst_message_get_structure(msg) == NULL)
2233                                         break;
2234
2235                                 structure_name = gst_structure_get_name(gst_message_get_structure(msg));
2236                                 if(!strcmp(structure_name, "Language_list"))
2237                                 {
2238                                         const GValue *lang_list = NULL;
2239                                         lang_list = gst_structure_get_value (gst_message_get_structure(msg), "lang_list");
2240                                         if(lang_list != NULL)
2241                                         {
2242                                                 count = g_list_length((GList *)g_value_get_pointer (lang_list));
2243                                                 if (count > 1)
2244                                                         debug_log("Total audio tracks (from parser) = %d \n",count);
2245                                         }
2246                                 }
2247
2248                                 if (!strcmp (structure_name, "Ext_Sub_Language_List"))
2249                                 {
2250                                         const GValue *lang_list = NULL;
2251                                         MMPlayerLangStruct *temp = NULL;
2252
2253                                         lang_list = gst_structure_get_value (gst_message_get_structure(msg), "lang_list");
2254                                         if (lang_list != NULL)
2255                                         {
2256                                                 count = g_list_length ((GList *)g_value_get_pointer (lang_list));
2257                                                 if (count)
2258                                                 {
2259                                                         player->subtitle_language_list = (GList *)g_value_get_pointer (lang_list);
2260                                                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
2261                                                         if (mmf_attrs_commit (attrs))
2262                                                           debug_error("failed to commit.\n");
2263                                                         debug_log("Total subtitle tracks = %d \n", count);
2264                                                 }
2265                                                 while (count)
2266                                                 {
2267                                                         temp = g_list_nth_data (player->subtitle_language_list, count - 1);
2268                                                         debug_log ("value of lang_key is %s and lang_code is %s",
2269                                                                                 temp->language_key, temp->language_code);
2270                                                         count--;
2271                                                 }
2272                                         }
2273                                 }
2274
2275                                 /* custom message */
2276                                 if (!strcmp (structure_name, "audio_codec_not_supported")) {
2277                                         MMMessageParamType msg_param = {0,};
2278                                         msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
2279                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
2280                                 }
2281                         }
2282                         break;
2283
2284                 case GST_MESSAGE_DURATION_CHANGED:
2285                 {
2286                         debug_log("GST_MESSAGE_DURATION_CHANGED\n");
2287                         ret = __mmplayer_gst_handle_duration(player, msg);
2288                         if (!ret)
2289                         {
2290                                 debug_warning("failed to update duration");
2291                         }
2292                 }
2293
2294                 break;
2295
2296                 case GST_MESSAGE_ASYNC_START:
2297                 {
2298                         debug_log("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2299                 }
2300                 break;
2301
2302                 case GST_MESSAGE_ASYNC_DONE:
2303                 {
2304                         debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2305
2306                         /* we only handle messages from pipeline */
2307                         if( msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
2308                                 break;
2309
2310                         if (player->doing_seek)
2311                         {
2312                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2313                                 {
2314                                         player->doing_seek = FALSE;
2315                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2316                                 }
2317                                 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2318                                 {
2319                                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2320                                                 (player->streamer) &&
2321                                                 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
2322                                                 (player->streamer->is_buffering == FALSE))
2323                                         {
2324                                                 GstQuery *query = NULL;
2325                                                 gboolean busy = FALSE;
2326                                                 gint percent = 0;
2327
2328                                                 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer)
2329                                                 {
2330                                                         query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
2331                                                         if ( gst_element_query (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query ) )
2332                                                         {
2333                                                                 gst_query_parse_buffering_percent ( query, &busy, &percent);
2334                                                         }
2335                                                         gst_query_unref (query);
2336
2337                                                         debug_log("buffered percent(%s): %d\n",
2338                                                                 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
2339                                                 }
2340
2341                                                 if (percent >= 100)
2342                                                 {
2343                                                         player->streamer->is_buffering = FALSE;
2344                                                         __mmplayer_handle_buffering_message(player);
2345                                                 }
2346                                         }
2347
2348                                         async_done = TRUE;
2349                                 }
2350                         }
2351                 }
2352                 break;
2353
2354                 #if 0 /* delete unnecessary logs */
2355                 case GST_MESSAGE_REQUEST_STATE:         debug_log("GST_MESSAGE_REQUEST_STATE\n"); break;
2356                 case GST_MESSAGE_STEP_START:            debug_log("GST_MESSAGE_STEP_START\n"); break;
2357                 case GST_MESSAGE_QOS:                           debug_log("GST_MESSAGE_QOS\n"); break;
2358                 case GST_MESSAGE_PROGRESS:                      debug_log("GST_MESSAGE_PROGRESS\n"); break;
2359                 case GST_MESSAGE_ANY:                           debug_log("GST_MESSAGE_ANY\n"); break;
2360                 case GST_MESSAGE_INFO:                          debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2361                 case GST_MESSAGE_STATE_DIRTY:           debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2362                 case GST_MESSAGE_STEP_DONE:                     debug_log("GST_MESSAGE_STEP_DONE\n"); break;
2363                 case GST_MESSAGE_CLOCK_PROVIDE:         debug_log("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
2364                 case GST_MESSAGE_STRUCTURE_CHANGE:      debug_log("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
2365                 case GST_MESSAGE_STREAM_STATUS:         debug_log("GST_MESSAGE_STREAM_STATUS\n"); break;
2366                 case GST_MESSAGE_APPLICATION:           debug_log("GST_MESSAGE_APPLICATION\n"); break;
2367                 case GST_MESSAGE_SEGMENT_START:         debug_log("GST_MESSAGE_SEGMENT_START\n"); break;
2368                 case GST_MESSAGE_SEGMENT_DONE:          debug_log("GST_MESSAGE_SEGMENT_DONE\n"); break;
2369                 case GST_MESSAGE_LATENCY:                               debug_log("GST_MESSAGE_LATENCY\n"); break;
2370                 #endif
2371
2372                 default:
2373                 break;
2374         }
2375
2376         /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
2377          * gst_element_post_message api takes ownership of the message.
2378          */
2379         //gst_message_unref( msg );
2380
2381         return ret;
2382 }
2383
2384 static gboolean
2385 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
2386 {
2387         gint64 bytes = 0;
2388
2389         MMPLAYER_FENTER();
2390
2391         return_val_if_fail(player, FALSE);
2392         return_val_if_fail(msg, FALSE);
2393
2394         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2395                 (msg->src) && (msg->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst))
2396         {
2397                 debug_log("msg src : [%s]", GST_ELEMENT_NAME(GST_ELEMENT_CAST(msg->src)));
2398
2399                 if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes))
2400                 {
2401                         debug_log("data total size of http content: %lld", bytes);
2402                         player->http_content_size = bytes;
2403                 }
2404         }
2405         else
2406         {
2407                 /* handling audio clip which has vbr. means duration is keep changing */
2408                 _mmplayer_update_content_attrs (player, ATTR_DURATION );
2409         }
2410
2411         MMPLAYER_FLEAVE();
2412
2413         return TRUE;
2414 }
2415
2416
2417 static gboolean
2418 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg) // @
2419 {
2420
2421 /* macro for better code readability */
2422 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
2423 if (gst_tag_list_get_string(tag_list, gsttag, &string)) \
2424 {\
2425         if (string != NULL)\
2426         {\
2427                 secure_debug_log ( "update tag string : %s\n", string); \
2428                 mm_attrs_set_string_by_name(attribute, playertag, string); \
2429                 g_free(string);\
2430                 string = NULL;\
2431         }\
2432 }
2433
2434 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
2435 GstSample *sample = NULL;\
2436 if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample))\
2437 {\
2438         GstMapInfo info = GST_MAP_INFO_INIT;\
2439         buffer = gst_sample_get_buffer(sample);\
2440         if (!gst_buffer_map(buffer, &info, GST_MAP_READ)){\
2441                 debug_log("failed to get image data from tag");\
2442                 return FALSE;\
2443         }\
2444         secure_debug_log ( "update album cover data : %p, size : %d\n", info.data, info.size);\
2445         MMPLAYER_FREEIF(player->album_art); \
2446         player->album_art = (gchar *)g_malloc(info.size); \
2447         if (player->album_art) \
2448         { \
2449                 memcpy(player->album_art, info.data, info.size); \
2450                 mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, info.size); \
2451                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) \
2452                 { \
2453                         msg_param.data = (void *)player->album_art; \
2454                         msg_param.size = info.size; \
2455                         MMPLAYER_POST_MSG (player, MM_MESSAGE_IMAGE_BUFFER, &msg_param); \
2456                         secure_debug_log ( "post message image buffer data : %p, size : %d\n", info.data, info.size); \
2457                 } \
2458         } \
2459         gst_buffer_unmap(buffer, &info); \
2460 }
2461
2462 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
2463 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint))\
2464 {\
2465         if(v_uint)\
2466         {\
2467                 if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) \
2468                 {\
2469                         if (player->updated_bitrate_count == 0) \
2470                                 mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
2471                         if (player->updated_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2472                         {\
2473                                 player->bitrate[player->updated_bitrate_count] = v_uint;\
2474                                 player->total_bitrate += player->bitrate[player->updated_maximum_bitrate_count]; \
2475                                 player->updated_bitrate_count++; \
2476                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate);\
2477                                 secure_debug_log ( "update bitrate %d[bps] of stream #%d.\n", v_uint, player->updated_bitrate_count);\
2478                         }\
2479                 }\
2480                 else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) \
2481                 {\
2482                         if (player->updated_maximum_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2483                         {\
2484                                 player->maximum_bitrate[player->updated_maximum_bitrate_count] = v_uint;\
2485                                 player->total_maximum_bitrate += player->maximum_bitrate[player->updated_maximum_bitrate_count]; \
2486                                 player->updated_maximum_bitrate_count++; \
2487                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate); \
2488                                 secure_debug_log ( "update maximum bitrate %d[bps] of stream #%d\n", v_uint, player->updated_maximum_bitrate_count);\
2489                         }\
2490                 }\
2491                 else\
2492                 {\
2493                         mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
2494                 }\
2495                 v_uint = 0;\
2496         }\
2497 }
2498
2499 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
2500 if (gst_tag_list_get_date(tag_list, gsttag, &date))\
2501 {\
2502         if (date != NULL)\
2503         {\
2504                 string = g_strdup_printf("%d", g_date_get_year(date));\
2505                 mm_attrs_set_string_by_name(attribute, playertag, string);\
2506                 secure_debug_log ( "metainfo year : %s\n", string);\
2507                 MMPLAYER_FREEIF(string);\
2508                 g_date_free(date);\
2509         }\
2510 }
2511
2512 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
2513 if(gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64))\
2514 {\
2515         if(v_uint64)\
2516         {\
2517                 /* FIXIT : don't know how to store date */\
2518                 g_assert(1);\
2519                 v_uint64 = 0;\
2520         }\
2521 }
2522
2523 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
2524 if(gst_tag_list_get_double(tag_list, gsttag, &v_double))\
2525 {\
2526         if(v_double)\
2527         {\
2528                 /* FIXIT : don't know how to store date */\
2529                 g_assert(1);\
2530                 v_double = 0;\
2531         }\
2532 }
2533
2534         /* function start */
2535         GstTagList* tag_list = NULL;
2536
2537         MMHandleType attrs = 0;
2538
2539         char *string = NULL;
2540         guint v_uint = 0;
2541         GDate *date = NULL;
2542         /* album cover */
2543         GstBuffer *buffer = NULL;
2544         gint index = 0;
2545         MMMessageParamType msg_param = {0, };
2546
2547         /* currently not used. but those are needed for above macro */
2548         //guint64 v_uint64 = 0;
2549         //gdouble v_double = 0;
2550
2551         return_val_if_fail( player && msg, FALSE );
2552
2553         attrs = MMPLAYER_GET_ATTRS(player);
2554
2555         return_val_if_fail( attrs, FALSE );
2556
2557         /* get tag list from gst message */
2558         gst_message_parse_tag(msg, &tag_list);
2559
2560         /* store tags to player attributes */
2561         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
2562         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
2563         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
2564         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
2565         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
2566         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
2567         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
2568         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
2569         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
2570         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
2571         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
2572         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
2573         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
2574         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
2575         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
2576         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
2577         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
2578         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
2579         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
2580         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
2581         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
2582         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
2583         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
2584         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
2585         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
2586         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
2587         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
2588         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
2589         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
2590         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
2591         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
2592         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
2593         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
2594         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
2595         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
2596         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
2597         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
2598         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
2599         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
2600         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
2601         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
2602         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
2603         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
2604         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
2605         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
2606         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, attrs, "content_video_orientation");
2607
2608         if ( mmf_attrs_commit ( attrs ) )
2609                 debug_error("failed to commit.\n");
2610
2611         gst_tag_list_free(tag_list);
2612
2613         return TRUE;
2614 }
2615
2616 static void
2617 __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data)  // @
2618 {
2619         mm_player_t* player = (mm_player_t*) data;
2620
2621         MMPLAYER_FENTER();
2622
2623         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2624           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2625           * num_dynamic_pad. and this is no-more-pad situation which means mo more pad will be added.
2626           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2627
2628           * [1] audio and video will be dumped with filesink.
2629           * [2] autoplugging is done by just using pad caps.
2630           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
2631           * and the video will be dumped via filesink.
2632           */
2633         if ( player->num_dynamic_pad == 0 )
2634         {
2635                 debug_log("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
2636
2637                 if ( ! __mmplayer_gst_remove_fakesink( player,
2638                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
2639                 {
2640                         /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
2641                          * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
2642                          * source element are not same. To overcome this situation, this function will called
2643                          * several places and several times. Therefore, this is not an error case.
2644                          */
2645                         return;
2646                 }
2647         }
2648
2649         /* create dot before error-return. for debugging */
2650         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-no-more-pad" );
2651
2652         player->no_more_pad = TRUE;
2653
2654         MMPLAYER_FLEAVE();
2655 }
2656
2657 static gboolean
2658 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink) // @
2659 {
2660         GstElement* parent = NULL;
2661
2662         return_val_if_fail(player && player->pipeline, FALSE);
2663
2664         /* if we have no fakesink. this meas we are using decodebin2 which doesn'
2665         t need to add extra fakesink */
2666         return_val_if_fail(fakesink, TRUE);
2667
2668         /* lock */
2669         g_mutex_lock(&player->fsink_lock );
2670
2671         if ( ! fakesink->gst )
2672         {
2673                 goto ERROR;
2674         }
2675
2676         /* get parent of fakesink */
2677         parent = (GstElement*)gst_object_get_parent( (GstObject*)fakesink->gst );
2678         if ( ! parent )
2679         {
2680                 debug_log("fakesink already removed\n");
2681                 goto ERROR;
2682         }
2683
2684         gst_element_set_locked_state( fakesink->gst, TRUE );
2685
2686         /* setting the state to NULL never returns async
2687          * so no need to wait for completion of state transiton
2688          */
2689         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (fakesink->gst, GST_STATE_NULL) )
2690         {
2691                 debug_error("fakesink state change failure!\n");
2692
2693                 /* FIXIT : should I return here? or try to proceed to next? */
2694                 /* return FALSE; */
2695         }
2696
2697         /* remove fakesink from it's parent */
2698         if ( ! gst_bin_remove( GST_BIN( parent ), fakesink->gst ) )
2699         {
2700                 debug_error("failed to remove fakesink\n");
2701
2702                 gst_object_unref( parent );
2703
2704                 goto ERROR;
2705         }
2706
2707         gst_object_unref( parent );
2708
2709         debug_log("state-holder removed\n");
2710
2711         gst_element_set_locked_state( fakesink->gst, FALSE );
2712
2713         g_mutex_unlock( &player->fsink_lock );
2714         return TRUE;
2715
2716 ERROR:
2717         if ( fakesink->gst )
2718         {
2719                 gst_element_set_locked_state( fakesink->gst, FALSE );
2720         }
2721
2722         g_mutex_unlock( &player->fsink_lock );
2723         return FALSE;
2724 }
2725
2726
2727 static void
2728 __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2729 {
2730         GstPad *sinkpad = NULL;
2731         GstCaps* caps = NULL;
2732         GstElement* new_element = NULL;
2733         GstStructure* str = NULL;
2734         const gchar* name = NULL;
2735
2736         mm_player_t* player = (mm_player_t*) data;
2737
2738         MMPLAYER_FENTER();
2739
2740         return_if_fail( element && pad );
2741         return_if_fail( player &&
2742                                         player->pipeline &&
2743                                         player->pipeline->mainbin );
2744
2745
2746         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2747          * num_dynamic_pad will decreased after creating a sinkbin.
2748          */
2749         player->num_dynamic_pad++;
2750         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2751
2752         /* perform autoplugging if dump is disabled */
2753         if ( player->ini.rtsp_do_typefinding )
2754         {
2755                 /* create typefind */
2756                 new_element = gst_element_factory_make( "typefind", NULL );
2757                 if ( ! new_element )
2758                 {
2759                         debug_error("failed to create typefind\n");
2760                         goto ERROR;
2761                 }
2762
2763                 MMPLAYER_SIGNAL_CONNECT(        player,
2764                                                                         G_OBJECT(new_element),
2765                                                                         MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2766                                                                         "have-type",
2767                                                                         G_CALLBACK(__mmplayer_typefind_have_type),
2768                                                                         (gpointer)player);
2769
2770                 /* FIXIT : try to remove it */
2771                 player->have_dynamic_pad = FALSE;
2772         }
2773         else  /* NOTE : use pad's caps directely. if enabled. what I am assuming is there's no elemnt has dynamic pad */
2774         {
2775                 debug_log("using pad caps to autopluging instead of doing typefind\n");
2776
2777                 caps = gst_pad_query_caps( pad, NULL );
2778
2779                 MMPLAYER_CHECK_NULL( caps );
2780
2781                 /* clear  previous result*/
2782                 player->have_dynamic_pad = FALSE;
2783
2784                 str = gst_caps_get_structure(caps, 0);
2785
2786                 if ( ! str )
2787                 {
2788                         debug_error ("cannot get structure from capse.\n");
2789                         goto ERROR;
2790                 }
2791
2792                 name = gst_structure_get_name (str);
2793                 if ( ! name )
2794                 {
2795                         debug_error ("cannot get mimetype from structure.\n");
2796                         goto ERROR;
2797                 }
2798
2799                 if (strstr(name, "video"))
2800                 {
2801                         gint stype = 0;
2802                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
2803
2804                         if (stype == MM_DISPLAY_SURFACE_NULL)
2805                         {
2806                                 if (player->v_stream_caps)
2807                                 {
2808                                         gst_caps_unref(player->v_stream_caps);
2809                                         player->v_stream_caps = NULL;
2810                                 }
2811
2812                                 new_element = gst_element_factory_make("fakesink", NULL);
2813                                 player->num_dynamic_pad--;
2814                                 goto NEW_ELEMENT;
2815                         }
2816                 }
2817
2818                 /* clear  previous result*/
2819                 player->have_dynamic_pad = FALSE;
2820
2821                 if ( !__mmplayer_try_to_plug_decodebin(player, pad, caps))
2822                 {
2823                         debug_error("failed to autoplug for caps");
2824                         goto ERROR;
2825                 }
2826
2827                 /* check if there's dynamic pad*/
2828                 if( player->have_dynamic_pad )
2829                 {
2830                         debug_error("using pad caps assums there's no dynamic pad !\n");
2831                         debug_error("try with enalbing rtsp_do_typefinding\n");
2832                         goto ERROR;
2833                 }
2834
2835                 gst_caps_unref( caps );
2836                 caps = NULL;
2837         }
2838
2839         NEW_ELEMENT:
2840
2841         /* excute new_element if created*/
2842         if ( new_element )
2843         {
2844                 debug_log("adding new element to pipeline\n");
2845
2846                 /* set state to READY before add to bin */
2847                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2848
2849                 /* add new element to the pipeline */
2850                 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2851                 {
2852                         debug_error("failed to add autoplug element to bin\n");
2853                         goto ERROR;
2854                 }
2855
2856                 /* get pad from element */
2857                 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2858                 if ( !sinkpad )
2859                 {
2860                         debug_error("failed to get sinkpad from autoplug element\n");
2861                         goto ERROR;
2862                 }
2863
2864                 /* link it */
2865                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2866                 {
2867                         debug_error("failed to link autoplug element\n");
2868                         goto ERROR;
2869                 }
2870
2871                 gst_object_unref (sinkpad);
2872                 sinkpad = NULL;
2873
2874                 /* run. setting PLAYING here since streamming source is live source */
2875                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2876         }
2877
2878         MMPLAYER_FLEAVE();
2879
2880         return;
2881
2882 STATE_CHANGE_FAILED:
2883 ERROR:
2884         /* FIXIT : take care if new_element has already added to pipeline */
2885         if ( new_element )
2886                 gst_object_unref(GST_OBJECT(new_element));
2887
2888         if ( sinkpad )
2889                 gst_object_unref(GST_OBJECT(sinkpad));
2890
2891         if ( caps )
2892                 gst_object_unref(GST_OBJECT(caps));
2893
2894         /* FIXIT : how to inform this error to MSL ????? */
2895         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2896          * then post an error to application
2897          */
2898 }
2899
2900
2901
2902 /* FIXIT : check indent */
2903 #if 0
2904 static void
2905 __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2906 {
2907   GstPad *sinkpad = NULL;
2908   GstCaps* caps = NULL;
2909   GstElement* new_element = NULL;
2910   enum MainElementID element_id = MMPLAYER_M_NUM;
2911
2912   mm_player_t* player = (mm_player_t*) data;
2913
2914   MMPLAYER_FENTER();
2915
2916   return_if_fail( element && pad );
2917   return_if_fail(  player &&
2918           player->pipeline &&
2919           player->pipeline->mainbin );
2920
2921   debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2922
2923   {
2924     debug_log("using pad caps to autopluging instead of doing typefind\n");
2925     caps = gst_pad_query_caps( pad );
2926     MMPLAYER_CHECK_NULL( caps );
2927     /* clear  previous result*/
2928     player->have_dynamic_pad = FALSE;
2929     new_element = gst_element_factory_make("rtpmp2tdepay", "wfd_rtp_depay");
2930     if ( !new_element )
2931     {
2932       debug_error ( "failed to create wfd rtp depay element\n" );
2933       goto ERROR;
2934     }
2935     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2936     /* add new element to the pipeline */
2937     if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2938     {
2939       debug_log("failed to add autoplug element to bin\n");
2940       goto ERROR;
2941     }
2942     /* get pad from element */
2943     sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2944     if ( !sinkpad )
2945     {
2946       debug_log("failed to get sinkpad from autoplug element\n");
2947       goto ERROR;
2948     }
2949     /* link it */
2950     if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2951     {
2952       debug_log("failed to link autoplug element\n");
2953       goto ERROR;
2954     }
2955     gst_object_unref (sinkpad);
2956     sinkpad = NULL;
2957     pad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "src" );
2958     caps = gst_pad_query_caps( pad );
2959     MMPLAYER_CHECK_NULL( caps );
2960     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2961     /* create typefind */
2962     new_element = gst_element_factory_make( "typefind", NULL );
2963     if ( ! new_element )
2964     {
2965       debug_log("failed to create typefind\n");
2966       goto ERROR;
2967     }
2968
2969     MMPLAYER_SIGNAL_CONNECT(   player,
2970                 G_OBJECT(new_element),
2971                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2972                 "have-type",
2973                 G_CALLBACK(__mmplayer_typefind_have_type),
2974                 (gpointer)player);
2975
2976     player->have_dynamic_pad = FALSE;
2977   }
2978
2979   /* excute new_element if created*/
2980   if ( new_element )
2981   {
2982     debug_log("adding new element to pipeline\n");
2983
2984     /* set state to READY before add to bin */
2985     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2986
2987     /* add new element to the pipeline */
2988     if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2989     {
2990       debug_log("failed to add autoplug element to bin\n");
2991       goto ERROR;
2992     }
2993
2994     /* get pad from element */
2995     sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2996     if ( !sinkpad )
2997     {
2998       debug_log("failed to get sinkpad from autoplug element\n");
2999       goto ERROR;
3000     }
3001
3002     /* link it */
3003     if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
3004     {
3005       debug_log("failed to link autoplug element\n");
3006       goto ERROR;
3007     }
3008
3009     gst_object_unref (sinkpad);
3010     sinkpad = NULL;
3011
3012     /* run. setting PLAYING here since streamming source is live source */
3013     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
3014   }
3015
3016   /* store handle to futher manipulation */
3017   player->pipeline->mainbin[element_id].id = element_id;
3018   player->pipeline->mainbin[element_id].gst = new_element;
3019
3020   MMPLAYER_FLEAVE();
3021
3022   return;
3023
3024 STATE_CHANGE_FAILED:
3025 ERROR:
3026   /* FIXIT : take care if new_element has already added to pipeline */
3027   if ( new_element )
3028     gst_object_unref(GST_OBJECT(new_element));
3029
3030   if ( sinkpad )
3031     gst_object_unref(GST_OBJECT(sinkpad));
3032
3033   if ( caps )
3034     gst_object_unref(GST_OBJECT(caps));
3035
3036   /* FIXIT : how to inform this error to MSL ????? */
3037   /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
3038    * then post an error to application
3039    */
3040 }
3041 #endif
3042
3043 static GstPadProbeReturn
3044 __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
3045 {
3046         debug_log ("pad blocked callback, blocked");
3047         return GST_PAD_PROBE_OK;
3048 }
3049
3050 static void
3051 __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data)
3052 {
3053         mm_player_t* player = NULL;
3054         GstElement* pipeline = NULL;
3055         GstElement* selector = NULL;
3056         GstElement* fakesink = NULL;
3057         GstCaps* caps = NULL;
3058         GstStructure* str = NULL;
3059         const gchar* name = NULL;
3060         GstPad* sinkpad = NULL;
3061         GstPad* srcpad = NULL;
3062         gboolean first_track = FALSE;
3063
3064         enum MainElementID elemId = MMPLAYER_M_NUM;
3065         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
3066
3067         /* check handles */
3068         player = (mm_player_t*)data;
3069
3070         return_if_fail (elem && pad);
3071         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3072
3073         //debug_log ("pad-added signal handling\n");
3074
3075         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3076
3077         /* get mimetype from caps */
3078         caps = gst_pad_query_caps (pad, NULL);
3079         if ( !caps )
3080         {
3081                 debug_error ("cannot get caps from pad.\n");
3082                 goto ERROR;
3083         }
3084
3085         str = gst_caps_get_structure (caps, 0);
3086         if ( ! str )
3087         {
3088                 debug_error ("cannot get structure from capse.\n");
3089                 goto ERROR;
3090         }
3091
3092         name = gst_structure_get_name (str);
3093         if ( ! name )
3094         {
3095                 debug_error ("cannot get mimetype from structure.\n");
3096                 goto ERROR;
3097         }
3098
3099         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3100         //debug_log ("detected mimetype : %s\n", name);
3101
3102         if (strstr(name, "video"))
3103         {
3104                 gint stype = 0;
3105                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
3106
3107                 /* don't make video because of not required, and not support multiple track */
3108                 if (stype == MM_DISPLAY_SURFACE_NULL)
3109                 {
3110                         debug_log ("no video sink by null surface or multiple track");
3111                         gchar *caps_str = gst_caps_to_string(caps);
3112                         if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
3113                         {
3114                                 player->set_mode.video_zc = TRUE;
3115                         }
3116                         MMPLAYER_FREEIF( caps_str );
3117
3118                         if (player->v_stream_caps)
3119                         {
3120                                 gst_caps_unref(player->v_stream_caps);
3121                                 player->v_stream_caps = NULL;
3122                         }
3123
3124                         debug_log ("create fakesink instead of videobin");
3125
3126                         /* fake sink */
3127                         fakesink = gst_element_factory_make ("fakesink", NULL);
3128                         if (fakesink == NULL)
3129                         {
3130                                 debug_error ("ERROR : fakesink create error\n");
3131                                 goto ERROR;
3132                         }
3133
3134                         player->video_fakesink = fakesink;
3135
3136                         gst_bin_add (GST_BIN(pipeline), fakesink);
3137
3138                         // link
3139                         sinkpad = gst_element_get_static_pad (fakesink, "sink");
3140
3141                         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3142                         {
3143                                 debug_warning ("failed to link fakesink\n");
3144                                 gst_object_unref (GST_OBJECT(fakesink));
3145                                 goto ERROR;
3146                         }
3147
3148                         if (player->set_mode.media_packet_video_stream)
3149                                 player->video_cb_probe_id = gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER, __mmplayer_video_stream_probe, player, NULL);
3150
3151                         g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
3152                         g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
3153                         gst_element_set_state (fakesink, GST_STATE_PAUSED);
3154
3155                         goto DONE;
3156                 }
3157 #ifdef _USE_M_V_INPUT_SELECTOR_
3158                 debug_log ("video selector \n");
3159                 elemId = MMPLAYER_M_V_INPUT_SELECTOR;
3160                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
3161 #else
3162                 __mmplayer_gst_decode_callback (elem, pad, player);
3163 #endif
3164         }
3165         else
3166         {
3167                 if (strstr(name, "audio"))
3168                 {
3169                         gint samplerate = 0;
3170                         gint channels = 0;
3171 #ifdef TEST_ES
3172                         if (MMPLAYER_IS_ES_BUFF_SRC(player))
3173                         {
3174                                 __mmplayer_gst_decode_callback (elem, pad, player);
3175                                 return;
3176                         }
3177 #endif
3178                         debug_log ("audio selector \n");
3179                         elemId = MMPLAYER_M_A_INPUT_SELECTOR;
3180                         stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
3181
3182                         gst_structure_get_int (str, "rate", &samplerate);
3183                         gst_structure_get_int (str, "channels", &channels);
3184
3185                         if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
3186                                 /* fake sink */
3187                                 fakesink = gst_element_factory_make ("fakesink", NULL);
3188                                 if (fakesink == NULL)
3189                                 {
3190                                         debug_error ("ERROR : fakesink create error\n");
3191                                         goto ERROR;
3192                                 }
3193
3194                                 gst_bin_add (GST_BIN(pipeline), fakesink);
3195
3196                                 /* link */
3197                                 sinkpad = gst_element_get_static_pad (fakesink, "sink");
3198
3199                                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3200                                 {
3201                                         debug_warning ("failed to link fakesink\n");
3202                                         gst_object_unref (GST_OBJECT(fakesink));
3203                                         goto ERROR;
3204                                 }
3205
3206                                 g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
3207                                 g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
3208                                 gst_element_set_state (fakesink, GST_STATE_PAUSED);
3209
3210                                 goto DONE;
3211                         }
3212                 }
3213                 else if (strstr(name, "text"))
3214                 {
3215                         debug_log ("text selector \n");
3216                         elemId = MMPLAYER_M_T_INPUT_SELECTOR;
3217                         stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
3218                 }
3219                 else
3220                 {
3221                         debug_error ("wrong elem id \n");
3222                         goto ERROR;
3223                 }
3224         }
3225 #ifndef _USE_M_V_INPUT_SELECTOR_ //if not defined
3226         if(strstr(name, "video"))
3227                 return;
3228 #endif
3229         selector = player->pipeline->mainbin[elemId].gst;
3230
3231         if (selector == NULL)
3232         {
3233                 selector = gst_element_factory_make ("input-selector", NULL);
3234                 debug_log ("Creating input-selector\n");
3235                 if (selector == NULL)
3236                 {
3237                         debug_error ("ERROR : input-selector create error\n");
3238                         goto ERROR;
3239                 }
3240                 g_object_set (selector, "sync-streams", TRUE, NULL);
3241
3242                 gst_bin_add (GST_BIN(pipeline), selector);
3243                 gst_element_set_state (selector, GST_STATE_PAUSED);
3244
3245                 player->pipeline->mainbin[elemId].id = elemId;
3246                 player->pipeline->mainbin[elemId].gst = selector;
3247
3248                 first_track = TRUE;
3249                 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK;      // default
3250
3251                 srcpad = gst_element_get_static_pad (selector, "src");
3252
3253 //              debug_log ("blocking %" GST_PTR_FORMAT, srcpad);
3254 //              gst_pad_set_blocked_async (srcpad, TRUE, __mmplayer_gst_selector_blocked, NULL);
3255 //              gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3256 //                      __mmplayer_gst_selector_blocked, NULL, NULL);
3257
3258         }
3259         else
3260         {
3261                 debug_log ("input-selector is already created.\n");
3262                 selector = player->pipeline->mainbin[elemId].gst;
3263         }
3264
3265         // link
3266         debug_log ("Calling request pad with selector %p \n", selector);
3267         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3268
3269         debug_log ("got pad %s:%s from selector", GST_DEBUG_PAD_NAME (sinkpad));
3270
3271         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3272         {
3273                 debug_warning ("failed to link selector\n");
3274                 gst_object_unref (GST_OBJECT(selector));
3275                 goto ERROR;
3276         }
3277
3278         if (first_track)
3279         {
3280                 debug_log ("this is first track --> active track \n");
3281                 g_object_set (selector, "active-pad", sinkpad, NULL);
3282         }
3283
3284         _mmplayer_track_update_info(player, stream_type, sinkpad);
3285
3286
3287 DONE:
3288 ERROR:
3289
3290         if (caps)
3291         {
3292                 gst_caps_unref (caps);
3293         }
3294
3295         if (sinkpad)
3296         {
3297                 gst_object_unref (GST_OBJECT(sinkpad));
3298                 sinkpad = NULL;
3299         }
3300
3301         if (srcpad)
3302         {
3303                 gst_object_unref (GST_OBJECT(srcpad));
3304                 srcpad = NULL;
3305         }
3306
3307         return;
3308 }
3309
3310 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
3311 {
3312         GstPad* srcpad = NULL;
3313         MMHandleType attrs = 0;
3314         gint active_index = 0;
3315
3316         // [link] input-selector :: textbin
3317         srcpad = gst_element_get_static_pad (text_selector, "src");
3318         if (!srcpad)
3319         {
3320                 debug_error("failed to get srcpad from selector\n");
3321                 return;
3322         }
3323
3324         debug_log ("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
3325
3326         active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
3327         if ((active_index != DEFAULT_TRACK) &&
3328                 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE))
3329         {
3330                 debug_warning("failed to change text track\n");
3331                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
3332         }
3333
3334         player->no_more_pad = TRUE;
3335         __mmplayer_gst_decode_callback (text_selector, srcpad, player);
3336
3337         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3338 //      gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3339
3340         debug_log("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3341
3342         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
3343                 player->has_closed_caption = TRUE;
3344
3345         attrs = MMPLAYER_GET_ATTRS(player);
3346         if ( attrs )
3347         {
3348                 mm_attrs_set_int_by_name(attrs, "content_text_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3349                 if (mmf_attrs_commit (attrs))
3350                         debug_error("failed to commit.\n");
3351         }
3352         else
3353         {
3354                 debug_error("cannot get content attribute");
3355         }
3356
3357         if (srcpad)
3358         {
3359                 gst_object_unref ( GST_OBJECT(srcpad) );
3360                 srcpad = NULL;
3361         }
3362 }
3363
3364 int _mmplayer_gst_set_audio_channel(MMHandleType hplayer, MMPlayerAudioChannel ch_idx)
3365 {
3366         int result = MM_ERROR_NONE;
3367
3368         mm_player_t* player = (mm_player_t*)hplayer;
3369         MMPlayerGstElement* mainbin = NULL;
3370         gchar* change_pad_name = NULL;
3371         GstPad* sinkpad = NULL;
3372         GstCaps* caps = NULL;
3373
3374         MMPLAYER_FENTER();
3375
3376         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3377
3378         debug_log ("Change Audio mode to %d\n", ch_idx);
3379         player->use_deinterleave = TRUE;
3380
3381         if ((!player->pipeline) || (!player->pipeline->mainbin))
3382         {
3383                 debug_log ("pre setting : %d\n", ch_idx);
3384
3385                 player->audio_mode.active_pad_index = ch_idx;
3386                 return result;
3387         }
3388
3389         mainbin = player->pipeline->mainbin;
3390
3391         if (mainbin[MMPLAYER_M_A_SELECTOR].gst == NULL)
3392         {
3393                 if (player->max_audio_channels < 2)
3394                 {
3395                         debug_log ("mono channel track only\n");
3396                         return result;
3397                 }
3398
3399                 debug_warning ("selector doesn't exist\n");
3400                 return result;  /* keep playing */
3401         }
3402
3403         debug_log ("total_ch_num : %d\n", player->audio_mode.total_track_num);
3404
3405         if (player->audio_mode.total_track_num < 2)
3406         {
3407                 debug_warning ("there is no another audio path\n");
3408                 return result;  /* keep playing */
3409         }
3410
3411         if ((ch_idx < 0) || (ch_idx >= player->audio_mode.total_track_num))
3412         {
3413                 debug_warning ("Not a proper ch_idx : %d \n", ch_idx);
3414                 return result;  /* keep playing */
3415         }
3416
3417         /*To get the new pad from the selector*/
3418         change_pad_name = g_strdup_printf ("sink%d", ch_idx);
3419         if (change_pad_name == NULL)
3420         {
3421                 debug_warning ("Pad does not exists\n");
3422                 goto ERROR;     /* keep playing */
3423         }
3424
3425         debug_log ("new active pad name: %s\n", change_pad_name);
3426
3427         sinkpad = gst_element_get_static_pad (mainbin[MMPLAYER_M_A_SELECTOR].gst, change_pad_name);
3428         if (sinkpad == NULL)
3429         {
3430                 //result = MM_ERROR_PLAYER_INTERNAL;
3431                 goto ERROR;     /* keep playing */
3432         }
3433
3434         debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3435         g_object_set (mainbin[MMPLAYER_M_A_SELECTOR].gst, "active-pad", sinkpad, NULL);
3436
3437         caps = gst_pad_get_current_caps(sinkpad);
3438         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3439
3440         __mmplayer_set_audio_attrs (player, caps);
3441         player->audio_mode.active_pad_index = ch_idx;
3442
3443 ERROR:
3444
3445         if (sinkpad)
3446                 gst_object_unref (sinkpad);
3447
3448         MMPLAYER_FREEIF(change_pad_name);
3449
3450         MMPLAYER_FLEAVE();
3451         return result;
3452 }
3453
3454
3455
3456 static void
3457 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
3458 {
3459         mm_player_t* player = (mm_player_t*)data;
3460         GstElement* selector = NULL;
3461         GstElement* queue = NULL;
3462
3463         GstPad* srcpad = NULL;
3464         GstPad* sinkpad = NULL;
3465         gchar* caps_str= NULL;
3466
3467         MMPLAYER_FENTER();
3468         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3469
3470         caps_str = gst_caps_to_string(gst_pad_get_current_caps(pad));
3471         debug_log ("deinterleave new caps : %s\n", caps_str);
3472         MMPLAYER_FREEIF(caps_str);
3473
3474         if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL)
3475         {
3476                 debug_error ("ERROR : queue create error\n");
3477                 goto ERROR;
3478         }
3479
3480         g_object_set(G_OBJECT(queue),
3481                                 "max-size-buffers", 10,
3482                                 "max-size-bytes", 0,
3483                                 "max-size-time", (guint64)0,
3484                                 NULL);
3485
3486         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3487
3488         if (!selector)
3489         {
3490                 debug_error("there is no audio channel selector.\n");
3491                 goto ERROR;
3492         }
3493
3494         srcpad = gst_element_get_static_pad (queue, "src");
3495         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3496
3497         debug_log ("link (%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
3498
3499         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3500         {
3501                 debug_warning ("failed to link deinterleave - selector\n");
3502                 goto ERROR;
3503         }
3504
3505         gst_element_set_state (queue, GST_STATE_PAUSED);
3506         player->audio_mode.total_track_num++;
3507
3508 ERROR:
3509
3510         if (srcpad)
3511         {
3512                 gst_object_unref ( GST_OBJECT(srcpad) );
3513                 srcpad = NULL;
3514         }
3515
3516         if (sinkpad)
3517         {
3518                 gst_object_unref ( GST_OBJECT(sinkpad) );
3519                 sinkpad = NULL;
3520         }
3521
3522         MMPLAYER_FLEAVE();
3523         return;
3524 }
3525
3526 static void
3527 __mmplayer_gst_deinterleave_no_more_pads (GstElement *elem, gpointer data)
3528 {
3529         mm_player_t* player = NULL;
3530         GstElement* selector = NULL;
3531         GstPad* sinkpad = NULL;
3532         gint active_index = 0;
3533         gchar* change_pad_name = NULL;
3534         GstCaps* caps = NULL;   // no need to unref
3535
3536         MMPLAYER_FENTER();
3537         player = (mm_player_t*) data;
3538
3539         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3540
3541         if (!selector)
3542         {
3543                 debug_error("there is no audio channel selector.\n");
3544                 goto ERROR;
3545         }
3546
3547         active_index = player->audio_mode.active_pad_index;
3548
3549         if (active_index != DEFAULT_AUDIO_CH)
3550         {
3551                 gint audio_ch = DEFAULT_AUDIO_CH;
3552
3553                 /*To get the new pad from the selector*/
3554                 change_pad_name = g_strdup_printf ("sink%d", active_index);
3555                 if (change_pad_name != NULL)
3556                 {
3557                         sinkpad = gst_element_get_static_pad (selector, change_pad_name);
3558                         if (sinkpad != NULL)
3559                         {
3560                                 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3561                                 g_object_set (selector, "active-pad", sinkpad, NULL);
3562
3563                                 audio_ch = active_index;
3564
3565                                 caps = gst_pad_get_current_caps(sinkpad);
3566                                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3567
3568                                 __mmplayer_set_audio_attrs (player, caps);
3569                         }
3570                 }
3571
3572                 player->audio_mode.active_pad_index = audio_ch;
3573                 debug_log("audio LR info (0:stereo) = %d\n", player->audio_mode.active_pad_index);
3574         }
3575
3576 ERROR:
3577
3578         if (sinkpad)
3579                 gst_object_unref (sinkpad);
3580
3581         MMPLAYER_FLEAVE();
3582         return;
3583 }
3584
3585 static void
3586 __mmplayer_gst_build_deinterleave_path (GstElement *elem, GstPad *pad, gpointer data)
3587 {
3588         mm_player_t* player = NULL;
3589         MMPlayerGstElement *mainbin = NULL;
3590
3591         GstElement* tee = NULL;
3592         GstElement* stereo_queue = NULL;
3593         GstElement* mono_queue = NULL;
3594         GstElement* conv = NULL;
3595         GstElement* filter = NULL;
3596         GstElement* deinterleave = NULL;
3597         GstElement* selector = NULL;
3598
3599         GstPad* srcpad = NULL;
3600         GstPad* selector_srcpad = NULL;
3601         GstPad* sinkpad = NULL;
3602         GstCaps* caps = NULL;
3603
3604         MMPLAYER_FENTER();
3605
3606         /* check handles */
3607         player = (mm_player_t*) data;
3608
3609         return_if_fail( elem && pad );
3610         return_if_fail( player && player->pipeline && player->pipeline->mainbin );
3611
3612         mainbin = player->pipeline->mainbin;
3613
3614         /* tee */
3615         if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL)
3616         {
3617                 debug_error ("ERROR : tee create error\n");
3618                 goto ERROR;
3619         }
3620
3621         mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
3622         mainbin[MMPLAYER_M_A_TEE].gst = tee;
3623
3624         gst_element_set_state (tee, GST_STATE_PAUSED);
3625
3626         /* queue */
3627         srcpad = gst_element_get_request_pad (tee, "src_%u");
3628         if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3629         {
3630                 debug_error ("ERROR : stereo queue create error\n");
3631                 goto ERROR;
3632         }
3633
3634         g_object_set(G_OBJECT(stereo_queue),
3635                                 "max-size-buffers", 10,
3636                                 "max-size-bytes", 0,
3637                                 "max-size-time", (guint64)0,
3638                                 NULL);
3639
3640         player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
3641         player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
3642
3643         if (srcpad)
3644         {
3645                 gst_object_unref (GST_OBJECT(srcpad));
3646                 srcpad = NULL;
3647         }
3648
3649         srcpad = gst_element_get_request_pad (tee, "src_%u");
3650
3651         if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3652         {
3653                 debug_error ("ERROR : mono queue create error\n");
3654                 goto ERROR;
3655         }
3656
3657         g_object_set(G_OBJECT(mono_queue),
3658                                 "max-size-buffers", 10,
3659                                 "max-size-bytes", 0,
3660                                 "max-size-time", (guint64)0,
3661                                 NULL);
3662
3663         player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3664         player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3665
3666         gst_element_set_state (stereo_queue, GST_STATE_PAUSED);
3667         gst_element_set_state (mono_queue, GST_STATE_PAUSED);
3668
3669         /* audioconvert */
3670         srcpad = gst_element_get_static_pad (mono_queue, "src");
3671         if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL)
3672         {
3673                 debug_error ("ERROR : audioconvert create error\n");
3674                 goto ERROR;
3675         }
3676
3677         player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3678         player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3679
3680         /* caps filter */
3681         if (srcpad)
3682         {
3683                 gst_object_unref (GST_OBJECT(srcpad));
3684                 srcpad = NULL;
3685         }
3686         srcpad = gst_element_get_static_pad (conv, "src");
3687
3688         if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL)
3689         {
3690                 debug_error ("ERROR : capsfilter create error\n");
3691                 goto ERROR;
3692         }
3693
3694         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3695         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3696
3697         caps = gst_caps_from_string( "audio/x-raw-int, "
3698                                 "width = (int) 16, "
3699                                 "depth = (int) 16, "
3700                                 "channels = (int) 2");
3701
3702         g_object_set (GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL );
3703         gst_caps_unref( caps );
3704
3705         gst_element_set_state (conv, GST_STATE_PAUSED);
3706         gst_element_set_state (filter, GST_STATE_PAUSED);
3707
3708         /* deinterleave */
3709         if (srcpad)
3710         {
3711                 gst_object_unref (GST_OBJECT(srcpad));
3712                 srcpad = NULL;
3713         }
3714         srcpad = gst_element_get_static_pad (filter, "src");
3715
3716         if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL)
3717         {
3718                 debug_error ("ERROR : deinterleave create error\n");
3719                 goto ERROR;
3720         }
3721
3722         g_object_set (deinterleave, "keep-positions", TRUE, NULL);
3723
3724         MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3725                                                         G_CALLBACK (__mmplayer_gst_deinterleave_pad_added), player);
3726
3727         MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3728                                                         G_CALLBACK (__mmplayer_gst_deinterleave_no_more_pads), player);
3729
3730         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3731         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3732
3733         /* selector */
3734         selector = gst_element_factory_make ("input-selector", "audio-channel-selector");
3735         if (selector == NULL)
3736         {
3737                 debug_error ("ERROR : audio-selector create error\n");
3738                 goto ERROR;
3739         }
3740
3741         g_object_set (selector, "sync-streams", TRUE, NULL);
3742         gst_bin_add (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3743
3744         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3745         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3746
3747         selector_srcpad = gst_element_get_static_pad (selector, "src");
3748
3749         debug_log ("blocking %" GST_PTR_FORMAT, selector_srcpad);
3750         //gst_pad_set_blocked_async (selector_srcpad, TRUE, __mmplayer_gst_selector_blocked, NULL);
3751         gst_pad_add_probe(selector_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3752                         __mmplayer_gst_selector_blocked, NULL, NULL);
3753
3754         if (srcpad)
3755         {
3756                 gst_object_unref (GST_OBJECT(srcpad));
3757                 srcpad = NULL;
3758         }
3759
3760         srcpad = gst_element_get_static_pad(stereo_queue, "src");
3761         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3762
3763         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3764         {
3765                 debug_warning ("failed to link queue_stereo - selector\n");
3766                 goto ERROR;
3767         }
3768
3769         player->audio_mode.total_track_num++;
3770
3771         g_object_set (selector, "active-pad", sinkpad, NULL);
3772         gst_element_set_state (deinterleave, GST_STATE_PAUSED);
3773         gst_element_set_state (selector, GST_STATE_PAUSED);
3774
3775         __mmplayer_gst_decode_callback (selector, selector_srcpad, player);
3776
3777         debug_log ("unblocking %" GST_PTR_FORMAT, selector_srcpad);
3778 //      gst_pad_set_blocked_async (selector_srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3779
3780 ERROR:
3781         if (sinkpad)
3782         {
3783                 gst_object_unref (GST_OBJECT(sinkpad));
3784                 sinkpad = NULL;
3785         }
3786
3787         if (srcpad)
3788         {
3789                 gst_object_unref (GST_OBJECT(srcpad));
3790                 srcpad = NULL;
3791         }
3792
3793         if (selector_srcpad)
3794         {
3795                 gst_object_unref (GST_OBJECT(selector_srcpad));
3796                 selector_srcpad = NULL;
3797         }
3798
3799         MMPLAYER_FLEAVE();
3800         return;
3801 }
3802
3803 static void
3804 __mmplayer_gst_decode_no_more_pads (GstElement *elem, gpointer data)
3805 {
3806         mm_player_t* player = NULL;
3807         GstPad* srcpad = NULL;
3808 #ifdef _USE_M_V_INPUT_SELECTOR_
3809         GstElement* video_selector = NULL;
3810 #endif
3811         GstElement* audio_selector = NULL;
3812         GstElement* text_selector = NULL;
3813         MMHandleType attrs = 0;
3814         gint active_index = 0;
3815         gint64 dur_bytes = 0L;
3816
3817         player = (mm_player_t*) data;
3818
3819         debug_log("no-more-pad signal handling\n");
3820
3821         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3822                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
3823         {
3824                 debug_warning("no need to go more");
3825
3826                 if (player->pp_rebuilding)
3827                 {
3828                         player->pp_rebuilding = FALSE;
3829                         MMPLAYER_PLAYBACK_UNLOCK(player);
3830                 }
3831
3832                 return;
3833         }
3834
3835         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3836                 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3837                 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3838                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
3839         {
3840                 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
3841
3842                 if (NULL == player->streamer)
3843                 {
3844                         debug_warning("invalid state for buffering");
3845                         goto ERROR;
3846                 }
3847
3848                 gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
3849                 guint buffer_bytes = init_buffering_time * ESTIMATED_BUFFER_UNIT;
3850
3851                 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
3852                 debug_log("[Decodebin2] set use-buffering on Q2 (pre buffer time: %d sec, buffer size : %d)\n", (gint)init_buffering_time, buffer_bytes);
3853
3854                 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
3855
3856                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
3857                         debug_error("fail to get duration.\n");
3858
3859                 // enable use-buffering on queue2 instead of multiqueue (ex)audio only streaming
3860                 // use file information was already set on Q2 when it was created.
3861                 __mm_player_streaming_set_queue2(player->streamer,
3862                                                 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
3863                                                 TRUE,                                                           // use_buffering
3864                                                 buffer_bytes,
3865                                                 init_buffering_time,
3866                                                 1.0,                                                            // low percent
3867                                                 player->ini.http_buffering_limit,       // high percent
3868                                                 FALSE,
3869                                                 NULL,
3870                                                 ((dur_bytes>0)?((guint64)dur_bytes):0));
3871         }
3872 #ifdef _USE_M_V_INPUT_SELECTOR_
3873         video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
3874 #endif
3875         audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
3876         text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3877 #ifdef _USE_M_V_INPUT_SELECTOR_
3878         if (video_selector)
3879         {
3880                 // the first track can be played only. not support track changing yet.
3881                 // [link] input-selector :: videobin
3882                 srcpad = gst_element_get_static_pad (video_selector, "src");
3883                 if (!srcpad)
3884                 {
3885                         debug_error("failed to get srcpad from video selector\n");
3886                         goto ERROR;
3887                 }
3888
3889                 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3890                 if ((!text_selector) && (!audio_selector))
3891                         player->no_more_pad = TRUE;
3892
3893                 __mmplayer_gst_decode_callback (video_selector, srcpad, player);
3894
3895                 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3896 //              gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3897
3898                 debug_log("Total video tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].total_track_num);
3899
3900                 gst_object_unref ( GST_OBJECT(srcpad) );
3901                 srcpad = NULL;
3902         }
3903         else
3904         {
3905                 if ((player->pipeline->videobin) && (player->pipeline->videobin[MMPLAYER_V_BIN].gst))
3906                 {
3907                         debug_log ("There is no video track : remove videobin");
3908
3909                         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN );
3910                         __mmplayer_del_sink ( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
3911
3912                         MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->videobin, MMPLAYER_V_BIN );
3913                         MMPLAYER_FREEIF ( player->pipeline->videobin )
3914                 }
3915         }
3916 #endif
3917         if (audio_selector)
3918         {
3919                 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
3920                 if ((active_index != DEFAULT_TRACK) &&
3921                         (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE))
3922                 {
3923                         debug_warning("failed to change audio track\n");
3924                         player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
3925                 }
3926
3927                 // [link] input-selector :: audiobin
3928                 srcpad = gst_element_get_static_pad (audio_selector, "src");
3929                 if (!srcpad)
3930                 {
3931                         debug_error("failed to get srcpad from selector\n");
3932                         goto ERROR;
3933                 }
3934
3935                 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3936                 if (!text_selector)
3937                         player->no_more_pad = TRUE;
3938
3939                 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2))
3940                 {
3941                         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3942 //                      gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3943
3944                         __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
3945                 }
3946                 else
3947                 {
3948                         __mmplayer_gst_decode_callback (audio_selector, srcpad, player);
3949
3950                         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3951 //                      gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3952                 }
3953
3954                 debug_log("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3955
3956                 attrs = MMPLAYER_GET_ATTRS(player);
3957                 if ( attrs )
3958                 {
3959                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3960                         if (mmf_attrs_commit (attrs))
3961                                 debug_error("failed to commit.\n");
3962                 }
3963                 else
3964                 {
3965                         debug_error("cannot get content attribute");
3966                 }
3967         }
3968         else
3969         {
3970                 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst))
3971                 {
3972                         debug_log ("There is no audio track : remove audiobin");
3973
3974                         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN );
3975                         __mmplayer_del_sink ( player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst );
3976
3977                         MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->audiobin, MMPLAYER_A_BIN );
3978                         MMPLAYER_FREEIF ( player->pipeline->audiobin )
3979                 }
3980
3981                 if (player->num_dynamic_pad == 0)
3982                 {
3983                         __mmplayer_pipeline_complete (NULL, player);
3984                 }
3985         }
3986
3987 #ifdef TEST_ES
3988         if (!MMPLAYER_IS_ES_BUFF_SRC(player))
3989 #endif
3990         {
3991                 if (text_selector)
3992                 {
3993                         __mmplayer_handle_text_decode_path(player, text_selector);
3994                 }
3995         }
3996
3997         MMPLAYER_FLEAVE();
3998
3999 ERROR:
4000         if (srcpad)
4001         {
4002                 gst_object_unref ( GST_OBJECT(srcpad) );
4003                 srcpad = NULL;
4004         }
4005
4006         if (player->pp_rebuilding)
4007         {
4008                 player->pp_rebuilding = FALSE;
4009                 MMPLAYER_PLAYBACK_UNLOCK(player);
4010         }
4011 }
4012
4013 static void
4014 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // @
4015 {
4016         mm_player_t* player = NULL;
4017         MMHandleType attrs = 0;
4018         GstElement* pipeline = NULL;
4019         GstCaps* caps = NULL;
4020         gchar* caps_str = NULL;
4021         GstStructure* str = NULL;
4022         const gchar* name = NULL;
4023         GstPad* sinkpad = NULL;
4024         GstElement* sinkbin = NULL;
4025         gboolean reusing = FALSE;
4026         GstElement *text_selector = NULL;
4027
4028         /* check handles */
4029         player = (mm_player_t*) data;
4030
4031         return_if_fail( elem && pad );
4032         return_if_fail(player && player->pipeline && player->pipeline->mainbin);
4033
4034         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
4035
4036         attrs = MMPLAYER_GET_ATTRS(player);
4037         if ( !attrs )
4038         {
4039                 debug_error("cannot get content attribute\n");
4040                 goto ERROR;
4041         }
4042
4043         /* get mimetype from caps */
4044         caps = gst_pad_query_caps( pad, NULL );
4045         if ( !caps )
4046         {
4047                 debug_error("cannot get caps from pad.\n");
4048                 goto ERROR;
4049         }
4050         caps_str = gst_caps_to_string(caps);
4051
4052         str = gst_caps_get_structure( caps, 0 );
4053         if ( ! str )
4054         {
4055                 debug_error("cannot get structure from capse.\n");
4056                 goto ERROR;
4057         }
4058
4059         name = gst_structure_get_name(str);
4060         if ( ! name )
4061         {
4062                 debug_error("cannot get mimetype from structure.\n");
4063                 goto ERROR;
4064         }
4065
4066         //debug_log("detected mimetype : %s\n", name);
4067
4068         if (strstr(name, "audio"))
4069         {
4070                 if (player->pipeline->audiobin == NULL)
4071                 {
4072                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player))
4073                         {
4074                                 debug_error("failed to create audiobin. continuing without audio\n");
4075                                 goto ERROR;
4076                         }
4077
4078                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
4079                         debug_log("creating audiosink bin success\n");
4080                 }
4081                 else
4082                 {
4083                         reusing = TRUE;
4084                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
4085                         debug_log("reusing audiobin\n");
4086                         _mmplayer_update_content_attrs( player, ATTR_AUDIO);
4087                 }
4088
4089                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
4090                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
4091
4092                 player->audiosink_linked  = 1;
4093
4094                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
4095                 if ( !sinkpad )
4096                 {
4097                         debug_error("failed to get pad from sinkbin\n");
4098                         goto ERROR;
4099                 }
4100         }
4101         else if (strstr(name, "video"))
4102         {
4103                 if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
4104                 {
4105                         player->set_mode.video_zc = TRUE;
4106                 }
4107
4108                 if (player->pipeline->videobin == NULL)
4109                 {
4110                         /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
4111                         /* get video surface type */
4112                         int surface_type = 0;
4113                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
4114
4115                         if (surface_type == MM_DISPLAY_SURFACE_NULL)
4116                         {
4117                                 debug_log("not make videobin because it dose not want\n");
4118                                 goto ERROR;
4119                         }
4120
4121                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type) )
4122                         {
4123                                 debug_error("failed to create videobin. continuing without video\n");
4124                                 goto ERROR;
4125                         }
4126
4127                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
4128                         debug_log("creating videosink bin success\n");
4129                 }
4130                 else
4131                 {
4132                         reusing = TRUE;
4133                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
4134                         debug_log("re-using videobin\n");
4135                         _mmplayer_update_content_attrs( player, ATTR_VIDEO);
4136                 }
4137
4138                 /* FIXIT : track number shouldn't be hardcoded */
4139                 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 1);
4140                 player->videosink_linked  = 1;
4141
4142                 /* NOTE : intermediate code before doing H/W subtitle compositon */
4143                 if ( player->use_textoverlay && player->play_subtitle )
4144                 {
4145                         debug_log("using textoverlay for external subtitle");
4146                         /* check text bin has created well */
4147                         if ( player->pipeline && player->pipeline->textbin )
4148                         {
4149                                 /* get sinkpad from textoverlay */
4150                                 sinkpad = gst_element_get_static_pad(
4151                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
4152                                         "video_sink" );
4153                                 if ( ! sinkpad )
4154                                 {
4155                                         debug_error("failed to get sink pad from textoverlay");
4156                                         goto ERROR;
4157                                 }
4158
4159                                 /* link new pad with textoverlay first */
4160                                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
4161                                 {
4162                                         debug_error("failed to get pad from sinkbin\n");
4163                                         goto ERROR;
4164                                 }
4165
4166                                 gst_object_unref(sinkpad);
4167                                 sinkpad = NULL;
4168
4169                                 /* alright, override pad to textbin.src for futher link */
4170                                 pad = gst_element_get_static_pad(
4171                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
4172                                         "src" );
4173                                 if ( ! pad )
4174                                 {
4175                                         debug_error("failed to get sink pad from textoverlay");
4176                                         goto ERROR;
4177                                 }
4178                         }
4179                         else
4180                         {
4181                                 debug_error("should not reach here.");
4182                                 goto ERROR;
4183                         }
4184                 }
4185
4186                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
4187                 if ( !sinkpad )
4188                 {
4189                         debug_error("failed to get pad from sinkbin\n");
4190                         goto ERROR;
4191                 }
4192         }
4193         else if (strstr(name, "text"))
4194         {
4195                 if (player->pipeline->textbin == NULL)
4196                 {
4197                         MMPlayerGstElement* mainbin = NULL;
4198
4199                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
4200                         {
4201                                 debug_error("failed to create textbin. continuing without text\n");
4202                                 goto ERROR;
4203                         }
4204
4205                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
4206                         debug_log("creating textsink bin success\n");
4207
4208                         /* FIXIT : track number shouldn't be hardcoded */
4209                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
4210
4211                         player->textsink_linked  = 1;
4212                         debug_msg("player->textsink_linked set to 1\n");
4213
4214                         sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "text_sink" );
4215                         if ( !sinkpad )
4216                         {
4217                                 debug_error("failed to get pad from sinkbin\n");
4218                                 goto ERROR;
4219                         }
4220
4221                         mainbin = player->pipeline->mainbin;
4222
4223                         if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst)
4224                         {
4225                           /* input selector */
4226                           text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
4227                           if ( !text_selector )
4228                           {
4229                             debug_error ( "failed to create subtitle input selector element\n" );
4230                             goto ERROR;
4231                           }
4232                           g_object_set (text_selector, "sync-streams", TRUE, NULL);
4233
4234                           mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
4235                           mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
4236
4237                           /* warm up */
4238                           if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_READY))
4239                           {
4240                             debug_error("failed to set state(READY) to sinkbin\n");
4241                             goto ERROR;
4242                           }
4243
4244                           if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector))
4245                           {
4246                             debug_warning("failed to add subtitle input selector\n");
4247                             goto ERROR;
4248                           }
4249
4250                           debug_log ("created element input-selector");
4251
4252                         }
4253                         else
4254                         {
4255                           debug_log ("already having subtitle input selector");
4256                           text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
4257                         }
4258                 }
4259
4260                 else
4261                 {
4262                         if (!player->textsink_linked)
4263                         {
4264                                 debug_log("re-using textbin\n");
4265
4266                                 reusing = TRUE;
4267                                 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
4268
4269                                 player->textsink_linked  = 1;
4270                                 debug_msg("player->textsink_linked set to 1\n");
4271                         }
4272                         else
4273                         {
4274                                 debug_log("ignoring internal subtutle since external subtitle is available");
4275                         }
4276                 }
4277         }
4278         else
4279         {
4280                 debug_warning("unknown type of elementary stream! ignoring it...\n");
4281                 goto ERROR;
4282         }
4283
4284         if ( sinkbin )
4285         {
4286                 if(!reusing)
4287                 {
4288                         /* warm up */
4289                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_READY ) )
4290                         {
4291                                 debug_error("failed to set state(READY) to sinkbin\n");
4292                                 goto ERROR;
4293                         }
4294
4295                         /* Added for multi audio support to avoid adding audio bin again*/
4296                         /* add */
4297                         if ( FALSE == gst_bin_add( GST_BIN(pipeline), sinkbin ) )
4298                         {
4299                                 debug_error("failed to add sinkbin to pipeline\n");
4300                                 goto ERROR;
4301                         }
4302                 }
4303
4304                 /* link */
4305                 if (GST_PAD_LINK_OK != GST_PAD_LINK (pad, sinkpad))
4306                 {
4307                         debug_error("failed to get pad from sinkbin\n");
4308                         goto ERROR;
4309                 }
4310
4311                 if (!reusing)
4312                 {
4313                         /* run */
4314                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (sinkbin, GST_STATE_PAUSED))
4315                         {
4316                                 debug_error("failed to set state(PLAYING) to sinkbin\n");
4317                                 goto ERROR;
4318                         }
4319
4320                         if (text_selector)
4321                         {
4322                           if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_PAUSED))
4323                           {
4324                             debug_error("failed to set state(READY) to sinkbin\n");
4325                             goto ERROR;
4326                           }
4327                         }
4328                 }
4329
4330                 gst_object_unref (sinkpad);
4331                 sinkpad = NULL;
4332         }
4333
4334         debug_log ("linking sink bin success\n");
4335
4336         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
4337          * streaming task. if the task blocked, then buffer will not flow to the next element
4338          * ( autoplugging element ). so this is special hack for streaming. please try to remove it
4339          */
4340         /* dec stream count. we can remove fakesink if it's zero */
4341         if (player->num_dynamic_pad)
4342                 player->num_dynamic_pad--;
4343
4344         debug_log ("no more pads: %d stream count dec : %d (num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
4345
4346         if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
4347         {
4348                 __mmplayer_pipeline_complete (NULL, player);
4349         }
4350
4351         /* FIXIT : please leave a note why this code is needed */
4352         if(MMPLAYER_IS_WFD_STREAMING( player ))
4353         {
4354                 player->no_more_pad = TRUE;
4355         }
4356
4357 ERROR:
4358
4359         MMPLAYER_FREEIF(caps_str);
4360
4361         if ( caps )
4362                 gst_caps_unref( caps );
4363
4364         if ( sinkpad )
4365                 gst_object_unref(GST_OBJECT(sinkpad));
4366
4367         /* flusing out new attributes */
4368         if (  mmf_attrs_commit ( attrs ) )
4369         {
4370                 debug_error("failed to comit attributes\n");
4371         }
4372
4373         return;
4374 }
4375
4376 static gboolean
4377 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
4378 {
4379         int pro_value = 0; // in the case of expection, default will be returned.
4380         int dest_angle = rotation_angle;
4381         int rotation_type = -1;
4382         #define ROTATION_USING_SINK 0
4383         #define ROTATION_USING_CUSTOM 1
4384         #define ROTATION_USING_FLIP     2
4385
4386         return_val_if_fail(player, FALSE);
4387         return_val_if_fail(value, FALSE);
4388         return_val_if_fail(rotation_angle >= 0, FALSE);
4389
4390         if (rotation_angle >= 360)
4391         {
4392                 dest_angle = rotation_angle - 360;
4393         }
4394
4395         /* chech if supported or not */
4396         if ( dest_angle % 90 )
4397         {
4398                 debug_log("not supported rotation angle = %d", rotation_angle);
4399                 return FALSE;
4400         }
4401
4402         /*
4403           * xvimagesink only     (A)
4404           * custom_convert - no xv (e.g. memsink, evasimagesink  (B)
4405           * videoflip - avsysmemsink (C)
4406           */
4407         if (player->set_mode.video_zc)
4408         {
4409                 if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
4410                 {
4411                         rotation_type = ROTATION_USING_CUSTOM;
4412                 }
4413                 else // A
4414                 {
4415                         rotation_type = ROTATION_USING_SINK;
4416                 }
4417         }
4418         else
4419         {
4420                 int surface_type = 0;
4421                 rotation_type = ROTATION_USING_FLIP;
4422
4423                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
4424                 debug_log("check display surface type attribute: %d", surface_type);
4425
4426                 if ((surface_type == MM_DISPLAY_SURFACE_X) ||
4427                         (surface_type == MM_DISPLAY_SURFACE_EVAS && !strcmp(player->ini.videosink_element_evas, "evaspixmapsink")))
4428                 {
4429                         rotation_type = ROTATION_USING_SINK;
4430                 }
4431                 else
4432                 {
4433                         rotation_type = ROTATION_USING_FLIP; //C
4434                 }
4435
4436                 debug_log("using %d type for rotation", rotation_type);
4437         }
4438
4439         /* get property value for setting */
4440         switch(rotation_type)
4441         {
4442                 case ROTATION_USING_SINK: // xvimagesink, pixmap
4443                         {
4444                                 switch (dest_angle)
4445                                 {
4446                                         case 0:
4447                                                 break;
4448                                         case 90:
4449                                                 pro_value = 3; // clockwise 90
4450                                                 break;
4451                                         case 180:
4452                                                 pro_value = 2;
4453                                                 break;
4454                                         case 270:
4455                                                 pro_value = 1; // counter-clockwise 90
4456                                                 break;
4457                                 }
4458                         }
4459                         break;
4460                 case ROTATION_USING_CUSTOM:
4461                         {
4462                                 gchar *ename = NULL;
4463                                 ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
4464
4465                                 if (g_strrstr(ename, "fimcconvert"))
4466                                 {
4467                                         switch (dest_angle)
4468                                         {
4469                                                 case 0:
4470                                                         break;
4471                                                 case 90:
4472                                                         pro_value = 90; // clockwise 90
4473                                                         break;
4474                                                 case 180:
4475                                                         pro_value = 180;
4476                                                         break;
4477                                                 case 270:
4478                                                         pro_value = 270; // counter-clockwise 90
4479                                                         break;
4480                                         }
4481                                 }
4482                         }
4483                         break;
4484                 case ROTATION_USING_FLIP: // videoflip
4485                         {
4486                                         switch (dest_angle)
4487                                         {
4488
4489                                                 case 0:
4490                                                         break;
4491                                                 case 90:
4492                                                         pro_value = 1; // clockwise 90
4493                                                         break;
4494                                                 case 180:
4495                                                         pro_value = 2;
4496                                                         break;
4497                                                 case 270:
4498                                                         pro_value = 3; // counter-clockwise 90
4499                                                         break;
4500                                         }
4501                         }
4502                         break;
4503         }
4504
4505         debug_log("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
4506
4507         *value = pro_value;
4508
4509         return TRUE;
4510 }
4511
4512 int
4513 _mmplayer_update_video_param(mm_player_t* player) // @
4514 {
4515         MMHandleType attrs = 0;
4516         int surface_type = 0;
4517         int org_angle = 0; // current supported angle values are 0, 90, 180, 270
4518         int user_angle = 0;
4519         int user_angle_type= 0;
4520         int rotation_value = 0;
4521         gchar *org_orient = NULL;
4522
4523         MMPLAYER_FENTER();
4524
4525         /* check video sinkbin is created */
4526         return_val_if_fail ( player &&
4527                 player->pipeline &&
4528                 player->pipeline->videobin &&
4529                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
4530                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4531                 MM_ERROR_PLAYER_NOT_INITIALIZED );
4532
4533         attrs = MMPLAYER_GET_ATTRS(player);
4534         if ( !attrs )
4535         {
4536                 debug_error("cannot get content attribute");
4537                 return MM_ERROR_PLAYER_INTERNAL;
4538         }
4539
4540         /* update user roation */
4541         mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
4542
4543         /* get angle with user type */
4544         switch(user_angle_type)
4545         {
4546                 case MM_DISPLAY_ROTATION_NONE:
4547                         user_angle = 0;
4548                         break;
4549                 case MM_DISPLAY_ROTATION_90: // counter-clockwise 90
4550                         user_angle = 270;
4551                         break;
4552                 case MM_DISPLAY_ROTATION_180:
4553                         user_angle = 180;
4554                         break;
4555                 case MM_DISPLAY_ROTATION_270: // clockwise 90
4556                         user_angle = 90;
4557                         break;
4558         }
4559
4560         /* get original orientation */
4561         mm_attrs_get_string_by_name(attrs, "content_video_orientation", &org_orient);
4562
4563         if (org_orient)
4564         {
4565                 if (!strcmp (org_orient, "rotate-90"))
4566                         org_angle = 90;
4567                 else if (!strcmp (org_orient, "rotate-180"))
4568                         org_angle = 180;
4569                 else if (!strcmp (org_orient, "rotate-270"))
4570                         org_angle = 270;
4571                 else
4572                         debug_log ("original rotation is %s", org_orient);
4573         }
4574         else
4575         {
4576                 debug_log ("content_video_orientation get fail");
4577         }
4578
4579         debug_log("check user angle: %d, orientation: %d", user_angle, org_angle);
4580
4581         /* check video stream callback is used */
4582         if(!player->set_mode.media_packet_video_stream && player->use_video_stream )
4583         {
4584                 if (player->set_mode.video_zc)
4585                 {
4586                         gchar *ename = NULL;
4587                         int width = 0;
4588                         int height = 0;
4589
4590                         mm_attrs_get_int_by_name(attrs, "display_width", &width);
4591                         mm_attrs_get_int_by_name(attrs, "display_height", &height);
4592
4593                         /* resize video frame with requested values for fimcconvert */
4594                         ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
4595
4596                         if (ename && g_strrstr(ename, "fimcconvert"))
4597                         {
4598                                 if (width)
4599                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
4600
4601                                 if (height)
4602                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
4603
4604                                 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
4605                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
4606
4607                                 /* get rotation value to set */
4608                                 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4609
4610                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "rotate", rotation_value, NULL);
4611
4612                                 debug_log("updating fimcconvert - r[%d], w[%d], h[%d]", rotation_value, width, height);
4613                         }
4614                 }
4615                 else
4616                 {
4617                         debug_log("using video stream callback with memsink. player handle : [%p]", player);
4618
4619                         /* get rotation value to set */
4620                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4621
4622                         g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
4623                 }
4624
4625                 return MM_ERROR_NONE;
4626         }
4627
4628         /* update display surface */
4629         mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
4630         debug_log("check display surface type attribute: %d", surface_type);
4631
4632         /* configuring display */
4633         switch ( surface_type )
4634         {
4635                 case MM_DISPLAY_SURFACE_X:
4636                 {
4637                         /* ximagesink or xvimagesink */
4638                         void *surface = NULL;
4639                         double zoom = 0;
4640                         int display_method = 0;
4641                         int roi_x = 0;
4642                         int roi_y = 0;
4643                         int roi_w = 0;
4644                         int roi_h = 0;
4645                         int src_crop_x = 0;
4646                         int src_crop_y = 0;
4647                         int src_crop_w = 0;
4648                         int src_crop_h = 0;
4649                         int force_aspect_ratio = 0;
4650                         gboolean visible = TRUE;
4651
4652 #ifdef HAVE_WAYLAND
4653                         /*set wl_display*/
4654                         void* wl_display = NULL;
4655                         GstContext *context = NULL;
4656                         int wl_window_x = 0;
4657                         int wl_window_y = 0;
4658                         int wl_window_width = 0;
4659                         int wl_window_height = 0;
4660
4661                         mm_attrs_get_data_by_name(attrs, "wl_display", &wl_display);
4662                         if (wl_display)
4663                                 context = gst_wayland_display_handle_context_new(wl_display);
4664                         if (context)
4665                                 gst_element_set_context(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), context);
4666
4667                         /*It should be set after setting window*/
4668                         mm_attrs_get_int_by_name(attrs, "wl_window_render_x", &wl_window_x);
4669                         mm_attrs_get_int_by_name(attrs, "wl_window_render_y", &wl_window_y);
4670                         mm_attrs_get_int_by_name(attrs, "wl_window_render_width", &wl_window_width);
4671                         mm_attrs_get_int_by_name(attrs, "wl_window_render_height", &wl_window_height);
4672 #endif
4673                         /* common case if using x surface */
4674                         mm_attrs_get_data_by_name(attrs, "display_overlay", &surface);
4675                         if ( surface )
4676                         {
4677 #ifdef HAVE_WAYLAND
4678                                 int wl_surface = 0;
4679                                 wl_surface = (int*)surface;
4680                                 debug_log("set video param : xid %p", (int*)surface);
4681                                 if (wl_surface)
4682                                 {
4683                                         gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), (int*)surface );
4684                                         /* After setting window handle, set render      rectangle */
4685                                         gst_video_overlay_set_render_rectangle(
4686                                                  GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ),
4687                                                  wl_window_x,wl_window_y,wl_window_width,wl_window_height);
4688                                 }
4689 #else // HAVE_X11
4690                                 int xwin_id = 0;
4691                                 xwin_id = *(int*)surface;
4692                                 debug_log("set video param : xid %p", *(int*)surface);
4693                                 if (xwin_id)
4694                                 {
4695                                         gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)surface );
4696                                 }
4697 #endif
4698                         }
4699                         else
4700                         {
4701                                 /* FIXIT : is it error case? */
4702                                 debug_warning("still we don't have xid on player attribute. create it's own surface.");
4703                         }
4704
4705                         /* if xvimagesink */
4706                         if (!strcmp(player->ini.videosink_element_x,"xvimagesink"))
4707                         {
4708                                 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
4709                                 mm_attrs_get_double_by_name(attrs, "display_zoom", &zoom);
4710                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4711                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_x", &src_crop_x);
4712                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_y", &src_crop_y);
4713                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_width", &src_crop_w);
4714                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_height", &src_crop_h);
4715                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
4716                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
4717                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
4718                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
4719                                 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4720                                 #define DEFAULT_DISPLAY_MODE    2       // TV only, PRI_VIDEO_OFF_AND_SEC_VIDEO_FULL_SCREEN
4721
4722                                 /* setting for cropping media source */
4723                                 if (src_crop_w && src_crop_h)
4724                                 {
4725                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4726                                                 "src-crop-x", src_crop_x,
4727                                                 "src-crop-y", src_crop_y,
4728                                                 "src-crop-w", src_crop_w,
4729                                                 "src-crop-h", src_crop_h,
4730                                                 NULL );
4731                                 }
4732
4733                                 /* setting for ROI mode */
4734                                 if (display_method == 5)        // 5 for ROI mode
4735                                 {
4736                                         int roi_mode = 0;
4737                                         mm_attrs_get_int_by_name(attrs, "display_roi_mode", &roi_mode);
4738                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4739                                                 "dst-roi-mode", roi_mode,
4740                                                 "dst-roi-x", roi_x,
4741                                                 "dst-roi-y", roi_y,
4742                                                 "dst-roi-w", roi_w,
4743                                                 "dst-roi-h", roi_h,
4744                                                 NULL );
4745                                         /* get rotation value to set,
4746                                            do not use org_angle because ROI mode in xvimagesink needs both a rotation value and an orientation value */
4747                                         __mmplayer_get_property_value_for_rotation(player, user_angle, &rotation_value);
4748                                 }
4749                                 else
4750                                 {
4751                                         /* get rotation value to set */
4752                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4753                                 }
4754
4755                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4756                                         "force-aspect-ratio", force_aspect_ratio,
4757                                         "zoom", (float)zoom,
4758                                         "orientation", org_angle/90, // setting for orientation of media, it is used for ROI/ZOOM feature in xvimagesink
4759                                         "rotate", rotation_value,
4760                                         "handle-events", TRUE,
4761                                         "display-geometry-method", display_method,
4762                                         "draw-borders", FALSE,
4763                                         "visible", visible,
4764                                         "display-mode", DEFAULT_DISPLAY_MODE,
4765                                         NULL );
4766
4767                                 debug_log("set video param : zoom %lf, rotate %d, method %d visible %d", zoom, rotation_value, display_method, visible);
4768                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d", roi_x, roi_y, roi_w, roi_h );
4769                                 debug_log("set video param : force aspect ratio %d, display mode %d", force_aspect_ratio, DEFAULT_DISPLAY_MODE);
4770                         }
4771                 }
4772                 break;
4773                 case MM_DISPLAY_SURFACE_EVAS:
4774                 {
4775                         void *object = NULL;
4776                         int scaling = 0;
4777                         gboolean visible = TRUE;
4778                         int display_method = 0;
4779
4780                         /* common case if using evas surface */
4781                         mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
4782                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4783                         mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
4784                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4785
4786                         /* if evasimagesink */
4787                         if (!strcmp(player->ini.videosink_element_evas,"evasimagesink"))
4788                         {
4789                                 if (object)
4790                                 {
4791                                         /* if it is evasimagesink, we are not supporting rotation */
4792                                         if (user_angle_type!=MM_DISPLAY_ROTATION_NONE)
4793                                         {
4794                                                 mm_attrs_set_int_by_name(attrs, "display_rotation", MM_DISPLAY_ROTATION_NONE);
4795                                                 if (mmf_attrs_commit (attrs)) /* return -1 if error */
4796                                                         debug_error("failed to commit\n");
4797                                                 debug_warning("unsupported feature");
4798                                                 return MM_ERROR_NOT_SUPPORT_API;
4799                                         }
4800                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4801                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4802                                                         "evas-object", object,
4803                                                         "visible", visible,
4804                                                         "display-geometry-method", display_method,
4805                                                         "rotate", rotation_value,
4806                                                         NULL);
4807                                         debug_log("set video param : method %d", display_method);
4808                                         debug_log("set video param : evas-object %x, visible %d", object, visible);
4809                                         debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
4810                                 }
4811                                 else
4812                                 {
4813                                         debug_error("no evas object");
4814                                         return MM_ERROR_PLAYER_INTERNAL;
4815                                 }
4816
4817
4818                                 /* if evasimagesink using converter */
4819                                 if (player->set_mode.video_zc && player->pipeline->videobin[MMPLAYER_V_CONV].gst)
4820                                 {
4821                                         int width = 0;
4822                                         int height = 0;
4823                                         int no_scaling = !scaling;
4824
4825                                         mm_attrs_get_int_by_name(attrs, "display_width", &width);
4826                                         mm_attrs_get_int_by_name(attrs, "display_height", &height);
4827
4828                                         /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
4829                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
4830                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-buffer-num", 5, NULL);
4831
4832                                         if (no_scaling)
4833                                         {
4834                                                 /* no-scaling order to fimcconvert, original width, height size of media src will be passed to sink plugin */
4835                                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst,
4836                                                                 "dst-width", 0, /* setting 0, output video width will be media src's width */
4837                                                                 "dst-height", 0, /* setting 0, output video height will be media src's height */
4838                                                                 NULL);
4839                                         }
4840                                         else
4841                                         {
4842                                                 /* scaling order to fimcconvert */
4843                                                 if (width)
4844                                                 {
4845                                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
4846                                                 }
4847                                                 if (height)
4848                                                 {
4849                                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
4850                                                 }
4851                                                 debug_log("set video param : video frame scaling down to width(%d) height(%d)", width, height);
4852                                         }
4853                                         debug_log("set video param : display_evas_do_scaling %d", scaling);
4854                                 }
4855                         }
4856
4857                         /* if evaspixmapsink */
4858                         if (!strcmp(player->ini.videosink_element_evas,"evaspixmapsink"))
4859                         {
4860                                 if (object)
4861                                 {
4862                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4863                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4864                                                         "evas-object", object,
4865                                                         "visible", visible,
4866                                                         "display-geometry-method", display_method,
4867                                                         "rotate", rotation_value,
4868                                                         NULL);
4869                                         debug_log("set video param : method %d", display_method);
4870                                         debug_log("set video param : evas-object %x, visible %d", object, visible);
4871                                         debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
4872                                 }
4873                                 else
4874                                 {
4875                                         debug_error("no evas object");
4876                                         return MM_ERROR_PLAYER_INTERNAL;
4877                                 }
4878
4879                                 int display_method = 0;
4880                                 int roi_x = 0;
4881                                 int roi_y = 0;
4882                                 int roi_w = 0;
4883                                 int roi_h = 0;
4884                                 int origin_size = !scaling;
4885
4886                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4887                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
4888                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
4889                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
4890                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
4891
4892                                 /* get rotation value to set */
4893                                 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4894
4895                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4896                                         "origin-size", origin_size,
4897                                         "rotate", rotation_value,
4898                                         "dst-roi-x", roi_x,
4899                                         "dst-roi-y", roi_y,
4900                                         "dst-roi-w", roi_w,
4901                                         "dst-roi-h", roi_h,
4902                                         "display-geometry-method", display_method,
4903                                         NULL );
4904
4905                                 debug_log("set video param : method %d", display_method);
4906                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
4907                                                                 roi_x, roi_y, roi_w, roi_h );
4908                                 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
4909                         }
4910                 }
4911                 break;
4912                 case MM_DISPLAY_SURFACE_X_EXT:  /* NOTE : this surface type is used for the videoTexture(canvasTexture) overlay */
4913                 {
4914                         void *pixmap_id_cb = NULL;
4915                         void *pixmap_id_cb_user_data = NULL;
4916                         int display_method = 0;
4917                         gboolean visible = TRUE;
4918
4919                         /* if xvimagesink */
4920                         if (strcmp(player->ini.videosink_element_x,"xvimagesink"))
4921                         {
4922                                 debug_error("videosink is not xvimagesink");
4923                                 return MM_ERROR_PLAYER_INTERNAL;
4924                         }
4925
4926                         /* get information from attributes */
4927                         mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
4928                         mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
4929                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4930                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4931
4932                         if ( pixmap_id_cb )
4933                         {
4934                                 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
4935                                 if (pixmap_id_cb_user_data)
4936                                 {
4937                                         debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
4938                                 }
4939                         }
4940                         else
4941                         {
4942                                 debug_error("failed to set pixmap-id-callback");
4943                                 return MM_ERROR_PLAYER_INTERNAL;
4944                         }
4945                         /* get rotation value to set */
4946                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4947
4948                         debug_log("set video param : rotate %d, method %d, visible %d", rotation_value, display_method, visible);
4949
4950                         /* set properties of videosink plugin */
4951                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4952                                 "display-geometry-method", display_method,
4953                                 "draw-borders", FALSE,
4954                                 "visible", visible,
4955                                 "rotate", rotation_value,
4956                                 "pixmap-id-callback", pixmap_id_cb,
4957                                 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
4958                                 NULL );
4959                 }
4960                 break;
4961                 case MM_DISPLAY_SURFACE_NULL:
4962                 {
4963                         /* do nothing */
4964                 }
4965                 break;
4966         }
4967
4968         MMPLAYER_FLEAVE();
4969
4970         return MM_ERROR_NONE;
4971 }
4972
4973 static int
4974 __mmplayer_gst_element_link_bucket(GList* element_bucket) // @
4975 {
4976         GList* bucket = element_bucket;
4977         MMPlayerGstElement* element = NULL;
4978         MMPlayerGstElement* prv_element = NULL;
4979         gint successful_link_count = 0;
4980
4981         MMPLAYER_FENTER();
4982
4983         return_val_if_fail(element_bucket, -1);
4984
4985         prv_element = (MMPlayerGstElement*)bucket->data;
4986         bucket = bucket->next;
4987
4988         for ( ; bucket; bucket = bucket->next )
4989         {
4990                 element = (MMPlayerGstElement*)bucket->data;
4991
4992                 if ( element && element->gst )
4993                 {
4994 #ifdef TEST_ES
4995                         /* If next element is audio appsrc then make a seprate audio pipeline */
4996                         if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),"audio_appsrc") ||
4997                                 !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),"subtitle_appsrc"))
4998                         {
4999                                 prv_element = element;
5000                                 continue;
5001                         }
5002 #endif
5003                         if ( GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst)) )
5004                         {
5005                                 debug_log("linking [%s] to [%s] success\n",
5006                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
5007                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
5008                                 successful_link_count ++;
5009                         }
5010                         else
5011                         {
5012                                 debug_log("linking [%s] to [%s] failed\n",
5013                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
5014                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
5015                                 return -1;
5016                         }
5017                 }
5018
5019                 prv_element = element;
5020         }
5021
5022         MMPLAYER_FLEAVE();
5023
5024         return successful_link_count;
5025 }
5026
5027 static int
5028 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket) // @
5029 {
5030         GList* bucket = element_bucket;
5031         MMPlayerGstElement* element = NULL;
5032         int successful_add_count = 0;
5033
5034         MMPLAYER_FENTER();
5035
5036         return_val_if_fail(element_bucket, 0);
5037         return_val_if_fail(bin, 0);
5038
5039         for ( ; bucket; bucket = bucket->next )
5040         {
5041                 element = (MMPlayerGstElement*)bucket->data;
5042
5043                 if ( element && element->gst )
5044                 {
5045                         if( !gst_bin_add(bin, GST_ELEMENT(element->gst)) )
5046                         {
5047                                 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
5048                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
5049                                         GST_ELEMENT_NAME(GST_ELEMENT(bin) ) );
5050                                 return 0;
5051                         }
5052                         successful_add_count ++;
5053                 }
5054         }
5055
5056         MMPLAYER_FLEAVE();
5057
5058         return successful_add_count;
5059 }
5060
5061 static void __mmplayer_gst_caps_notify_cb (GstPad * pad, GParamSpec * unused, gpointer data)
5062 {
5063         mm_player_t* player = (mm_player_t*) data;
5064         GstCaps *caps = NULL;
5065         GstStructure *str = NULL;
5066         const char *name;
5067
5068         MMPLAYER_FENTER();
5069
5070         return_if_fail ( pad )
5071         return_if_fail ( unused )
5072         return_if_fail ( data )
5073
5074         caps = gst_pad_query_caps(pad, NULL);
5075         if ( !caps )
5076         {
5077                 return;
5078         }
5079
5080         str = gst_caps_get_structure(caps, 0);
5081         if ( !str )
5082         {
5083                 goto ERROR;
5084         }
5085
5086         name = gst_structure_get_name(str);
5087         if ( !name )
5088         {
5089                 goto ERROR;
5090         }
5091
5092         debug_log("name = %s\n", name);
5093
5094         if (strstr(name, "audio"))
5095         {
5096                 _mmplayer_update_content_attrs (player, ATTR_AUDIO);
5097
5098                 if (player->audio_stream_changed_cb)
5099                 {
5100                         debug_error("call the audio stream changed cb\n");
5101                         player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
5102                 }
5103         }
5104         else if (strstr(name, "video"))
5105         {
5106                 _mmplayer_update_content_attrs (player, ATTR_VIDEO);
5107
5108                 if (player->video_stream_changed_cb)
5109                 {
5110                         debug_error("call the video stream changed cb\n");
5111                         player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
5112                 }
5113         }
5114         else
5115         {
5116                 goto ERROR;
5117         }
5118
5119 ERROR:
5120
5121         gst_caps_unref(caps);
5122
5123         MMPLAYER_FLEAVE();
5124
5125         return;
5126 }
5127
5128
5129
5130 /**
5131  * This function is to create audio pipeline for playing.
5132  *
5133  * @param       player          [in]    handle of player
5134  *
5135  * @return      This function returns zero on success.
5136  * @remark
5137  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
5138  */
5139 #define MMPLAYER_CREATEONLY_ELEMENT(x_bin, x_id, x_factory, x_name) \
5140 x_bin[x_id].id = x_id;\
5141 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5142 if ( ! x_bin[x_id].gst )\
5143 {\
5144         debug_error("failed to create %s \n", x_factory);\
5145         goto ERROR;\
5146 }\
5147
5148 #define MMPLAYER_CREATE_ELEMENT_ADD_BIN(x_bin, x_id, x_factory, x_name, y_bin, x_player) \
5149 x_bin[x_id].id = x_id;\
5150 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5151 if ( ! x_bin[x_id].gst )\
5152 {\
5153         debug_error("failed to create %s \n", x_factory);\
5154         goto ERROR;\
5155 }\
5156 else\
5157 {\
5158         if (x_player->ini.set_dump_element_flag)\
5159                 __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
5160 }\
5161 if( !gst_bin_add(GST_BIN(y_bin), GST_ELEMENT(x_bin[x_id].gst)))\
5162 {\
5163         debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",\
5164                 GST_ELEMENT_NAME(GST_ELEMENT(x_bin[x_id].gst)),\
5165                 GST_ELEMENT_NAME(GST_ELEMENT(y_bin) ) );\
5166         goto ERROR;\
5167 }\
5168
5169 /* macro for code readability. just for sinkbin-creation functions */
5170 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
5171 do \
5172 { \
5173         x_bin[x_id].id = x_id;\
5174         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5175         if ( ! x_bin[x_id].gst )\
5176         {\
5177                 debug_error("failed to create %s \n", x_factory);\
5178                 goto ERROR;\
5179         }\
5180         else\
5181         {\
5182                 if (x_player->ini.set_dump_element_flag)\
5183                         __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
5184         }\
5185         if ( x_add_bucket )\
5186                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
5187 } while(0);
5188
5189 static void
5190 __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5191 {
5192         mm_player_t* player = (mm_player_t*) data;
5193
5194         gint channel = 0;
5195         gint rate = 0;
5196         gint depth = 0;
5197         gint endianness = 0;
5198         guint64 channel_mask = 0;
5199
5200         MMPlayerAudioStreamDataType audio_stream = { 0, };
5201         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5202
5203         MMPLAYER_FENTER();
5204         return_if_fail(player->audio_stream_render_cb_ex);
5205
5206         debug_log ("__mmplayer_audio_stream_decoded_render_cb new pad: %s", GST_PAD_NAME (pad));
5207
5208         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
5209         audio_stream.data = mapinfo.data;
5210         audio_stream.data_size = mapinfo.size;
5211
5212         GstCaps *caps = gst_pad_get_current_caps( pad );
5213         GstStructure *structure = gst_caps_get_structure (caps, 0);
5214
5215         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5216         gst_structure_get_int (structure, "rate", &rate);
5217         gst_structure_get_int (structure, "channels", &channel);
5218         gst_structure_get_int (structure, "depth", &depth);
5219         gst_structure_get_int (structure, "endianness", &endianness);
5220         gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
5221
5222         gst_caps_unref(GST_CAPS(caps));
5223
5224         audio_stream.bitrate = rate;
5225         audio_stream.channel = channel;
5226         audio_stream.depth = depth;
5227         audio_stream.is_little_endian = (endianness == 1234 ? 1 : 0);
5228         audio_stream.channel_mask = channel_mask;
5229         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);
5230         player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param);
5231         gst_buffer_unmap(buffer, &mapinfo);
5232
5233         MMPLAYER_FLEAVE();
5234 }
5235
5236 static void
5237 __mmplayer_gst_audio_deinterleave_pad_added (GstElement *elem, GstPad *pad, gpointer data)
5238 {
5239         mm_player_t* player = (mm_player_t*)data;
5240         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
5241         GstPad* sinkpad = NULL;
5242         GstElement *queue = NULL, *sink = NULL;
5243
5244         MMPLAYER_FENTER();
5245         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
5246
5247         queue = gst_element_factory_make ("queue", NULL);
5248         if (queue == NULL)
5249         {
5250                 debug_log ("fail make queue\n");
5251                 goto ERROR;
5252         }
5253
5254         sink = gst_element_factory_make ("fakesink", NULL);
5255         if (sink == NULL)
5256         {
5257                 debug_log ("fail make fakesink\n");
5258                 goto ERROR;
5259         }
5260
5261         gst_bin_add_many (GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
5262
5263         if (!gst_element_link_pads_full (queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING))
5264         {
5265                 debug_warning("failed to link queue & sink\n");
5266                 goto ERROR;
5267         }
5268
5269         sinkpad = gst_element_get_static_pad (queue, "sink");
5270
5271         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
5272         {
5273                 debug_warning ("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
5274                 goto ERROR;
5275         }
5276
5277         debug_error("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
5278
5279         gst_object_unref (sinkpad);
5280         g_object_set (sink, "sync", player->audio_stream_sink_sync, NULL);
5281         g_object_set (sink, "signal-handoffs", TRUE, NULL);
5282
5283         gst_element_set_state (sink, GST_STATE_PAUSED);
5284         gst_element_set_state (queue, GST_STATE_PAUSED);
5285
5286         MMPLAYER_SIGNAL_CONNECT( player,
5287                 G_OBJECT(sink),
5288                 MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
5289                 "handoff",
5290                 G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
5291                 (gpointer)player );
5292
5293         MMPLAYER_FLEAVE();
5294         return ;
5295
5296 ERROR:
5297         debug_error("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
5298         if (queue)
5299         {
5300                 gst_object_unref(GST_OBJECT(queue));
5301                 queue = NULL;
5302         }
5303         if (sink)
5304         {
5305                 gst_object_unref(GST_OBJECT(sink));
5306                 sink = NULL;
5307         }
5308         if (sinkpad)
5309         {
5310                 gst_object_unref ( GST_OBJECT(sinkpad) );
5311                 sinkpad = NULL;
5312         }
5313
5314         return;
5315 }
5316
5317
5318 /**
5319   * AUDIO PIPELINE
5320   * - Local playback    : audiotp !audioconvert ! volume ! capsfilter ! audioeffect ! audioeffect_sec ! audiosink
5321   * - Streaming         : audiotp !audioconvert !volume ! audiosink
5322   * - PCM extraction : audiotp !audioconvert ! audioresample ! capsfilter ! fakesink
5323   */
5324 void __mmplayer_gst_create_audiosink_configure(mm_player_t* player, MMHandleType attrs)
5325 {
5326 #define MAX_PROPS_LEN 64
5327         gint volume_type = 0;
5328         gint route_path = 0;
5329         gint latency_mode = 0;
5330         gchar *stream_type = NULL;
5331         gint stream_id = 0;
5332         gchar stream_props[MAX_PROPS_LEN] = {0,};
5333         GstStructure *props = NULL;
5334
5335         /* set volume table
5336          * It should be set after player creation through attribute.
5337          * But, it can not be changed during playing.
5338          */
5339         MMPLAYER_FENTER();
5340         mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
5341         mm_attrs_get_string_by_name (attrs, "sound_stream_type", &stream_type );
5342
5343         if ( stream_id < 1 || !stream_type || strlen(stream_type) < 1)
5344         {
5345                 debug_error("stream_id[%d] or stream_type[%s] is not valid.\n", stream_id, stream_type);
5346         }
5347         else
5348         {
5349                 snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d", stream_type, stream_id);
5350                 props = gst_structure_from_string(stream_props, NULL);
5351                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
5352         }
5353
5354         debug_log("stream_id[%d], stream_type[%s], result[%s].\n", stream_id, stream_type, stream_props);
5355
5356 /* for audio tunning */
5357 #ifndef IS_SDK
5358         if (player->profile.play_mode == MM_PLAYER_MODE_MIDI)
5359         {
5360                 volume_type |= MM_SOUND_VOLUME_GAIN_MIDI;
5361         }
5362 #endif
5363         /* hook sound_type if emergency case */
5364         if (player->sm.event == ASM_EVENT_EMERGENCY)
5365         {
5366                 debug_log ("This is emergency session, hook sound_type from [%d] to [%d]\n", volume_type, MM_SOUND_VOLUME_TYPE_EMERGENCY);
5367                 volume_type = MM_SOUND_VOLUME_TYPE_EMERGENCY;
5368         }
5369
5370         mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
5371
5372         if (player->sm.user_route_policy != 0)
5373         {
5374                 route_path = player->sm.user_route_policy;
5375         }
5376
5377         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
5378                         "latency", latency_mode,
5379                         NULL);
5380
5381         debug_log("audiosink property status...volume type:%d, user-route=%d, latency=%d \n",
5382                 volume_type, route_path, latency_mode);
5383         MMPLAYER_FLEAVE();
5384 }
5385
5386 static int
5387 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
5388 {
5389         MMPlayerGstElement* first_element = NULL;
5390         MMPlayerGstElement* audiobin = NULL;
5391         MMHandleType attrs = 0;
5392         GstPad *pad = NULL;
5393         GstPad *ghostpad = NULL;
5394         GList* element_bucket = NULL;
5395         gboolean link_audio_sink_now = TRUE;
5396         int i =0;
5397
5398         MMPLAYER_FENTER();
5399
5400         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5401
5402         /* alloc handles */
5403         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
5404         if ( ! audiobin )
5405         {
5406                 debug_error("failed to allocate memory for audiobin\n");
5407                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5408         }
5409
5410         attrs = MMPLAYER_GET_ATTRS(player);
5411
5412         /* create bin */
5413         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
5414         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
5415         if ( !audiobin[MMPLAYER_A_BIN].gst )
5416         {
5417                 debug_error("failed to create audiobin\n");
5418                 goto ERROR;
5419         }
5420
5421         /* take it */
5422         player->pipeline->audiobin = audiobin;
5423
5424         player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
5425
5426         /* Adding audiotp plugin for reverse trickplay feature */
5427 //      MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
5428
5429         /* converter */
5430         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
5431
5432         /* resampler */
5433         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER,  player->ini.name_of_audio_resampler, "audio resampler", TRUE, player);
5434
5435         if (player->set_mode.pcm_extraction) // pcm extraction only and no sound output
5436         {
5437                 if(player->audio_stream_render_cb_ex)
5438                 {
5439                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
5440
5441                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
5442                         /* raw pad handling signal */
5443                         MMPLAYER_SIGNAL_CONNECT( player,
5444                                 (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
5445                                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
5446                                                                                                 G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
5447                 }
5448                 else
5449                 {
5450                         int dst_samplerate = 0;
5451                         int dst_channels = 0;
5452                         int dst_depth = 0;
5453                         char *caps_str = NULL;
5454                         GstCaps* caps = NULL;
5455
5456                         /* get conf. values */
5457                         mm_attrs_multiple_get(player->attrs,
5458                                                 NULL,
5459                                                 "pcm_extraction_samplerate", &dst_samplerate,
5460                                                 "pcm_extraction_channels", &dst_channels,
5461                                                 "pcm_extraction_depth", &dst_depth,
5462                                                 NULL);
5463
5464                         /* capsfilter */
5465                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
5466                         caps = gst_caps_new_simple ("audio/x-raw",
5467                                         "rate", G_TYPE_INT, dst_samplerate,
5468                                         "channels", G_TYPE_INT, dst_channels,
5469                                         "depth", G_TYPE_INT, dst_depth,
5470                                         NULL);
5471                         caps_str = gst_caps_to_string(caps);
5472                         debug_log("new caps : %s\n", caps_str);
5473
5474                         g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5475
5476                         /* clean */
5477                         gst_caps_unref( caps );
5478                         MMPLAYER_FREEIF( caps_str );
5479
5480                         /* fake sink */
5481                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
5482
5483                         /* set sync */
5484                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
5485                 }
5486         }
5487         else // normal playback
5488         {
5489                 //GstCaps* caps = NULL;
5490                 gint channels = 0;
5491
5492                 /* for logical volume control */
5493                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
5494                 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
5495
5496                 if (player->sound.mute)
5497                 {
5498                         debug_log("mute enabled\n");
5499                         g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
5500                 }
5501
5502 #if 0
5503                 /*capsfilter */
5504                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
5505                 caps = gst_caps_from_string( "audio/x-raw-int, "
5506                                         "endianness = (int) LITTLE_ENDIAN, "
5507                                         "signed = (boolean) true, "
5508                                         "width = (int) 16, "
5509                                         "depth = (int) 16" );
5510                 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5511                 gst_caps_unref( caps );
5512 #endif
5513
5514                 /* chech if multi-chennels */
5515                 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)
5516                 {
5517                         GstPad *srcpad = NULL;
5518                         GstCaps *caps = NULL;
5519
5520                         if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src")))
5521                         {
5522                                 if ((caps = gst_pad_query_caps(srcpad, NULL)))
5523                                 {
5524                                         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5525                                         GstStructure *str = gst_caps_get_structure(caps, 0);
5526                                         if (str)
5527                                                 gst_structure_get_int (str, "channels", &channels);
5528                                         gst_caps_unref(caps);
5529                                 }
5530                                 gst_object_unref(srcpad);
5531                         }
5532                 }
5533
5534                 /* audio effect element. if audio effect is enabled */
5535                 if ( (strcmp(player->ini.name_of_audio_effect, ""))
5536                         && (channels <= 2)
5537                         && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom) )
5538                 {
5539                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.name_of_audio_effect, "audio effect filter", TRUE, player);
5540
5541                         debug_log("audio effect config. bypass = %d, effect type  = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
5542
5543                         if ( (!player->bypass_audio_effect)
5544                                 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom) )
5545                         {
5546                                 if ( MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type )
5547                                 {
5548                                         if (!_mmplayer_audio_effect_custom_apply(player))
5549                                         {
5550                                                 debug_msg("apply audio effect(custom) setting success\n");
5551                                         }
5552                                 }
5553                         }
5554
5555                         if ( (strcmp(player->ini.name_of_audio_effect_sec, ""))
5556                                 && (player->set_mode.rich_audio) )
5557                         {
5558                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.name_of_audio_effect_sec, "audio effect filter", TRUE, player);
5559                         }
5560                 }
5561                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
5562                 {
5563                         if (player->set_mode.rich_audio && channels <= 2)
5564                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VSP, "audiovsp", "x-speed", TRUE, player);
5565                 }
5566
5567                 /* create audio sink */
5568                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.name_of_audiosink, "audiosink", link_audio_sink_now, player);
5569
5570                 /* qos on */
5571                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);     /* qos on */
5572                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
5573
5574                 /* FIXIT : using system clock. isn't there another way? */
5575                 if (player->videodec_linked)
5576                 {
5577                         debug_log("provide clock for movie = %s", (player->ini.provide_clock_for_movie)?"audio_clock":"sys_clock");
5578                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_movie,  NULL);
5579                 }
5580                 else
5581                 {
5582                         debug_log("provide clock for music = %s", (player->ini.provide_clock_for_music)?"audio_clock":"sys_clock");
5583                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_music,  NULL);
5584                 }
5585
5586                 if ( g_strrstr(player->ini.name_of_audiosink, "pulsesink") )
5587                 {
5588                         __mmplayer_gst_create_audiosink_configure(player, attrs);
5589                 }
5590
5591                 /* Antishock can be enabled when player is resumed by soundCM.
5592                  * But, it's not used in MMS, setting and etc.
5593                  * Because, player start seems like late.
5594                  */
5595                 __mmplayer_set_antishock( player , FALSE );
5596         }
5597
5598         if (audiobin[MMPLAYER_A_SINK].gst)
5599         {
5600                 GstPad *sink_pad = NULL;
5601                 sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
5602                 MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
5603                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
5604                 gst_object_unref (GST_OBJECT(sink_pad));
5605         }
5606
5607         __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
5608
5609         /* adding created elements to bin */
5610         debug_log("adding created elements to bin\n");
5611         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket ))
5612         {
5613                 debug_error("failed to add elements\n");
5614                 goto ERROR;
5615         }
5616
5617         /* linking elements in the bucket by added order. */
5618         debug_log("Linking elements in the bucket by added order.\n");
5619         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5620         {
5621                 debug_error("failed to link elements\n");
5622                 goto ERROR;
5623         }
5624
5625         /* get first element's sinkpad for creating ghostpad */
5626         first_element = (MMPlayerGstElement *)element_bucket->data;
5627
5628         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5629         if ( ! pad )
5630         {
5631                 debug_error("failed to get pad from first element of audiobin\n");
5632                 goto ERROR;
5633         }
5634
5635         ghostpad = gst_ghost_pad_new("sink", pad);
5636         if ( ! ghostpad )
5637         {
5638                 debug_error("failed to create ghostpad\n");
5639                 goto ERROR;
5640         }
5641
5642         if ( FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad) )
5643         {
5644                 debug_error("failed to add ghostpad to audiobin\n");
5645                 goto ERROR;
5646         }
5647
5648         gst_object_unref(pad);
5649
5650         g_list_free(element_bucket);
5651
5652         mm_attrs_set_int_by_name(attrs, "content_audio_found", TRUE);
5653
5654         MMPLAYER_FLEAVE();
5655
5656         return MM_ERROR_NONE;
5657
5658 ERROR:
5659
5660         debug_log("ERROR : releasing audiobin\n");
5661
5662         if ( pad )
5663                 gst_object_unref(GST_OBJECT(pad));
5664
5665         if ( ghostpad )
5666                 gst_object_unref(GST_OBJECT(ghostpad));
5667
5668         g_list_free( element_bucket );
5669
5670         /* release element which are not added to bin */
5671         for ( i = 1; i < MMPLAYER_A_NUM; i++ )  /* NOTE : skip bin */
5672         {
5673                 if ( audiobin[i].gst )
5674                 {
5675                         GstObject* parent = NULL;
5676                         parent = gst_element_get_parent( audiobin[i].gst );
5677
5678                         if ( !parent )
5679                         {
5680                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
5681                                 audiobin[i].gst = NULL;
5682                         }
5683                         else
5684                         {
5685                                 gst_object_unref(GST_OBJECT(parent));
5686                         }
5687                 }
5688         }
5689
5690         /* release audiobin with it's childs */
5691         if ( audiobin[MMPLAYER_A_BIN].gst )
5692         {
5693                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
5694         }
5695
5696         MMPLAYER_FREEIF( audiobin );
5697
5698         player->pipeline->audiobin = NULL;
5699
5700         return MM_ERROR_PLAYER_INTERNAL;
5701 }
5702
5703 static GstPadProbeReturn
5704 __mmplayer_audio_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
5705 {
5706         mm_player_t* player = (mm_player_t*) u_data;
5707         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
5708         GstMapInfo probe_info = GST_MAP_INFO_INIT;
5709
5710         gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
5711
5712         if (player->audio_stream_cb && probe_info.size && probe_info.data)
5713                 player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
5714
5715         return GST_PAD_PROBE_OK;
5716 }
5717
5718 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
5719 {
5720     return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
5721 }
5722
5723 static GstPadProbeReturn
5724 __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
5725 {
5726         GstCaps *caps = NULL;
5727         MMPlayerVideoStreamDataType stream;
5728         MMVideoBuffer *video_buffer = NULL;
5729         GstMemory *dataBlock = NULL;
5730         GstMemory *metaBlock = NULL;
5731         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5732         GstStructure *structure = NULL;
5733         const gchar *string_format = NULL;
5734         unsigned int fourcc = 0;
5735         mm_player_t* player = (mm_player_t*)user_data;
5736         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
5737
5738         return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
5739         return_val_if_fail(gst_buffer_n_memory(buffer)  , GST_PAD_PROBE_DROP);
5740
5741         caps = gst_pad_get_current_caps(pad);
5742         if (caps == NULL) {
5743                 debug_error( "Caps is NULL." );
5744                 return GST_PAD_PROBE_OK;
5745         }
5746
5747         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5748
5749         /* clear stream data structure */
5750         memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
5751
5752         structure = gst_caps_get_structure( caps, 0 );
5753         gst_structure_get_int(structure, "width", &(stream.width));
5754         gst_structure_get_int(structure, "height", &(stream.height));
5755         string_format = gst_structure_get_string(structure, "format");
5756         if(string_format) {
5757                 fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
5758         }
5759         stream.format = util_get_pixtype(fourcc);
5760         gst_caps_unref( caps );
5761         caps = NULL;
5762
5763     /*
5764         debug_log( "Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
5765                         GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format );
5766     */
5767
5768         if (stream.width == 0 || stream.height == 0 || stream.format == MM_PIXEL_FORMAT_INVALID) {
5769                 debug_error("Wrong condition!!");
5770                 return TRUE;
5771         }
5772
5773         /* set size and timestamp */
5774         dataBlock = gst_buffer_peek_memory(buffer, 0);
5775         stream.length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
5776         stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano sec -> mili sec */
5777
5778         /* check zero-copy */
5779         if (player->set_mode.video_zc &&
5780                 player->set_mode.media_packet_video_stream &&
5781                 gst_buffer_n_memory(buffer) > 1) {
5782                 metaBlock = gst_buffer_peek_memory(buffer, 1);
5783                 gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
5784                 video_buffer = (MMVideoBuffer *)mapinfo.data;
5785         }
5786
5787         if (video_buffer) {
5788                 /* set tbm bo */
5789                 if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
5790                         /* copy pointer of tbm bo, stride, elevation */
5791                         memcpy(stream.bo, video_buffer->handle.bo,
5792                                         sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
5793                 }
5794                 else if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
5795                         memcpy(stream.data, video_buffer->data,
5796                                         sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
5797                 }
5798                 memcpy(stream.stride, video_buffer->stride_width,
5799                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5800                 memcpy(stream.elevation, video_buffer->stride_height,
5801                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5802                 /* set gst buffer */
5803                 stream.internal_buffer = buffer;
5804         } else {
5805                 gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
5806                 stream.data[0] = mapinfo.data;
5807         }
5808
5809         if (player->video_stream_cb) {
5810                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
5811         }
5812
5813         if (metaBlock) {
5814                 gst_memory_unmap(metaBlock, &mapinfo);
5815         }else {
5816                 gst_memory_unmap(dataBlock, &mapinfo);
5817         }
5818
5819         return GST_PAD_PROBE_OK;
5820 }
5821
5822 static int
5823 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket, gboolean use_video_stream)
5824 {
5825         gchar* video_csc = "videoconvert"; // default colorspace converter
5826         GList* element_bucket = *bucket;
5827
5828         return_val_if_fail(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5829
5830         MMPLAYER_FENTER();
5831
5832         if (!player->set_mode.media_packet_video_stream && use_video_stream)
5833         {
5834                 if (player->set_mode.video_zc && strlen(player->ini.name_of_video_converter) > 0)
5835                 {
5836                         video_csc = player->ini.name_of_video_converter;
5837                 }
5838
5839                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5840                 debug_log("using video converter: %s", video_csc);
5841
5842                 if ( !player->set_mode.video_zc)
5843                 {
5844                         GstStructure *str = NULL;
5845                         gint width = 0;         //width of video
5846                         gint height = 0;                //height of video
5847                         GstCaps* video_caps = NULL;
5848                         GstStructure *structure = NULL;
5849
5850                         /* rotator, scaler and capsfilter */
5851                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5852                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "video scaler", TRUE, player);
5853                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CAPS, "capsfilter", "videocapsfilter", TRUE, player);
5854
5855                         /* get video stream caps parsed by demuxer */
5856                         str = gst_caps_get_structure (player->v_stream_caps, 0);
5857                         if ( !str )
5858                         {
5859                                 debug_error("cannot get structure");
5860                                 goto ERROR;
5861                         }
5862
5863                         mm_attrs_get_int_by_name(player->attrs, "display_width", &width);
5864
5865                         if (width) {
5866                                 if (structure) {
5867                                         gst_structure_set (structure, "width", G_TYPE_INT, width, NULL);
5868                                 } else {
5869                                         structure = gst_structure_new("video/x-raw", "width", G_TYPE_INT, width, NULL);
5870                                 }
5871                         }
5872
5873                         mm_attrs_get_int_by_name(player->attrs, "display_height", &height);
5874
5875                         if (height) {
5876                                 if (structure) {
5877                                         gst_structure_set (structure, "height", G_TYPE_INT, height, NULL);
5878                                 } else {
5879                                         structure = gst_structure_new("video/x-raw", "height", G_TYPE_INT, height, NULL);
5880                                 }
5881                         }
5882
5883                         if (width || height) {
5884                                 video_caps = gst_caps_new_full(structure, NULL);
5885                                 gst_structure_free(structure);
5886
5887                                 g_object_set (GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_CAPS].gst), "caps", video_caps, NULL );
5888                                 MMPLAYER_LOG_GST_CAPS_TYPE(video_caps);
5889                                 gst_caps_unref(video_caps);
5890                         }
5891                 }
5892         }
5893         else
5894         {
5895                 MMDisplaySurfaceType surface_type = MM_DISPLAY_SURFACE_NULL;
5896                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", (int *)&surface_type);
5897
5898                 if (player->set_mode.video_zc)
5899                 {
5900                         if ( (surface_type == MM_DISPLAY_SURFACE_EVAS) && ( !strcmp(player->ini.videosink_element_evas, "evasimagesink")) )
5901                         {
5902                                 video_csc = player->ini.name_of_video_converter;
5903                         }
5904                         else
5905                         {
5906                                 video_csc = "";
5907                         }
5908                 }
5909
5910                 if (video_csc && (strcmp(video_csc, "")))
5911                 {
5912                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5913                         debug_log("using video converter: %s", video_csc);
5914                 }
5915
5916                 /* set video rotator */
5917                 if ( !player->set_mode.video_zc )
5918                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5919
5920                 /* videoscaler */
5921                 #if !defined(__arm__)
5922                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "videoscaler", TRUE, player);
5923                 #endif
5924         }
5925
5926         *bucket = element_bucket;
5927         MMPLAYER_FLEAVE();
5928         return MM_ERROR_NONE;
5929
5930 ERROR:
5931         *bucket = NULL;
5932         MMPLAYER_FLEAVE();
5933         return MM_ERROR_PLAYER_INTERNAL;
5934 }
5935
5936 /**
5937  * This function is to create video pipeline.
5938  *
5939  * @param       player          [in]    handle of player
5940  *              caps            [in]    src caps of decoder
5941  *              surface_type    [in]    surface type for video rendering
5942  *
5943  * @return      This function returns zero on success.
5944  * @remark
5945  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5946  */
5947 /**
5948   * VIDEO PIPELINE
5949   * - x surface (arm/x86) : xvimagesink
5950   * - evas surface  (arm) : evaspixmapsink
5951   *                         fimcconvert ! evasimagesink
5952   * - evas surface  (x86) : videoconvertor ! videoflip ! evasimagesink
5953   */
5954 static int
5955 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5956 {
5957         GstPad *pad = NULL;
5958         MMHandleType attrs;
5959         GList*element_bucket = NULL;
5960         MMPlayerGstElement* first_element = NULL;
5961         MMPlayerGstElement* videobin = NULL;
5962         gchar *videosink_element = NULL;
5963
5964         MMPLAYER_FENTER();
5965
5966         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5967
5968         /* alloc handles */
5969         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5970         if ( !videobin )
5971         {
5972                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5973         }
5974
5975         player->pipeline->videobin = videobin;
5976
5977         attrs = MMPLAYER_GET_ATTRS(player);
5978         if ( !attrs )
5979         {
5980                 debug_error("cannot get content attribute");
5981                 return MM_ERROR_PLAYER_INTERNAL;
5982         }
5983
5984         /* create bin */
5985         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
5986         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
5987         if ( !videobin[MMPLAYER_V_BIN].gst )
5988         {
5989                 debug_error("failed to create videobin");
5990                 goto ERROR;
5991         }
5992
5993         if( player->use_video_stream ) // video stream callback, so send raw video data to application
5994         {
5995                 debug_log("using memsink\n");
5996
5997                 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, TRUE) != MM_ERROR_NONE)
5998                         goto ERROR;
5999
6000                 /* finally, create video sink. output will be BGRA8888. */
6001                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, "avsysmemsink", "videosink", TRUE, player);
6002
6003                 MMPLAYER_SIGNAL_CONNECT( player,
6004                                                                          videobin[MMPLAYER_V_SINK].gst,
6005                                                                          MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
6006                                                                          "video-stream",
6007                                                                          G_CALLBACK(__mmplayer_videostream_cb),
6008                                                                          player );
6009         }
6010         else // render video data using sink plugin like xvimagesink
6011         {
6012                 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, FALSE) != MM_ERROR_NONE)
6013                         goto ERROR;
6014
6015                 /* set video sink */
6016                 switch (surface_type)
6017                 {
6018                         case MM_DISPLAY_SURFACE_X:
6019                                 if (strlen(player->ini.videosink_element_x) > 0)
6020                                         videosink_element = player->ini.videosink_element_x;
6021                                 else
6022                                         goto ERROR;
6023                                 break;
6024                         case MM_DISPLAY_SURFACE_EVAS:
6025                                 if (strlen(player->ini.videosink_element_evas) > 0)
6026                                         videosink_element = player->ini.videosink_element_evas;
6027                                 else
6028                                         goto ERROR;
6029                                 break;
6030                         case MM_DISPLAY_SURFACE_X_EXT:
6031                         {
6032                                 void *pixmap_id_cb = NULL;
6033                                 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
6034                                 if (pixmap_id_cb) /* this is used for the videoTextue(canvasTexture) overlay */
6035                                 {
6036                                         videosink_element = player->ini.videosink_element_x;
6037                                 }
6038                                 else
6039                                 {
6040                                         debug_error("something wrong.. callback function for getting pixmap id is null");
6041                                         goto ERROR;
6042                                 }
6043                                 break;
6044                         }
6045                         case MM_DISPLAY_SURFACE_NULL:
6046                                 if (strlen(player->ini.videosink_element_fake) > 0)
6047                                         videosink_element = player->ini.videosink_element_fake;
6048                                 else
6049                                         goto ERROR;
6050                                 break;
6051                         default:
6052                                 debug_error("unidentified surface type");
6053                                 goto ERROR;
6054                 }
6055
6056                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, videosink_element, TRUE, player);
6057                 debug_log("selected videosink name: %s", videosink_element);
6058
6059                 /* connect signal handlers for sink plug-in */
6060                 switch (surface_type) {
6061                         case MM_DISPLAY_SURFACE_X_EXT:
6062                                 MMPLAYER_SIGNAL_CONNECT( player,
6063                                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
6064                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
6065                                                                                 "frame-render-error",
6066                                                                                 G_CALLBACK(__mmplayer_videoframe_render_error_cb),
6067                                                                                 player );
6068                                 debug_log("videoTexture usage, connect a signal handler for pixmap rendering error");
6069                                 break;
6070                         default:
6071                                 break;
6072                 }
6073         }
6074
6075         if (_mmplayer_update_video_param(player) != MM_ERROR_NONE)
6076                 goto ERROR;
6077
6078         if (videobin[MMPLAYER_V_SINK].gst)
6079         {
6080                 GstPad *sink_pad = NULL;
6081                 sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
6082                 if (sink_pad)
6083                 {
6084                         MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
6085                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
6086                         gst_object_unref (GST_OBJECT(sink_pad));
6087                 }
6088         }
6089
6090         /* store it as it's sink element */
6091         __mmplayer_add_sink( player, videobin[MMPLAYER_V_SINK].gst );
6092
6093         /* adding created elements to bin */
6094         if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket) )
6095         {
6096                 debug_error("failed to add elements\n");
6097                 goto ERROR;
6098         }
6099
6100         /* Linking elements in the bucket by added order */
6101         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
6102         {
6103                 debug_error("failed to link elements\n");
6104                 goto ERROR;
6105         }
6106
6107         /* get first element's sinkpad for creating ghostpad */
6108         first_element = (MMPlayerGstElement *)element_bucket->data;
6109         if ( !first_element )
6110         {
6111                 debug_error("failed to get first element from bucket\n");
6112                 goto ERROR;
6113         }
6114
6115         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
6116         if ( !pad )
6117         {
6118                 debug_error("failed to get pad from first element\n");
6119                 goto ERROR;
6120         }
6121
6122         /* create ghostpad */
6123         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
6124         if ( FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
6125         {
6126                 debug_error("failed to add ghostpad to videobin\n");
6127                 goto ERROR;
6128         }
6129         gst_object_unref(pad);
6130
6131         /* done. free allocated variables */
6132         g_list_free(element_bucket);
6133
6134         mm_attrs_set_int_by_name(attrs, "content_video_found", TRUE);
6135
6136         MMPLAYER_FLEAVE();
6137
6138         return MM_ERROR_NONE;
6139
6140 ERROR:
6141         debug_error("ERROR : releasing videobin\n");
6142
6143         g_list_free( element_bucket );
6144
6145         if (pad)
6146                 gst_object_unref(GST_OBJECT(pad));
6147
6148         /* release videobin with it's childs */
6149         if ( videobin[MMPLAYER_V_BIN].gst )
6150         {
6151                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
6152         }
6153
6154
6155         MMPLAYER_FREEIF( videobin );
6156
6157         player->pipeline->videobin = NULL;
6158
6159         return MM_ERROR_PLAYER_INTERNAL;
6160 }
6161
6162 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
6163 {
6164         GList *element_bucket = NULL;
6165         MMPlayerGstElement *textbin = player->pipeline->textbin;
6166
6167         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_FAKE_QUEUE, "queue", "text_f_queue", TRUE, player);
6168         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
6169         MMPLAYER_SIGNAL_CONNECT( player,
6170                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
6171                                                         MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
6172                                                         "handoff",
6173                                                         G_CALLBACK(__mmplayer_update_subtitle),
6174                                                         (gpointer)player );
6175
6176         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
6177         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
6178         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
6179
6180         if (!player->play_subtitle)
6181         {
6182                 debug_log ("add textbin sink as sink element of whole pipeline.\n");
6183                 __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
6184         }
6185
6186         /* adding created elements to bin */
6187         debug_log("adding created elements to bin\n");
6188         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
6189         {
6190                 debug_error("failed to add elements\n");
6191                 goto ERROR;
6192         }
6193
6194         /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
6195         GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
6196         GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
6197
6198         /* linking elements in the bucket by added order. */
6199         debug_log("Linking elements in the bucket by added order.\n");
6200         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
6201         {
6202                 debug_error("failed to link elements\n");
6203                 goto ERROR;
6204         }
6205
6206         /* done. free allocated variables */
6207         g_list_free(element_bucket);
6208
6209         if (textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst)
6210         {
6211                 GstPad *pad = NULL;
6212                 GstPad *ghostpad = NULL;
6213
6214                 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst), "sink");
6215                 if (!pad)
6216                 {
6217                         debug_error("failed to get video pad of textbin\n");
6218                         return MM_ERROR_PLAYER_INTERNAL;
6219                 }
6220
6221                 ghostpad = gst_ghost_pad_new("text_sink", pad);
6222                 gst_object_unref(pad);
6223
6224                 if (!ghostpad)
6225                 {
6226                         debug_error("failed to create ghostpad of textbin\n");
6227                         goto ERROR;
6228                 }
6229
6230                 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad))
6231                 {
6232                         debug_error("failed to add ghostpad to textbin\n");
6233                         goto ERROR;
6234                 }
6235         }
6236
6237         return MM_ERROR_NONE;
6238
6239 ERROR:
6240         g_list_free(element_bucket);
6241
6242         return MM_ERROR_PLAYER_INTERNAL;
6243 }
6244
6245 static int __mmplayer_gst_create_text_pipeline(mm_player_t* player)
6246 {
6247         MMPlayerGstElement *textbin = NULL;
6248         GList *element_bucket = NULL;
6249         GstPad *pad = NULL;
6250         GstPad *ghostpad = NULL;
6251         gint i = 0;
6252
6253         MMPLAYER_FENTER();
6254
6255         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6256
6257         /* alloc handles */
6258         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
6259         if ( ! textbin )
6260         {
6261                 debug_error("failed to allocate memory for textbin\n");
6262                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
6263         }
6264
6265         /* create bin */
6266         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
6267         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
6268         if ( !textbin[MMPLAYER_T_BIN].gst )
6269         {
6270                 debug_error("failed to create textbin\n");
6271                 goto ERROR;
6272         }
6273
6274         /* take it */
6275         player->pipeline->textbin = textbin;
6276
6277         /* fakesink */
6278         if (player->use_textoverlay)
6279         {
6280                 debug_log ("use textoverlay for displaying \n");
6281
6282                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_TEXT_FAKE_QUEUE, "queue", "text_t_queue", textbin[MMPLAYER_T_BIN].gst, player);
6283
6284                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_QUEUE, "queue", "text_v_queue", textbin[MMPLAYER_T_BIN].gst, player);
6285
6286                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_CONVERTER, "fimcconvert", "text_v_converter", textbin[MMPLAYER_T_BIN].gst, player);
6287
6288                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_OVERLAY, "textoverlay", "text_overlay", textbin[MMPLAYER_T_BIN].gst, player);
6289
6290                 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_QUEUE].gst, "src", textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "sink"))
6291                 {
6292                         debug_error("failed to link queue and converter\n");
6293                         goto ERROR;
6294                 }
6295
6296                 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "video_sink"))
6297                 {
6298                         debug_error("failed to link queue and textoverlay\n");
6299                         goto ERROR;
6300                 }
6301
6302                 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "text_sink"))
6303                 {
6304                         debug_error("failed to link queue and textoverlay\n");
6305                         goto ERROR;
6306                 }
6307         }
6308         else
6309         {
6310                 int surface_type = 0;
6311
6312                 debug_log ("use subtitle message for displaying \n");
6313
6314                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
6315
6316                 switch(surface_type)
6317                 {
6318                         case MM_DISPLAY_SURFACE_X:
6319                         case MM_DISPLAY_SURFACE_EVAS:
6320                         case MM_DISPLAY_SURFACE_GL:
6321                         case MM_DISPLAY_SURFACE_NULL:
6322                         case MM_DISPLAY_SURFACE_X_EXT:
6323                                 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE)
6324                                 {
6325                                         debug_error("failed to make plain text elements\n");
6326                                         goto ERROR;
6327                                 }
6328                                 break;
6329
6330                         default:
6331                                 break;
6332                 }
6333         }
6334         gst_object_unref(pad);
6335
6336         MMPLAYER_FLEAVE();
6337
6338         return MM_ERROR_NONE;
6339
6340 ERROR:
6341
6342         debug_log("ERROR : releasing textbin\n");
6343
6344         if ( pad )
6345                 gst_object_unref(GST_OBJECT(pad));
6346
6347         if ( ghostpad )
6348                 gst_object_unref(GST_OBJECT(ghostpad));
6349
6350         g_list_free( element_bucket );
6351
6352         /* release element which are not added to bin */
6353         for ( i = 1; i < MMPLAYER_T_NUM; i++ )  /* NOTE : skip bin */
6354         {
6355                 if ( textbin[i].gst )
6356                 {
6357                         GstObject* parent = NULL;
6358                         parent = gst_element_get_parent( textbin[i].gst );
6359
6360                         if ( !parent )
6361                         {
6362                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
6363                                 textbin[i].gst = NULL;
6364                         }
6365                         else
6366                         {
6367                                 gst_object_unref(GST_OBJECT(parent));
6368                         }
6369                 }
6370         }
6371
6372         /* release textbin with it's childs */
6373         if ( textbin[MMPLAYER_T_BIN].gst )
6374         {
6375                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
6376         }
6377
6378         MMPLAYER_FREEIF( textbin );
6379
6380         player->pipeline->textbin = NULL;
6381
6382         return MM_ERROR_PLAYER_INTERNAL;
6383 }
6384
6385
6386 static int
6387 __mmplayer_gst_create_subtitle_src(mm_player_t* player)
6388 {
6389         MMPlayerGstElement* mainbin = NULL;
6390         MMHandleType attrs = 0;
6391         GstElement *subsrc = NULL;
6392         GstElement *subparse = NULL;
6393         gchar *subtitle_uri =NULL;
6394         const gchar *charset = NULL;
6395         GstPad *pad = NULL;
6396
6397         MMPLAYER_FENTER();
6398
6399         /* get mainbin */
6400         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
6401
6402         mainbin = player->pipeline->mainbin;
6403
6404         attrs = MMPLAYER_GET_ATTRS(player);
6405         if ( !attrs )
6406         {
6407                 debug_error("cannot get content attribute\n");
6408                 return MM_ERROR_PLAYER_INTERNAL;
6409         }
6410
6411         mm_attrs_get_string_by_name ( attrs, "subtitle_uri", &subtitle_uri );
6412         if ( !subtitle_uri || strlen(subtitle_uri) < 1)
6413         {
6414                 debug_error("subtitle uri is not proper filepath.\n");
6415                 return MM_ERROR_PLAYER_INVALID_URI;
6416         }
6417         debug_log("subtitle file path is [%s].\n", subtitle_uri);
6418
6419
6420         /* create the subtitle source */
6421         subsrc = gst_element_factory_make("filesrc", "subtitle_source");
6422         if ( !subsrc )
6423         {
6424                 debug_error ( "failed to create filesrc element\n" );
6425                 goto ERROR;
6426         }
6427         g_object_set(G_OBJECT (subsrc), "location", subtitle_uri, NULL);
6428
6429         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6430         mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
6431
6432         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc))
6433         {
6434                 debug_warning("failed to add queue\n");
6435                 goto ERROR;
6436         }
6437
6438         /* subparse */
6439         subparse = gst_element_factory_make("subparse", "subtitle_parser");
6440         if ( !subparse )
6441         {
6442                 debug_error ( "failed to create subparse element\n" );
6443                 goto ERROR;
6444         }
6445
6446         charset = util_get_charset(subtitle_uri);
6447         if (charset)
6448         {
6449                 debug_log ("detected charset is %s\n", charset );
6450                 g_object_set (G_OBJECT (subparse), "subtitle-encoding", charset, NULL);
6451         }
6452
6453         mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE;
6454         mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
6455
6456         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse))
6457         {
6458                 debug_warning("failed to add subparse\n");
6459                 goto ERROR;
6460         }
6461
6462         if (!gst_element_link_pads (subsrc, "src", subparse, "sink"))
6463         {
6464                 debug_warning("failed to link subsrc and subparse\n");
6465                 goto ERROR;
6466         }
6467
6468         player->play_subtitle = TRUE;
6469         player->adjust_subtitle_pos = 0;
6470
6471         debug_log ("play subtitle using subtitle file\n");
6472
6473         if (player->pipeline->textbin == NULL)
6474         {
6475                 if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
6476                 {
6477                         debug_error("failed to create textbin. continuing without text\n");
6478                         goto ERROR;
6479                 }
6480
6481                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst)))
6482                 {
6483                         debug_warning("failed to add textbin\n");
6484                         goto ERROR;
6485                 }
6486
6487                 debug_log ("link text input selector and textbin ghost pad");
6488
6489                 player->textsink_linked = 1;
6490                 player->external_text_idx = 0;
6491                 debug_msg("player->textsink_linked set to 1\n");
6492         }
6493         else
6494         {
6495                 debug_log("text bin has been created. reuse it.");
6496                 player->external_text_idx = 1;
6497         }
6498
6499         if (!gst_element_link_pads (subparse, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink"))
6500         {
6501                 debug_warning("failed to link subparse and textbin\n");
6502                 goto ERROR;
6503         }
6504
6505         pad = gst_element_get_static_pad (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
6506
6507         if (!pad)
6508         {
6509                 debug_error("failed to get sink pad from textsink to probe data");
6510                 return MM_ERROR_PLAYER_INTERNAL;
6511         }
6512
6513         gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
6514                                 __mmplayer_subtitle_adjust_position_probe, player, NULL);
6515
6516         gst_object_unref(pad);
6517         pad=NULL;
6518
6519
6520         MMPLAYER_FLEAVE();
6521
6522         return MM_ERROR_NONE;
6523
6524 ERROR:
6525         player->textsink_linked = 0;
6526         return MM_ERROR_PLAYER_INTERNAL;
6527 }
6528
6529 gboolean
6530 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
6531 {
6532         mm_player_t* player = (mm_player_t*) data;
6533         MMMessageParamType msg = {0, };
6534         GstClockTime duration = 0;
6535         gpointer text = NULL;
6536         guint text_size = 0;
6537         gboolean ret = TRUE;
6538         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
6539
6540         MMPLAYER_FENTER();
6541
6542         return_val_if_fail ( player, FALSE );
6543         return_val_if_fail ( buffer, FALSE );
6544
6545         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
6546         text = g_memdup(mapinfo.data, mapinfo.size);
6547         text_size = mapinfo.size;
6548         duration = GST_BUFFER_DURATION(buffer);
6549
6550
6551         if ( player->set_mode.subtitle_off )
6552         {
6553                 debug_log("subtitle is OFF.\n" );
6554                 return TRUE;
6555         }
6556
6557         if ( !text || (text_size == 0))
6558         {
6559                 debug_log("There is no subtitle to be displayed.\n" );
6560                 return TRUE;
6561         }
6562
6563         msg.data = (void *) text;
6564         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
6565
6566         debug_log("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
6567
6568         MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
6569         gst_buffer_unmap(buffer, &mapinfo);
6570
6571         MMPLAYER_FLEAVE();
6572
6573         return ret;
6574 }
6575
6576 static GstPadProbeReturn
6577 __mmplayer_subtitle_adjust_position_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
6578
6579 {
6580         mm_player_t *player = (mm_player_t *) u_data;
6581         GstClockTime cur_timestamp = 0;
6582         gint64 adjusted_timestamp = 0;
6583         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
6584         GstMapInfo probe_info = GST_MAP_INFO_INIT;
6585
6586         return_val_if_fail ( player, FALSE );
6587
6588         gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
6589
6590         if ( player->set_mode.subtitle_off )
6591         {
6592                 debug_log("subtitle is OFF.\n" );
6593                 return TRUE;
6594         }
6595
6596         if (player->adjust_subtitle_pos == 0 )
6597         {
6598                 debug_log("nothing to do");
6599                 return TRUE;
6600         }
6601
6602         cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
6603         adjusted_timestamp = (gint64) cur_timestamp + ((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
6604
6605         gst_buffer_unmap(buffer, &probe_info);
6606
6607         if ( adjusted_timestamp < 0)
6608         {
6609                 debug_log("adjusted_timestamp under zero");
6610                 MMPLAYER_FLEAVE();
6611                 return FALSE;
6612         }
6613
6614         GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
6615         debug_log("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
6616                                 GST_TIME_ARGS(cur_timestamp),
6617                                 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
6618
6619         return GST_PAD_PROBE_OK;
6620 }
6621 static int      __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
6622 {
6623         MMPLAYER_FENTER();
6624
6625         /* check player and subtitlebin are created */
6626         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6627         return_val_if_fail ( player->play_subtitle, MM_ERROR_NOT_SUPPORT_API );
6628
6629         if (position == 0)
6630         {
6631                 debug_log ("nothing to do\n");
6632                 MMPLAYER_FLEAVE();
6633                 return MM_ERROR_NONE;
6634         }
6635
6636         switch (format)
6637         {
6638                 case MM_PLAYER_POS_FORMAT_TIME:
6639                 {
6640                         /* check current postion */
6641                         player->adjust_subtitle_pos = position;
6642
6643                         debug_log("save adjust_subtitle_pos in player") ;
6644                 }
6645                 break;
6646
6647                 default:
6648                 {
6649                         debug_warning("invalid format.\n");
6650                         MMPLAYER_FLEAVE();
6651                         return MM_ERROR_INVALID_ARGUMENT;
6652                 }
6653         }
6654
6655         MMPLAYER_FLEAVE();
6656
6657         return MM_ERROR_NONE;
6658 }
6659 static int __gst_adjust_video_position(mm_player_t* player, int offset)
6660 {
6661         MMPLAYER_FENTER();
6662         debug_log("adjusting video_pos in player") ;
6663         int current_pos = 0;
6664         /* check player and videobin are created */
6665         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6666         if ( !player->pipeline->videobin ||
6667                         !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
6668         {
6669                 debug_log("no video pipeline or sink is there");
6670                 return MM_ERROR_PLAYER_INVALID_STATE ;
6671         }
6672         if (offset == 0)
6673         {
6674                 debug_log ("nothing to do\n");
6675                 MMPLAYER_FLEAVE();
6676                 return MM_ERROR_NONE;
6677         }
6678         if(__gst_get_position ( player, MM_PLAYER_POS_FORMAT_TIME, (unsigned long*)&current_pos ) != MM_ERROR_NONE )
6679         {
6680                 debug_log("failed to get current position");
6681                 return MM_ERROR_PLAYER_INTERNAL;
6682         }
6683         if ( (current_pos - offset ) < GST_TIME_AS_MSECONDS(player->duration) )
6684         {
6685                 debug_log("enter video delay is valid");
6686         }
6687         else {
6688                 debug_log("enter video delay is crossing content boundary");
6689                 return MM_ERROR_INVALID_ARGUMENT ;
6690         }
6691         g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst),"ts-offset",((gint64) offset * G_GINT64_CONSTANT(1000000)),NULL);
6692         debug_log("video delay has been done");
6693         MMPLAYER_FLEAVE();
6694
6695         return MM_ERROR_NONE;
6696 }
6697
6698 static void
6699 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data) // @
6700 {
6701         GstElement *appsrc = element;
6702         tBuffer *buf = (tBuffer *)user_data;
6703         GstBuffer *buffer = NULL;
6704         GstFlowReturn ret = GST_FLOW_OK;
6705         gint len = size;
6706
6707         return_if_fail ( element );
6708         return_if_fail ( buf );
6709
6710         buffer = gst_buffer_new ();
6711
6712         if (buf->offset >= buf->len)
6713         {
6714                 debug_log("call eos appsrc\n");
6715                 g_signal_emit_by_name (appsrc, "end-of-stream", &ret);
6716                 return;
6717         }
6718
6719         if ( buf->len - buf->offset < size)
6720         {
6721                 len = buf->len - buf->offset + buf->offset;
6722         }
6723
6724         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));
6725         GST_BUFFER_OFFSET(buffer) = buf->offset;
6726         GST_BUFFER_OFFSET_END(buffer) = buf->offset + len;
6727
6728         //debug_log("feed buffer %p, offset %u-%u length %u\n", buffer, buf->offset, buf->len,len);
6729         g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
6730
6731         buf->offset += len;
6732 }
6733
6734 static gboolean
6735 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data) // @
6736 {
6737         tBuffer *buf = (tBuffer *)user_data;
6738
6739         return_val_if_fail ( buf, FALSE );
6740
6741         buf->offset  = (int)size;
6742
6743         return TRUE;
6744 }
6745
6746 static void
6747 __gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data) // @
6748 {
6749         mm_player_t *player  = (mm_player_t*)user_data;
6750         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
6751
6752         return_if_fail ( player );
6753
6754         debug_msg("app-src: feed data\n");
6755
6756         if (player->media_stream_buffer_status_cb[type])
6757                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
6758 }
6759
6760 static gboolean
6761 __gst_appsrc_seek_data(GstElement *element, guint64 offset, gpointer user_data) // @
6762 {
6763         mm_player_t *player  = (mm_player_t*)user_data;
6764         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
6765
6766         return_val_if_fail ( player, FALSE );
6767
6768         debug_msg("app-src: seek data\n");
6769
6770         if(player->media_stream_seek_data_cb[type])
6771                 player->media_stream_seek_data_cb[type](type, offset, player->buffer_cb_user_param);
6772
6773         return TRUE;
6774 }
6775
6776
6777 static gboolean
6778 __gst_appsrc_enough_data(GstElement *element, gpointer user_data) // @
6779 {
6780         mm_player_t *player  = (mm_player_t*)user_data;
6781         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
6782
6783         return_val_if_fail ( player, FALSE );
6784
6785         debug_msg("app-src: enough data:%p\n", player->media_stream_buffer_status_cb[type]);
6786
6787         if (player->media_stream_buffer_status_cb[type])
6788                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
6789
6790         return TRUE;
6791 }
6792
6793 int
6794 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
6795 {
6796         mm_player_t* player = (mm_player_t*)hplayer;
6797         GstBuffer *buffer = NULL;
6798         GstFlowReturn gst_ret = GST_FLOW_OK;
6799         int ret = MM_ERROR_NONE;
6800 //      gint len = size;
6801
6802         MMPLAYER_FENTER();
6803
6804         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6805
6806         /* check current state */
6807 //      MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
6808
6809
6810         /* NOTE : we should check and create pipeline again if not created as we destroy
6811          * whole pipeline when stopping in streamming playback
6812          */
6813         if ( ! player->pipeline )
6814         {
6815                 if ( MM_ERROR_NONE != __gst_realize( player ) )
6816                 {
6817                         debug_error("failed to realize before starting. only in streamming\n");
6818                         return MM_ERROR_PLAYER_INTERNAL;
6819                 }
6820         }
6821
6822         debug_msg("app-src: pushing data\n");
6823
6824         if ( buf == NULL )
6825         {
6826                 debug_error("buf is null\n");
6827                 return MM_ERROR_NONE;
6828         }
6829
6830         buffer = gst_buffer_new ();
6831
6832         if (size <= 0)
6833         {
6834                 debug_log("call eos appsrc\n");
6835                 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
6836                 return MM_ERROR_NONE;
6837         }
6838
6839         //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));
6840
6841         debug_log("feed buffer %p, length %u\n", buf, size);
6842         g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
6843
6844         MMPLAYER_FLEAVE();
6845
6846         return ret;
6847 }
6848
6849 /* if retval is FALSE, it will be dropped for perfomance. */
6850 static gboolean
6851 __mmplayer_check_useful_message(mm_player_t *player, GstMessage * message)
6852 {
6853         gboolean retval = FALSE;
6854
6855         if ( !(player->pipeline && player->pipeline->mainbin) )
6856         {
6857                 debug_error("player pipeline handle is null");
6858                 return TRUE;
6859         }
6860
6861         switch (GST_MESSAGE_TYPE (message))
6862         {
6863                 case GST_MESSAGE_TAG:
6864                 case GST_MESSAGE_EOS:
6865                 case GST_MESSAGE_ERROR:
6866                 case GST_MESSAGE_WARNING:
6867                 case GST_MESSAGE_CLOCK_LOST:
6868                 case GST_MESSAGE_NEW_CLOCK:
6869                 case GST_MESSAGE_ELEMENT:
6870                 case GST_MESSAGE_DURATION_CHANGED:
6871                 case GST_MESSAGE_ASYNC_START:
6872                         retval = TRUE;
6873                         break;
6874                 case GST_MESSAGE_ASYNC_DONE:
6875                 case GST_MESSAGE_STATE_CHANGED:
6876                         /* we only handle messages from pipeline */
6877                         if(( message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst ) && (!player->pp_rebuilding))
6878                                 retval = TRUE;
6879                         else
6880                                 retval = FALSE;
6881                         break;
6882                 case GST_MESSAGE_BUFFERING:
6883                 {
6884                         gint buffer_percent = 0;
6885
6886                         gst_message_parse_buffering (message, &buffer_percent);
6887
6888                         if ((MMPLAYER_IS_STREAMING(player)) &&
6889                                 (player->streamer) &&
6890                                 (player->streamer->is_buffering == TRUE) &&
6891                                 (buffer_percent == MAX_BUFFER_PERCENT))
6892                         {
6893                                 debug_log (">>> [%s] Buffering DONE is detected !!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
6894                                 player->streamer->is_buffering_done = TRUE;
6895                         }
6896
6897                         retval = TRUE;
6898                         break;
6899                 }
6900                 default:
6901                         retval = FALSE;
6902                         break;
6903         }
6904
6905         return retval;
6906 }
6907
6908 static GstBusSyncReply
6909 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
6910 {
6911         mm_player_t *player = (mm_player_t *)data;
6912         GstBusSyncReply reply = GST_BUS_DROP;
6913
6914         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
6915         {
6916                 debug_error("player pipeline handle is null");
6917                 return GST_BUS_PASS;
6918         }
6919
6920         if (!__mmplayer_check_useful_message(player, message))
6921         {
6922                 gst_message_unref (message);
6923                 return GST_BUS_DROP;
6924         }
6925
6926         switch (GST_MESSAGE_TYPE (message))
6927         {
6928                 case GST_MESSAGE_STATE_CHANGED:
6929                         /* post directly for fast launch */
6930                         if (player->sync_handler) {
6931                                 __mmplayer_gst_callback(NULL, message, player);
6932                                 reply = GST_BUS_DROP;
6933                         }
6934                         else {
6935                                 reply = GST_BUS_PASS;
6936                         }
6937                         break;
6938                 case GST_MESSAGE_TAG:
6939                         __mmplayer_gst_extract_tag_from_msg(player, message);
6940
6941                         #if 0 // debug
6942                         {
6943                                 GstTagList *tags = NULL;
6944
6945                                 gst_message_parse_tag (message, &tags);
6946                                 if (tags) {
6947                                         debug_error("TAGS received from element \"%s\".\n",
6948                                         GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
6949
6950                                         gst_tag_list_foreach (tags, print_tag, NULL);
6951                                         gst_tag_list_free (tags);
6952                                         tags = NULL;
6953                                 }
6954                                 break;
6955                         }
6956                         #endif
6957                         break;
6958
6959                 case GST_MESSAGE_DURATION_CHANGED:
6960                         __mmplayer_gst_handle_duration(player, message);
6961                         break;
6962                 case GST_MESSAGE_ASYNC_DONE:
6963                         /* NOTE:Don't call gst_callback directly
6964                          * because previous frame can be showed even though this message is received for seek.
6965                          */
6966                 default:
6967                         reply = GST_BUS_PASS;
6968                         break;
6969         }
6970
6971         if (reply == GST_BUS_DROP)
6972                 gst_message_unref (message);
6973
6974         return reply;
6975 }
6976 #ifdef TEST_ES
6977 #if 0   // TO CHECK
6978 static void
6979 __mm_player_src_pad_block_cb (GstPad *pad, gboolean blocked, gpointer user_data)
6980 {
6981         if (blocked)
6982         {
6983                 debug_log("src pad is blocked");
6984         }
6985         else
6986         {
6987                 debug_log("src pad is unblocked");
6988         }
6989 }
6990 #endif
6991 static gboolean
6992 __mmplayer_gst_create_decoder ( mm_player_t *player,
6993                                                                 MMPlayerTrackType track,
6994                                                                 GstPad* srcpad,
6995                                                                 enum MainElementID elemId,
6996                                                                 const gchar* name)
6997 {
6998         gboolean ret = TRUE;
6999         GstPad *sinkpad = NULL;
7000
7001         MMPLAYER_FENTER();
7002
7003         return_val_if_fail( player &&
7004                                                 player->pipeline &&
7005                                                 player->pipeline->mainbin, FALSE);
7006         return_val_if_fail((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE);
7007         return_val_if_fail(srcpad, FALSE);
7008         return_val_if_fail((player->pipeline->mainbin[elemId].gst == NULL), FALSE);
7009
7010         GstElement *decodebin = NULL;
7011         GstCaps *dec_caps = NULL;
7012
7013         /* create decodebin */
7014         decodebin = gst_element_factory_make("decodebin", name);
7015
7016         if (!decodebin)
7017         {
7018                 debug_error("error : fail to create decodebin for %d decoder\n", track);
7019                 ret = FALSE;
7020                 goto ERROR;
7021         }
7022
7023         /* raw pad handling signal */
7024         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7025                                                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
7026
7027         /* This signal is emitted whenever decodebin2 finds a new stream. It is emitted
7028         before looking for any elements that can handle that stream.*/
7029         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
7030                                                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
7031
7032         /* This signal is emitted when a element is added to the bin.*/
7033         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
7034                                                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
7035
7036         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), decodebin))
7037         {
7038                 debug_error("failed to add new decodebin\n");
7039                 ret = FALSE;
7040                 goto ERROR;
7041         }
7042
7043         dec_caps = gst_pad_query_caps (srcpad, NULL);
7044         if (dec_caps)
7045         {
7046                 //debug_log ("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
7047                 g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
7048                 gst_caps_unref(dec_caps);
7049         }
7050
7051         player->pipeline->mainbin[elemId].id = elemId;
7052         player->pipeline->mainbin[elemId].gst = decodebin;
7053
7054         sinkpad = gst_element_get_static_pad (decodebin, "sink");
7055
7056         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
7057         {
7058                 debug_warning ("failed to link [%s:%s] to decoder\n", GST_DEBUG_PAD_NAME(srcpad));
7059                 gst_object_unref (GST_OBJECT(decodebin));
7060         }
7061
7062         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (decodebin))
7063         {
7064                 debug_error("failed to sync second level decodebin state with parent\n");
7065         }
7066
7067         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
7068 // TO CHECK :   gst_pad_set_blocked_async (srcpad, FALSE, __mm_player_src_pad_block_cb, NULL);
7069
7070         debug_log("Total num of %d tracks = %d \n", track, player->selector[track].total_track_num);
7071
7072 ERROR:
7073         if (sinkpad)
7074         {
7075                 gst_object_unref ( GST_OBJECT(sinkpad) );
7076                 sinkpad = NULL;
7077         }
7078         MMPLAYER_FLEAVE();
7079
7080         return ret;
7081 }
7082 #endif
7083
7084 /**
7085  * This function is to create  audio or video pipeline for playing.
7086  *
7087  * @param       player          [in]    handle of player
7088  *
7089  * @return      This function returns zero on success.
7090  * @remark
7091  * @see
7092  */
7093 static int
7094 __mmplayer_gst_create_pipeline(mm_player_t* player) // @
7095 {
7096         GstBus  *bus = NULL;
7097         MMPlayerGstElement *mainbin = NULL;
7098         MMHandleType attrs = 0;
7099         GstElement* element = NULL;
7100 #ifdef TEST_ES
7101         GstElement* elem_src_audio = NULL;
7102         GstElement* elem_src_subtitle = NULL;
7103         GstElement* es_video_queue = NULL;
7104         GstElement* es_audio_queue = NULL;
7105         GstElement* es_subtitle_queue = NULL;
7106 #endif
7107         GList* element_bucket = NULL;
7108         gboolean need_state_holder = TRUE;
7109         gint i = 0;
7110
7111         MMPLAYER_FENTER();
7112
7113         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7114
7115         /* get profile attribute */
7116         attrs = MMPLAYER_GET_ATTRS(player);
7117         if ( !attrs )
7118         {
7119                 debug_error("cannot get content attribute\n");
7120                 goto INIT_ERROR;
7121         }
7122
7123         /* create pipeline handles */
7124         if ( player->pipeline )
7125         {
7126                 debug_warning("pipeline should be released before create new one\n");
7127                 goto INIT_ERROR;
7128         }
7129
7130         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0( sizeof(MMPlayerGstPipelineInfo) );
7131         if (player->pipeline == NULL)
7132                 goto INIT_ERROR;
7133
7134         memset( player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo) );
7135
7136
7137         /* create mainbin */
7138         mainbin = (MMPlayerGstElement*) g_malloc0( sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM );
7139         if (mainbin == NULL)
7140                 goto INIT_ERROR;
7141
7142         memset( mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
7143
7144         /* create pipeline */
7145         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
7146         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
7147         if ( ! mainbin[MMPLAYER_M_PIPE].gst )
7148         {
7149                 debug_error("failed to create pipeline\n");
7150                 goto INIT_ERROR;
7151         }
7152         player->demux_pad_index = 0;
7153         player->subtitle_language_list = NULL;
7154
7155         player->is_subtitle_force_drop = FALSE;
7156         player->last_multiwin_status = FALSE;
7157
7158         _mmplayer_track_initialize(player);
7159
7160         /* create source element */
7161         switch ( player->profile.uri_type )
7162         {
7163                 /* rtsp streamming */
7164                 case MM_PLAYER_URI_TYPE_URL_RTSP:
7165                 {
7166                         gint network_bandwidth;
7167                         gchar *user_agent, *wap_profile;
7168
7169                         element = gst_element_factory_make(player->ini.name_of_rtspsrc, "streaming_source");
7170
7171                         if ( !element )
7172                         {
7173                                 debug_error("failed to create streaming source element\n");
7174                                 break;
7175                         }
7176
7177                         debug_log("using streamming source [%s].\n", player->ini.name_of_rtspsrc);
7178
7179                         /* make it zero */
7180                         network_bandwidth = 0;
7181                         user_agent = wap_profile = NULL;
7182
7183                         /* get attribute */
7184                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
7185                         mm_attrs_get_string_by_name ( attrs,"streaming_wap_profile", &wap_profile );
7186                         mm_attrs_get_int_by_name ( attrs, "streaming_network_bandwidth", &network_bandwidth );
7187
7188                         secure_debug_log("user_agent : %s\n", user_agent);
7189                         secure_debug_log("wap_profile : %s\n", wap_profile);
7190
7191                         /* setting property to streaming source */
7192                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7193                         if ( user_agent )
7194                                 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
7195                         if ( wap_profile )
7196                                 g_object_set(G_OBJECT(element), "wap_profile", wap_profile, NULL);
7197
7198                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7199                                 G_CALLBACK (__mmplayer_gst_rtp_dynamic_pad), player );
7200                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
7201                                 G_CALLBACK (__mmplayer_gst_rtp_no_more_pads), player );
7202
7203                         player->use_decodebin = FALSE;
7204                 }
7205                 break;
7206 #if 0
7207                 /* WFD streamming */
7208                 case MM_PLAYER_URI_TYPE_URL_WFD:
7209                 {
7210                         element = gst_element_factory_make("wfdrtspsrc", "wfd_source");
7211                         if ( !element )
7212                         {
7213                                 debug_error("failed to create wfd streaming source element\n");
7214                                 break;
7215                         }
7216                         debug_log("using wfd streamming source wfdrtspsrc.\n");
7217                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7218                         g_object_set(G_OBJECT(element), "debug", TRUE, NULL);
7219                         g_object_set(G_OBJECT(element), "latency", 0, NULL);
7220                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7221                                G_CALLBACK (__mmplayer_gst_wfd_dynamic_pad), player );
7222
7223                         player->use_decodebin = FALSE;
7224                 }
7225                 break;
7226 #endif
7227                 /* http streaming*/
7228                 case MM_PLAYER_URI_TYPE_URL_HTTP:
7229                 {
7230                         gchar *user_agent, *proxy, *cookies, **cookie_list;
7231                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
7232                         user_agent = proxy = cookies = NULL;
7233                         cookie_list = NULL;
7234                         gint mode = MM_PLAYER_PD_MODE_NONE;
7235
7236                         mm_attrs_get_int_by_name ( attrs, "pd_mode", &mode );
7237
7238                         player->pd_mode = mode;
7239
7240                         debug_log("http playback, PD mode : %d\n", player->pd_mode);
7241
7242                         if ( ! MMPLAYER_IS_HTTP_PD(player) )
7243                         {
7244                                 element = gst_element_factory_make(player->ini.name_of_httpsrc, "http_streaming_source");
7245                                 if ( !element )
7246                                 {
7247                                         debug_error("failed to create http streaming source element[%s].\n", player->ini.name_of_httpsrc);
7248                                         break;
7249                                 }
7250                                 debug_log("using http streamming source [%s].\n", player->ini.name_of_httpsrc);
7251
7252                                 /* get attribute */
7253                                 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
7254                                 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
7255                                 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
7256                                 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
7257
7258                                 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
7259                                         (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
7260                                 {
7261                                         debug_log("get timeout from ini\n");
7262                                         http_timeout = player->ini.http_timeout;
7263                                 }
7264
7265                                 /* get attribute */
7266                                 secure_debug_log("location : %s\n", player->profile.uri);
7267                                 secure_debug_log("cookies : %s\n", cookies);
7268                                 secure_debug_log("proxy : %s\n", proxy);
7269                                 secure_debug_log("user_agent :  %s\n",  user_agent);
7270                                 debug_log("timeout : %d\n",  http_timeout);
7271
7272                                 /* setting property to streaming source */
7273                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7274                                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
7275                                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
7276
7277                                 /* check if prosy is vailid or not */
7278                                 if ( util_check_valid_url ( proxy ) )
7279                                         g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
7280                                 /* parsing cookies */
7281                                 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
7282                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
7283                                 if ( user_agent )
7284                                         g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
7285
7286                                 if ( MMPLAYER_URL_HAS_DASH_SUFFIX(player) )
7287                                 {
7288                                         debug_warning("it's dash. and it's still experimental feature.");
7289                                 }
7290                                 else if (MMPLAYER_URL_HAS_HLS_SUFFIX(player) )
7291                                 {
7292                                         debug_warning("it's hls. using decodebin");
7293                                 }
7294                         }
7295                         else // progressive download
7296                         {
7297                                 gchar* location = NULL;
7298
7299                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
7300                                 {
7301                                         gchar *path = NULL;
7302
7303                                         mm_attrs_get_string_by_name ( attrs, "pd_location", &path );
7304
7305                                         MMPLAYER_FREEIF(player->pd_file_save_path);
7306
7307                                         debug_log("PD Location : %s\n", path);
7308
7309                                         if ( path )
7310                                         {
7311                                                 player->pd_file_save_path = g_strdup(path);
7312                                         }
7313                                         else
7314                                         {
7315                                                 debug_error("can't find pd location so, it should be set \n");
7316                                                 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
7317                                         }
7318                                 }
7319
7320                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
7321                                 if ( !element )
7322                                 {
7323                                         debug_error("failed to create PD push source element[%s].\n", "pdpushsrc");
7324                                         break;
7325                                 }
7326
7327                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
7328                                         g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
7329                                 else
7330                                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7331
7332                                 g_object_get(element, "location", &location, NULL);
7333                                 debug_log("PD_LOCATION [%s].\n", location);
7334                                 if (location)
7335                                         g_free (location);
7336                         }
7337                 }
7338                 break;
7339
7340                 /* file source */
7341                 case MM_PLAYER_URI_TYPE_FILE:
7342                 {
7343
7344                         debug_log("using filesrc for 'file://' handler.\n");
7345
7346                         element = gst_element_factory_make("filesrc", "source");
7347
7348                         if ( !element )
7349                         {
7350                                 debug_error("failed to create filesrc\n");
7351                                 break;
7352                         }
7353
7354                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
7355                         //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL);
7356                 }
7357                 break;
7358
7359                 case MM_PLAYER_URI_TYPE_SS:
7360                 {
7361                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
7362                         element = gst_element_factory_make("souphttpsrc", "http streaming source");
7363                         if ( !element )
7364                         {
7365                                 debug_error("failed to create http streaming source element[%s]", player->ini.name_of_httpsrc);
7366                                 break;
7367                         }
7368
7369                         mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
7370
7371                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
7372                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
7373                         {
7374                                 debug_log("get timeout from ini\n");
7375                                 http_timeout = player->ini.http_timeout;
7376                         }
7377
7378                         /* setting property to streaming source */
7379                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7380                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
7381                 }
7382                 break;
7383
7384                 /* appsrc */
7385                 case MM_PLAYER_URI_TYPE_BUFF:
7386                 {
7387                         guint64 stream_type = GST_APP_STREAM_TYPE_STREAM;
7388
7389                         debug_log("mem src is selected\n");
7390
7391                         element = gst_element_factory_make("appsrc", "buff-source");
7392                         if ( !element )
7393                         {
7394                                 debug_error("failed to create appsrc element\n");
7395                                 break;
7396                         }
7397
7398                         g_object_set( element, "stream-type", stream_type, NULL );
7399                         //g_object_set( element, "size", player->mem_buf.len, NULL );
7400                         //g_object_set( element, "blocksize", (guint64)20480, NULL );
7401
7402                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7403                                 G_CALLBACK(__gst_appsrc_seek_data), player);
7404                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7405                                 G_CALLBACK(__gst_appsrc_feed_data), player);
7406                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7407                                 G_CALLBACK(__gst_appsrc_enough_data), player);
7408                 }
7409                 break;
7410 #ifdef TEST_ES
7411                 case MM_PLAYER_URI_TYPE_ES_BUFF:
7412                 {
7413                         debug_log("es buff src is selected\n");
7414
7415                         if (player->v_stream_caps)
7416                         {
7417                                 element = gst_element_factory_make("appsrc", "video_appsrc");
7418                                 if ( !element )
7419                                 {
7420                                         debug_critical("failed to create video app source element[appsrc].\n" );
7421                                         break;
7422                                 }
7423
7424                                 if ( player->a_stream_caps )
7425                                 {
7426                                         elem_src_audio = gst_element_factory_make("appsrc", "audio_appsrc");
7427                                         if ( !elem_src_audio )
7428                                         {
7429                                                 debug_critical("failed to create audio app source element[appsrc].\n" );
7430                                                 break;
7431                                         }
7432                                 }
7433                         }
7434                         else if ( player->a_stream_caps )
7435                         {
7436                                 /* no video, only audio pipeline*/
7437                                 element = gst_element_factory_make("appsrc", "audio_appsrc");
7438                                 if ( !element )
7439                                 {
7440                                         debug_critical("failed to create audio app source element[appsrc].\n" );
7441                                         break;
7442                                 }
7443                         }
7444
7445                         if ( player->s_stream_caps )
7446                         {
7447                                 elem_src_subtitle = gst_element_factory_make("appsrc", "subtitle_appsrc");
7448                                 if ( !elem_src_subtitle )
7449                                 {
7450                                         debug_critical("failed to create subtitle app source element[appsrc].\n" );
7451                                         break;
7452                                 }
7453                         }
7454
7455                         debug_log("setting app sources properties.\n");
7456                         debug_log("location : %s\n", player->profile.uri);
7457
7458                         if ( player->v_stream_caps && element )
7459                         {
7460                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
7461                                                                                             "blocksize", (guint)1048576,        /* size of many video frames are larger than default blocksize as 4096 */
7462                                                                                                 "caps", player->v_stream_caps, NULL);
7463
7464                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
7465                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
7466                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
7467                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
7468
7469                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
7470                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
7471                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7472                                                                                                                 G_CALLBACK(__gst_seek_video_data), player);
7473
7474                                 if (player->a_stream_caps && elem_src_audio)
7475                                 {
7476                                         g_object_set(G_OBJECT(elem_src_audio), "format", GST_FORMAT_TIME,
7477                                                                                                                         "caps", player->a_stream_caps, NULL);
7478
7479                                         if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7480                                                 g_object_set(G_OBJECT(elem_src_audio), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7481                                         if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7482                                                 g_object_set(G_OBJECT(elem_src_audio), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7483
7484                                         /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
7485                                         gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_audio), GST_APP_STREAM_TYPE_SEEKABLE);
7486                                         MMPLAYER_SIGNAL_CONNECT( player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7487                                                                                                                 G_CALLBACK(__gst_seek_audio_data), player);
7488                                 }
7489                         }
7490                         else if (player->a_stream_caps && element)
7491                         {
7492                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
7493                                                                                                 "caps", player->a_stream_caps, NULL);
7494
7495                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7496                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7497                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7498                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7499
7500                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
7501                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
7502                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7503                                                                                                                         G_CALLBACK(__gst_seek_audio_data), player);
7504                         }
7505
7506                         if (player->s_stream_caps && elem_src_subtitle)
7507                         {
7508                                 g_object_set(G_OBJECT(elem_src_subtitle), "format", GST_FORMAT_TIME,
7509                                                                                                                  "caps", player->s_stream_caps, NULL);
7510
7511                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
7512                                         g_object_set(G_OBJECT(elem_src_subtitle), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
7513                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
7514                                         g_object_set(G_OBJECT(elem_src_subtitle), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
7515
7516                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_subtitle), GST_APP_STREAM_TYPE_SEEKABLE);
7517
7518                                 MMPLAYER_SIGNAL_CONNECT( player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7519                                                                                                                                 G_CALLBACK(__gst_seek_subtitle_data), player);
7520                         }
7521
7522                         if (!player->es_player_push_mode)
7523                         {
7524                                 if (player->v_stream_caps && element)
7525                                 {
7526                                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7527                                                                                                                         G_CALLBACK(__gst_appsrc_feed_video_data), player);
7528                                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7529                                                                                                                         G_CALLBACK(__gst_appsrc_enough_video_data), player);
7530
7531                                         if (player->a_stream_caps && elem_src_audio)
7532                                         {
7533                                                 MMPLAYER_SIGNAL_CONNECT( player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7534                                                                                                                         G_CALLBACK(__gst_appsrc_feed_audio_data), player);
7535                                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7536                                                                                                                         G_CALLBACK(__gst_appsrc_enough_audio_data), player);
7537                                         }
7538                                 }
7539                                 else if (player->a_stream_caps && element)
7540                                 {
7541                                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7542                                                                                                                         G_CALLBACK(__gst_appsrc_feed_audio_data), player);
7543                                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7544                                                                                                                         G_CALLBACK(__gst_appsrc_enough_audio_data), player);
7545                                 }
7546
7547                                 if (player->s_stream_caps && elem_src_subtitle)
7548                                 {
7549                                         MMPLAYER_SIGNAL_CONNECT( player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7550                                                                                                                         G_CALLBACK(__gst_appsrc_feed_subtitle_data), player);
7551                                 }
7552                         }
7553
7554                         need_state_holder = FALSE;
7555                 }
7556                 break;
7557 #endif
7558                 /* appsrc */
7559                 case MM_PLAYER_URI_TYPE_MEM:
7560                 {
7561                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
7562
7563                         debug_log("mem src is selected\n");
7564
7565                         element = gst_element_factory_make("appsrc", "mem-source");
7566                         if ( !element )
7567                         {
7568                                 debug_error("failed to create appsrc element\n");
7569                                 break;
7570                         }
7571
7572                         g_object_set( element, "stream-type", stream_type, NULL );
7573                         g_object_set( element, "size", player->mem_buf.len, NULL );
7574                         g_object_set( element, "blocksize", (guint64)20480, NULL );
7575
7576                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7577                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->mem_buf );
7578                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7579                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->mem_buf );
7580                 }
7581                 break;
7582                 case MM_PLAYER_URI_TYPE_URL:
7583                 break;
7584
7585                 case MM_PLAYER_URI_TYPE_TEMP:
7586                 break;
7587
7588                 case MM_PLAYER_URI_TYPE_NONE:
7589                 default:
7590                 break;
7591         }
7592
7593         /* check source element is OK */
7594         if ( ! element )
7595         {
7596                 debug_error("no source element was created.\n");
7597                 goto INIT_ERROR;
7598         }
7599
7600         /* take source element */
7601         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
7602         mainbin[MMPLAYER_M_SRC].gst = element;
7603         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
7604
7605         if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL))
7606         {
7607                 player->streamer = __mm_player_streaming_create();
7608                 __mm_player_streaming_initialize(player->streamer);
7609         }
7610
7611         if ( MMPLAYER_IS_HTTP_PD(player) )
7612         {
7613                 gdouble pre_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
7614
7615                 debug_log ("Picked queue2 element(pre buffer : %d sec)....\n", pre_buffering_time);
7616                 element = gst_element_factory_make("queue2", "queue2");
7617                 if ( !element )
7618                 {
7619                         debug_error ( "failed to create http streaming buffer element\n" );
7620                         goto INIT_ERROR;
7621                 }
7622
7623                 /* take it */
7624                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
7625                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
7626                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
7627
7628                 pre_buffering_time = (pre_buffering_time > 0)?(pre_buffering_time):(player->ini.http_buffering_time);
7629
7630                 __mm_player_streaming_set_queue2(player->streamer,
7631                                 element,
7632                                 TRUE,
7633                                 player->ini.http_max_size_bytes,
7634                                 pre_buffering_time,
7635                                 1.0,
7636                                 player->ini.http_buffering_limit,
7637                                 FALSE,
7638                                 NULL,
7639                                 0);
7640         }
7641 #ifdef TEST_ES
7642         if (MMPLAYER_IS_ES_BUFF_SRC(player))
7643         {
7644                 if (player->v_stream_caps)
7645                 {
7646                         es_video_queue = gst_element_factory_make("queue2", "video_queue");
7647                         if (!es_video_queue)
7648                         {
7649                                 debug_error ("create es_video_queue for es player failed\n");
7650                                 goto INIT_ERROR;
7651                         }
7652                         mainbin[MMPLAYER_M_V_BUFFER].id = MMPLAYER_M_V_BUFFER;
7653                         mainbin[MMPLAYER_M_V_BUFFER].gst = es_video_queue;
7654                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_V_BUFFER]);
7655
7656                         /* Adding audio appsrc to bucket */
7657                         if (player->a_stream_caps && elem_src_audio)
7658                         {
7659                                 mainbin[MMPLAYER_M_2ND_SRC].id = MMPLAYER_M_2ND_SRC;
7660                                 mainbin[MMPLAYER_M_2ND_SRC].gst = elem_src_audio;
7661                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_2ND_SRC]);
7662
7663                                 es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
7664                                 if (!es_audio_queue)
7665                                 {
7666                                         debug_error ("create es_audio_queue for es player failed\n");
7667                                         goto INIT_ERROR;
7668                                 }
7669                                 mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
7670                                 mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
7671                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
7672                         }
7673                 }
7674                 /* Only audio stream, no video */
7675                 else if (player->a_stream_caps)
7676                 {
7677                         es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
7678                         if (!es_audio_queue)
7679                         {
7680                                 debug_error ("create es_audio_queue for es player failed\n");
7681                                 goto INIT_ERROR;
7682                         }
7683                         mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
7684                         mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
7685                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
7686                 }
7687
7688                 if (player->s_stream_caps && elem_src_subtitle)
7689                 {
7690                         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
7691                         mainbin[MMPLAYER_M_SUBSRC].gst = elem_src_subtitle;
7692                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SUBSRC]);
7693
7694                         es_subtitle_queue = gst_element_factory_make("queue2", "subtitle_queue");
7695                         if (!es_subtitle_queue)
7696                         {
7697                                 debug_error ("create es_subtitle_queue for es player failed\n");
7698                                 goto INIT_ERROR;
7699                         }
7700                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_V_BUFFER;
7701                         mainbin[MMPLAYER_M_S_BUFFER].gst = es_subtitle_queue;
7702                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
7703                 }
7704         }
7705 #endif
7706
7707         /* create autoplugging element if src element is not a rtsp src */
7708         if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
7709                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_WFD)
7710 #ifdef TEST_ES
7711                 && (player->profile.uri_type != MM_PLAYER_URI_TYPE_ES_BUFF)
7712 #endif
7713                 )
7714         {
7715                 element = NULL;
7716                 enum MainElementID elemId = MMPLAYER_M_NUM;
7717
7718                 if ((player->use_decodebin) &&
7719                         ((MMPLAYER_IS_HTTP_PD(player)) ||
7720                          (!MMPLAYER_IS_HTTP_STREAMING(player))))
7721                 {
7722                         elemId = MMPLAYER_M_AUTOPLUG;
7723                         element = __mmplayer_create_decodebin(player);
7724                         need_state_holder = FALSE;
7725                 }
7726                 else
7727                 {
7728                         elemId = MMPLAYER_M_TYPEFIND;
7729                         element = gst_element_factory_make("typefind", "typefinder");
7730                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
7731                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
7732                 }
7733
7734
7735                 /* check autoplug element is OK */
7736                 if ( ! element )
7737                 {
7738                         debug_error("can not create element (%d)\n", elemId);
7739                         goto INIT_ERROR;
7740                 }
7741
7742                 mainbin[elemId].id = elemId;
7743                 mainbin[elemId].gst = element;
7744
7745                 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
7746         }
7747
7748         /* add elements to pipeline */
7749         if( !__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket))
7750         {
7751                 debug_error("Failed to add elements to pipeline\n");
7752                 goto INIT_ERROR;
7753         }
7754
7755
7756         /* linking elements in the bucket by added order. */
7757         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
7758         {
7759                 debug_error("Failed to link some elements\n");
7760                 goto INIT_ERROR;
7761         }
7762
7763
7764         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
7765         if ( need_state_holder )
7766         {
7767                 /* create */
7768                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
7769                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make ("fakesink", "state-holder");
7770
7771                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
7772                 {
7773                         debug_error ("fakesink element could not be created\n");
7774                         goto INIT_ERROR;
7775                 }
7776                 GST_OBJECT_FLAG_UNSET (mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
7777
7778                 /* take ownership of fakesink. we are reusing it */
7779                 gst_object_ref( mainbin[MMPLAYER_M_SRC_FAKESINK].gst );
7780
7781                 /* add */
7782                 if ( FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
7783                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst) )
7784                 {
7785                         debug_error("failed to add fakesink to bin\n");
7786                         goto INIT_ERROR;
7787                 }
7788         }
7789
7790         /* now we have completed mainbin. take it */
7791         player->pipeline->mainbin = mainbin;
7792
7793 #ifdef TEST_ES
7794         if (MMPLAYER_IS_ES_BUFF_SRC(player))
7795         {
7796                 GstPad *srcpad = NULL;
7797
7798                 if (mainbin[MMPLAYER_M_V_BUFFER].gst)
7799                 {
7800                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_V_BUFFER].gst, "src");
7801                         if (srcpad)
7802                         {
7803                                 __mmplayer_gst_create_decoder ( player,
7804                                                                                                 MM_PLAYER_TRACK_TYPE_VIDEO,
7805                                                                                                 srcpad,
7806                                                                                                 MMPLAYER_M_AUTOPLUG_V_DEC,
7807                                                                                                 "video_decodebin");
7808
7809                                 gst_object_unref ( GST_OBJECT(srcpad) );
7810                                 srcpad = NULL;
7811                         }
7812                 }
7813
7814                 if ((player->a_stream_caps) && (mainbin[MMPLAYER_M_A_BUFFER].gst))
7815                 {
7816                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_BUFFER].gst, "src");
7817                         if (srcpad)
7818                         {
7819                                 __mmplayer_gst_create_decoder ( player,
7820                                                                                                 MM_PLAYER_TRACK_TYPE_AUDIO,
7821                                                                                                 srcpad,
7822                                                                                                 MMPLAYER_M_AUTOPLUG_A_DEC,
7823                                                                                                 "audio_decodebin");
7824
7825                                 gst_object_unref ( GST_OBJECT(srcpad) );
7826                                 srcpad = NULL;
7827                         } // else error
7828                 } //  else error
7829
7830                 if (mainbin[MMPLAYER_M_S_BUFFER].gst)
7831                 {
7832                         __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
7833                 }
7834         }
7835 #endif
7836
7837
7838         /* connect bus callback */
7839         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
7840         if ( !bus )
7841         {
7842                 debug_error ("cannot get bus from pipeline.\n");
7843                 goto INIT_ERROR;
7844         }
7845
7846         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
7847
7848         player->context.thread_default = g_main_context_get_thread_default();
7849
7850         if (NULL == player->context.thread_default)
7851         {
7852                 player->context.thread_default = g_main_context_default();
7853                 debug_log("thread-default context is the global default context");
7854         }
7855         debug_warning("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
7856
7857         /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
7858         if ( __mmplayer_check_subtitle ( player ) )
7859         {
7860                 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
7861                         debug_error("fail to create subtitle src\n");
7862         }
7863
7864         /* set sync handler to get tag synchronously */
7865         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL);
7866
7867         /* finished */
7868         gst_object_unref(GST_OBJECT(bus));
7869         g_list_free(element_bucket);
7870
7871         MMPLAYER_FLEAVE();
7872
7873         return MM_ERROR_NONE;
7874
7875 INIT_ERROR:
7876
7877         __mmplayer_gst_destroy_pipeline(player);
7878         g_list_free(element_bucket);
7879
7880         /* release element which are not added to bin */
7881         for ( i = 1; i < MMPLAYER_M_NUM; i++ )  /* NOTE : skip pipeline */
7882         {
7883                 if ( mainbin[i].gst )
7884                 {
7885                         GstObject* parent = NULL;
7886                         parent = gst_element_get_parent( mainbin[i].gst );
7887
7888                         if ( !parent )
7889                         {
7890                                 gst_object_unref(GST_OBJECT(mainbin[i].gst));
7891                                 mainbin[i].gst = NULL;
7892                         }
7893                         else
7894                         {
7895                                 gst_object_unref(GST_OBJECT(parent));
7896                         }
7897                 }
7898         }
7899
7900         /* release pipeline with it's childs */
7901         if ( mainbin[MMPLAYER_M_PIPE].gst )
7902         {
7903                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7904         }
7905
7906         MMPLAYER_FREEIF( player->pipeline );
7907         MMPLAYER_FREEIF( mainbin );
7908
7909         return MM_ERROR_PLAYER_INTERNAL;
7910 }
7911
7912 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
7913 {
7914         GSource *source = NULL;
7915
7916         MMPLAYER_FENTER();
7917
7918         source = g_main_context_find_source_by_id (context, source_id);
7919
7920         if (source != NULL)
7921         {
7922                 debug_warning("context: %p, source id: %d, source: %p", context, source_id, source);
7923                 g_source_destroy(source);
7924         }
7925
7926         MMPLAYER_FLEAVE();
7927 }
7928
7929 static int
7930 __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
7931 {
7932         gint timeout = 0;
7933         int ret = MM_ERROR_NONE;
7934
7935         MMPLAYER_FENTER();
7936
7937         return_val_if_fail ( player, MM_ERROR_INVALID_HANDLE );
7938
7939         /* cleanup stuffs */
7940         MMPLAYER_FREEIF(player->type);
7941         player->have_dynamic_pad = FALSE;
7942         player->no_more_pad = FALSE;
7943         player->num_dynamic_pad = 0;
7944         player->demux_pad_index = 0;
7945         player->subtitle_language_list = NULL;
7946         player->use_deinterleave = FALSE;
7947         player->pp_rebuilding = FALSE;
7948         player->max_audio_channels = 0;
7949         player->video_share_api_delta = 0;
7950         player->video_share_clock_delta = 0;
7951         player->video_hub_download_mode = 0;
7952
7953         __mmplayer_post_proc_reset(player);
7954
7955         if (player->streamer)
7956         {
7957                 __mm_player_streaming_deinitialize (player->streamer);
7958                 __mm_player_streaming_destroy(player->streamer);
7959                 player->streamer = NULL;
7960         }
7961
7962         /* cleanup unlinked mime type */
7963         MMPLAYER_FREEIF(player->unlinked_audio_mime);
7964         MMPLAYER_FREEIF(player->unlinked_video_mime);
7965         MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
7966
7967         /* cleanup running stuffs */
7968         __mmplayer_cancel_eos_timer( player );
7969
7970         /* remove sound cb */
7971         if ( MM_ERROR_NONE != mm_sound_remove_device_information_changed_callback())
7972         {
7973                 debug_error("failed to mm_sound_remove_device_information_changed_callback()");
7974         }
7975
7976         /* cleanup gst stuffs */
7977         if ( player->pipeline )
7978         {
7979                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
7980                 GstTagList* tag_list = player->pipeline->tag_list;
7981
7982                 /* first we need to disconnect all signal hander */
7983                 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_ALL );
7984
7985                 /* disconnecting bus watch */
7986                 if ( player->bus_watcher )
7987                         __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
7988                 player->bus_watcher = 0;
7989
7990                 if ( mainbin )
7991                 {
7992                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
7993                         MMPlayerGstElement* videobin = player->pipeline->videobin;
7994                         MMPlayerGstElement* textbin = player->pipeline->textbin;
7995                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mainbin[MMPLAYER_M_PIPE].gst));
7996                         gst_bus_set_sync_handler (bus, NULL, NULL, NULL);
7997                         gst_object_unref(bus);
7998
7999                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8000                         ret = __mmplayer_gst_set_state ( player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout );
8001                         if ( ret != MM_ERROR_NONE )
8002                         {
8003                                 debug_error("fail to change state to NULL\n");
8004                                 return MM_ERROR_PLAYER_INTERNAL;
8005                         }
8006
8007                         debug_warning("succeeded in chaning state to NULL\n");
8008
8009                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
8010
8011                         /* free fakesink */
8012                         if ( mainbin[MMPLAYER_M_SRC_FAKESINK].gst )
8013                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
8014
8015                         /* free avsysaudiosink
8016                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
8017                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
8018                         */
8019                         MMPLAYER_FREEIF( audiobin );
8020                         MMPLAYER_FREEIF( videobin );
8021                         MMPLAYER_FREEIF( textbin );
8022                         MMPLAYER_FREEIF( mainbin );
8023                 }
8024
8025                 if ( tag_list )
8026                         gst_tag_list_free(tag_list);
8027
8028                 MMPLAYER_FREEIF( player->pipeline );
8029         }
8030         MMPLAYER_FREEIF(player->album_art);
8031
8032         if (player->v_stream_caps)
8033         {
8034                 gst_caps_unref(player->v_stream_caps);
8035                 player->v_stream_caps = NULL;
8036         }
8037 #ifdef TEST_ES
8038         if (player->a_stream_caps)
8039         {
8040                 gst_caps_unref(player->a_stream_caps);
8041                 player->a_stream_caps = NULL;
8042         }
8043         if (player->s_stream_caps)
8044         {
8045                 gst_caps_unref(player->s_stream_caps);
8046                 player->s_stream_caps = NULL;
8047         }
8048 #endif
8049         _mmplayer_track_destroy(player);
8050
8051         if ( player->sink_elements )
8052                 g_list_free ( player->sink_elements );
8053         player->sink_elements = NULL;
8054
8055         debug_warning("finished destroy pipeline\n");
8056
8057         MMPLAYER_FLEAVE();
8058
8059         return ret;
8060 }
8061
8062 static int __gst_realize(mm_player_t* player) // @
8063 {
8064         gint timeout = 0;
8065         int ret = MM_ERROR_NONE;
8066
8067         MMPLAYER_FENTER();
8068
8069         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8070
8071         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
8072
8073         ret = __mmplayer_gst_create_pipeline(player);
8074         if ( ret )
8075         {
8076                 debug_error("failed to create pipeline\n");
8077                 return ret;
8078         }
8079
8080         /* set pipeline state to READY */
8081         /* NOTE : state change to READY must be performed sync. */
8082         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8083         ret = __mmplayer_gst_set_state(player,
8084                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
8085
8086         if ( ret != MM_ERROR_NONE )
8087         {
8088                 /* return error if failed to set state */
8089                 debug_error("failed to set READY state");
8090                 return ret;
8091         }
8092         else
8093         {
8094                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
8095         }
8096
8097         /* create dot before error-return. for debugging */
8098         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-realize" );
8099
8100         MMPLAYER_FLEAVE();
8101
8102         return ret;
8103 }
8104
8105 static int __gst_unrealize(mm_player_t* player) // @
8106 {
8107         int ret = MM_ERROR_NONE;
8108
8109         MMPLAYER_FENTER();
8110
8111         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8112
8113         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
8114         MMPLAYER_PRINT_STATE(player);
8115
8116         /* release miscellaneous information */
8117         __mmplayer_release_misc( player );
8118
8119         /* destroy pipeline */
8120         ret = __mmplayer_gst_destroy_pipeline( player );
8121         if ( ret != MM_ERROR_NONE )
8122         {
8123                 debug_error("failed to destory pipeline\n");
8124                 return ret;
8125         }
8126
8127         /* release miscellaneous information.
8128            these info needs to be released after pipeline is destroyed. */
8129         __mmplayer_release_misc_post( player );
8130
8131         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
8132
8133         MMPLAYER_FLEAVE();
8134
8135         return ret;
8136 }
8137
8138 static int __gst_pending_seek ( mm_player_t* player )
8139 {
8140         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
8141         int ret = MM_ERROR_NONE;
8142
8143         MMPLAYER_FENTER();
8144
8145         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8146
8147         if ( !player->pending_seek.is_pending )
8148         {
8149                 debug_log("pending seek is not reserved. nothing to do.\n" );
8150                 return ret;
8151         }
8152
8153         /* check player state if player could pending seek or not. */
8154         current_state = MMPLAYER_CURRENT_STATE(player);
8155
8156         if ( current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING  )
8157         {
8158                 debug_warning("try to pending seek in %s state, try next time. \n",
8159                         MMPLAYER_STATE_GET_NAME(current_state));
8160                 return ret;
8161         }
8162
8163         debug_log("trying to play from (%lu) pending position\n", player->pending_seek.pos);
8164
8165         ret = __gst_set_position ( player, player->pending_seek.format, player->pending_seek.pos, FALSE );
8166
8167         if ( MM_ERROR_NONE != ret )
8168                 debug_error("failed to seek pending postion. just keep staying current position.\n");
8169
8170         player->pending_seek.is_pending = FALSE;
8171
8172         MMPLAYER_FLEAVE();
8173
8174         return ret;
8175 }
8176
8177 static int __gst_start(mm_player_t* player) // @
8178 {
8179         gboolean sound_extraction = 0;
8180         int ret = MM_ERROR_NONE;
8181 #ifdef TEST_ES
8182         gboolean async = FALSE;
8183 #endif
8184         MMPLAYER_FENTER();
8185
8186         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8187
8188         /* get sound_extraction property */
8189         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
8190
8191         /* NOTE : if SetPosition was called before Start. do it now */
8192         /* streaming doesn't support it. so it should be always sync */
8193         /* !! create one more api to check if there is pending seek rather than checking variables */
8194         if ( (player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player))
8195         {
8196                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
8197                 ret = __gst_pause(player, FALSE);
8198                 if ( ret != MM_ERROR_NONE )
8199                 {
8200                         debug_error("failed to set state to PAUSED for pending seek\n");
8201                         return ret;
8202                 }
8203
8204                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
8205
8206                 if ( sound_extraction )
8207                 {
8208                         debug_log("setting pcm extraction\n");
8209
8210                         ret = __mmplayer_set_pcm_extraction(player);
8211                         if ( MM_ERROR_NONE != ret )
8212                         {
8213                                 debug_warning("failed to set pcm extraction\n");
8214                                 return ret;
8215                         }
8216                 }
8217                 else
8218                 {
8219                         if ( MM_ERROR_NONE != __gst_pending_seek(player) )
8220                         {
8221                                 debug_warning("failed to seek pending postion. starting from the begin of content.\n");
8222                         }
8223                 }
8224         }
8225
8226         debug_log("current state before doing transition");
8227         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
8228         MMPLAYER_PRINT_STATE(player);
8229
8230 #ifdef TEST_ES
8231         /* set pipeline state to PLAYING  */
8232         if (player->es_player_push_mode)
8233         {
8234                 async = TRUE;
8235         }
8236         /* set pipeline state to PLAYING  */
8237         ret = __mmplayer_gst_set_state(player,
8238                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
8239 #else
8240         /* set pipeline state to PLAYING  */
8241         ret = __mmplayer_gst_set_state(player,
8242                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
8243 #endif
8244         if (ret == MM_ERROR_NONE)
8245         {
8246                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
8247         }
8248         else
8249         {
8250                 debug_error("failed to set state to PLAYING");
8251                 return ret;
8252         }
8253
8254         /* generating debug info before returning error */
8255         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-start" );
8256
8257         MMPLAYER_FLEAVE();
8258
8259         return ret;
8260 }
8261
8262 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
8263 {
8264         MMPLAYER_FENTER();
8265
8266         return_if_fail(player
8267                 && player->pipeline
8268                 && player->pipeline->audiobin
8269                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
8270
8271         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
8272
8273         usleep(time);
8274
8275         MMPLAYER_FLEAVE();
8276 }
8277
8278 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
8279 {
8280         MMPLAYER_FENTER();
8281
8282         return_if_fail(player
8283                 && player->pipeline
8284                 && player->pipeline->audiobin
8285                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
8286
8287         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
8288
8289         MMPLAYER_FLEAVE();
8290 }
8291
8292 static int __gst_stop(mm_player_t* player) // @
8293 {
8294         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
8295         MMHandleType attrs = 0;
8296         gboolean fadedown = FALSE;
8297         gboolean rewind = FALSE;
8298         gint timeout = 0;
8299         int ret = MM_ERROR_NONE;
8300         GstState state;
8301 #ifdef TEST_ES
8302         gboolean async = FALSE;
8303 #endif
8304         MMPLAYER_FENTER();
8305
8306         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
8307         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
8308
8309         debug_log("current state before doing transition");
8310         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
8311         MMPLAYER_PRINT_STATE(player);
8312
8313         attrs = MMPLAYER_GET_ATTRS(player);
8314         if ( !attrs )
8315         {
8316                 debug_error("cannot get content attribute\n");
8317                 return MM_ERROR_PLAYER_INTERNAL;
8318         }
8319
8320         mm_attrs_get_int_by_name(attrs, "sound_fadedown", &fadedown);
8321
8322         /* enable fadedown */
8323         if (fadedown || player->sm.by_asm_cb)
8324                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8325
8326         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
8327         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
8328
8329         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_BUFF ||
8330                 player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS)
8331         {
8332                 state = GST_STATE_READY;
8333         }
8334         else
8335         {
8336                 state = GST_STATE_PAUSED;
8337
8338                 if ( ! MMPLAYER_IS_STREAMING(player) ||
8339                         (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked)) {
8340                         rewind = TRUE;
8341                 }
8342         }
8343 #ifdef TEST_ES
8344         if (player->es_player_push_mode)
8345         {
8346                 async = TRUE;
8347         }
8348         /* set gst state */
8349         ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, async, timeout );
8350 #else
8351         /* set gst state */
8352         ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, FALSE, timeout );
8353 #endif
8354
8355         /* disable fadeout */
8356         if (fadedown || player->sm.by_asm_cb)
8357                 __mmplayer_undo_sound_fadedown(player);
8358
8359         /* return if set_state has failed */
8360         if ( ret != MM_ERROR_NONE )
8361         {
8362                 debug_error("failed to set state.\n");
8363                 return ret;
8364         }
8365
8366         /* rewind */
8367         if ( rewind )
8368         {
8369                 if ( ! __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8370                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
8371                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE) )
8372                 {
8373                         debug_warning("failed to rewind\n");
8374                         ret = MM_ERROR_PLAYER_SEEK;
8375                 }
8376         }
8377
8378         /* initialize */
8379         player->sent_bos = FALSE;
8380
8381 #ifdef TEST_ES
8382         if (player->es_player_push_mode) //for cloudgame
8383         {
8384                 timeout = 0;
8385         }
8386 #endif
8387         /* wait for seek to complete */
8388         change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
8389         if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL )
8390         {
8391                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
8392         }
8393         else
8394         {
8395                 debug_error("fail to stop player.\n");
8396                 ret = MM_ERROR_PLAYER_INTERNAL;
8397                 __mmplayer_dump_pipeline_state(player);
8398         }
8399
8400         /* generate dot file if enabled */
8401         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-stop" );
8402
8403         MMPLAYER_FLEAVE();
8404
8405         return ret;
8406 }
8407
8408 int __gst_pause(mm_player_t* player, gboolean async) // @
8409 {
8410         int ret = MM_ERROR_NONE;
8411
8412         MMPLAYER_FENTER();
8413
8414         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
8415         return_val_if_fail(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
8416
8417         debug_log("current state before doing transition");
8418         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
8419         MMPLAYER_PRINT_STATE(player);
8420
8421         /* set pipeline status to PAUSED */
8422         player->ignore_asyncdone = TRUE;
8423
8424         ret = __mmplayer_gst_set_state(player,
8425                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
8426
8427         player->ignore_asyncdone = FALSE;
8428
8429         if ( FALSE == async )
8430         {
8431                 if ( ret != MM_ERROR_NONE )
8432                 {
8433                         GstMessage *msg = NULL;
8434                         GTimer *timer = NULL;
8435                         gdouble MAX_TIMEOUT_SEC = 3;
8436
8437                         debug_error("failed to set state to PAUSED");
8438
8439                         timer = g_timer_new();
8440                         g_timer_start(timer);
8441
8442                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
8443                         gboolean got_msg = FALSE;
8444                         /* check if gst error posted or not */
8445                         do
8446                         {
8447                                 msg = gst_bus_timed_pop(bus, GST_SECOND /2);
8448                                 if (msg)
8449                                 {
8450                                         if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR)
8451                                         {
8452                                                 GError *error = NULL;
8453
8454                                                 /* parse error code */
8455                                                 gst_message_parse_error(msg, &error, NULL);
8456
8457                                                 if ( gst_structure_has_name ( gst_message_get_structure(msg), "streaming_error" ) )
8458                                                 {
8459                                                         /* Note : the streaming error from the streaming source is handled
8460                                                          *   using __mmplayer_handle_streaming_error.
8461                                                          */
8462                                                         __mmplayer_handle_streaming_error ( player, msg );
8463
8464                                                 }
8465                                                 else if (error)
8466                                                 {
8467                                                         debug_error("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
8468
8469                                                         if (error->domain == GST_STREAM_ERROR)
8470                                                         {
8471                                                                 ret = __gst_handle_stream_error( player, error, msg );
8472                                                         }
8473                                                         else if (error->domain == GST_RESOURCE_ERROR)
8474                                                         {
8475                                                                 ret = __gst_handle_resource_error( player, error->code );
8476                                                         }
8477                                                         else if (error->domain == GST_LIBRARY_ERROR)
8478                                                         {
8479                                                                 ret = __gst_handle_library_error( player, error->code );
8480                                                         }
8481                                                         else if (error->domain == GST_CORE_ERROR)
8482                                                         {
8483                                                                 ret = __gst_handle_core_error( player, error->code );
8484                                                         }
8485                                                 }
8486
8487                                                 got_msg = TRUE;
8488                                                 player->msg_posted = TRUE;
8489                                         }
8490                                         gst_message_unref(msg);
8491                                 }
8492                         } while (!got_msg && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
8493                         /* clean */
8494                         gst_object_unref(bus);
8495                         g_timer_stop (timer);
8496                         g_timer_destroy (timer);
8497
8498                         return ret;
8499                 }
8500                 else if ( (!player->pipeline->videobin) && (!player->pipeline->audiobin) )
8501                 {
8502                         if (MMPLAYER_IS_RTSP_STREAMING(player))
8503                                 return ret;
8504                         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
8505                 }
8506                 else if ( ret== MM_ERROR_NONE)
8507                 {
8508                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
8509                 }
8510         }
8511
8512         /* generate dot file before returning error */
8513         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-pause" );
8514
8515         MMPLAYER_FLEAVE();
8516
8517         return ret;
8518 }
8519
8520 int __gst_resume(mm_player_t* player, gboolean async) // @
8521 {
8522         int ret = MM_ERROR_NONE;
8523         gint timeout = 0;
8524
8525         MMPLAYER_FENTER();
8526
8527         return_val_if_fail(player && player->pipeline,
8528                 MM_ERROR_PLAYER_NOT_INITIALIZED);
8529
8530         debug_log("current state before doing transition");
8531         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
8532         MMPLAYER_PRINT_STATE(player);
8533
8534         /* generate dot file before returning error */
8535         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
8536
8537         __mmplayer_set_antishock( player , FALSE );
8538
8539         if ( async )
8540                 debug_log("do async state transition to PLAYING.\n");
8541
8542         /* set pipeline state to PLAYING */
8543         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8544
8545         ret = __mmplayer_gst_set_state(player,
8546                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout );
8547         if (ret != MM_ERROR_NONE)
8548         {
8549                 debug_error("failed to set state to PLAYING\n");
8550                 return ret;
8551         }
8552         else
8553         {
8554                 if (async == FALSE)
8555                 {
8556                         // MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING );
8557                         debug_log("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
8558                         ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
8559                 }
8560         }
8561
8562         /* generate dot file before returning error */
8563         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
8564
8565         MMPLAYER_FLEAVE();
8566
8567         return ret;
8568 }
8569
8570 static int
8571 __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called) // @
8572 {
8573         unsigned long dur_msec = 0;
8574         gint64 dur_nsec = 0;
8575         gint64 pos_nsec = 0;
8576         gboolean ret = TRUE;
8577         gboolean accurated = FALSE;
8578         GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
8579
8580         MMPLAYER_FENTER();
8581         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8582         return_val_if_fail ( !MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP );
8583
8584         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
8585                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED )
8586                 goto PENDING;
8587
8588 #ifdef TEST_ES
8589         if( !MMPLAYER_IS_ES_BUFF_SRC(player) )
8590 #endif
8591         {
8592                 /* check duration */
8593                 /* NOTE : duration cannot be zero except live streaming.
8594                  *              Since some element could have some timing problemn with quering duration, try again.
8595                  */
8596                 if ( !player->duration )
8597                 {
8598                         if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
8599                         {
8600                                 goto SEEK_ERROR;
8601                         }
8602                         player->duration = dur_nsec;
8603                 }
8604
8605                 if ( player->duration )
8606                 {
8607                         dur_msec = GST_TIME_AS_MSECONDS(player->duration);
8608                 }
8609                 else
8610                 {
8611                         debug_error("could not get the duration. fail to seek.\n");
8612                         goto SEEK_ERROR;
8613                 }
8614         }
8615         debug_log("playback rate: %f\n", player->playback_rate);
8616
8617         mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
8618         if (accurated)
8619         {
8620                 seek_flags |= GST_SEEK_FLAG_ACCURATE;
8621         }
8622         else
8623         {
8624                 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
8625         }
8626
8627         /* do seek */
8628         switch ( format )
8629         {
8630                 case MM_PLAYER_POS_FORMAT_TIME:
8631                 {
8632 #ifdef TEST_ES
8633                         if( !MMPLAYER_IS_ES_BUFF_SRC(player) )
8634 #endif
8635                         {
8636                                 /* check position is valid or not */
8637                                 if ( position > dur_msec )
8638                                         goto INVALID_ARGS;
8639
8640                                 debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec);
8641
8642                                 if ( player->doing_seek )
8643                                 {
8644                                         debug_log("not completed seek");
8645                                         return MM_ERROR_PLAYER_DOING_SEEK;
8646                                 }
8647                         }
8648
8649                         if ( !internal_called )
8650                                 player->doing_seek = TRUE;
8651
8652                         pos_nsec = position * G_GINT64_CONSTANT(1000000);
8653
8654                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked))
8655                         {
8656                                 gint64 cur_time = 0;
8657
8658                                 /* get current position */
8659                                 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
8660
8661                                 /* flush */
8662                                 GstEvent *event = gst_event_new_seek (1.0,
8663                                                                 GST_FORMAT_TIME,
8664                                                                 (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
8665                                                                 GST_SEEK_TYPE_SET, cur_time,
8666                                                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
8667                                 if(event) {
8668                                         __gst_send_event_to_sink(player, event);
8669                                 }
8670
8671                                 __gst_pause( player, FALSE );
8672                         }
8673
8674                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8675                                                         GST_FORMAT_TIME, seek_flags,
8676                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
8677                         if ( !ret  )
8678                         {
8679                                 debug_error("failed to set position. dur[%lu]  pos[%lu]  pos_msec[%llu]\n", dur_msec, position, pos_nsec);
8680                                 goto SEEK_ERROR;
8681                         }
8682                 }
8683                 break;
8684
8685                 case MM_PLAYER_POS_FORMAT_PERCENT:
8686                 {
8687                         debug_log("seeking to (%lu)%% \n", position);
8688
8689                         if (player->doing_seek)
8690                         {
8691                                 debug_log("not completed seek");
8692                                 return MM_ERROR_PLAYER_DOING_SEEK;
8693                         }
8694
8695                         if ( !internal_called)
8696                                 player->doing_seek = TRUE;
8697
8698                         /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
8699                         pos_nsec = (gint64) ( ( position * player->duration ) / 100 );
8700                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8701                                                         GST_FORMAT_TIME, seek_flags,
8702                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
8703                         if ( !ret  )
8704                         {
8705                                 debug_error("failed to set position. dur[%lud]  pos[%lud]  pos_msec[%llud]\n", dur_msec, position, pos_nsec);
8706                                 goto SEEK_ERROR;
8707                         }
8708                 }
8709                 break;
8710
8711                 default:
8712                         goto INVALID_ARGS;
8713
8714         }
8715
8716         /* NOTE : store last seeking point to overcome some bad operation
8717           *      ( returning zero when getting current position ) of some elements
8718           */
8719         player->last_position = pos_nsec;
8720
8721         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
8722         if ( player->playback_rate > 1.0 )
8723                 _mmplayer_set_playspeed ( (MMHandleType)player, player->playback_rate );
8724
8725         MMPLAYER_FLEAVE();
8726         return MM_ERROR_NONE;
8727
8728 PENDING:
8729         player->pending_seek.is_pending = TRUE;
8730         player->pending_seek.format = format;
8731         player->pending_seek.pos = position;
8732
8733         debug_warning("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n",
8734                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
8735
8736         return MM_ERROR_NONE;
8737
8738 INVALID_ARGS:
8739         debug_error("invalid arguments, position : %ld  dur : %ld format : %d \n", position, dur_msec, format);
8740         return MM_ERROR_INVALID_ARGUMENT;
8741
8742 SEEK_ERROR:
8743         player->doing_seek = FALSE;
8744         return MM_ERROR_PLAYER_SEEK;
8745 }
8746
8747 #define TRICKPLAY_OFFSET GST_MSECOND
8748
8749 static int
8750 __gst_get_position(mm_player_t* player, int format, unsigned long* position) // @
8751 {
8752         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
8753         signed long long pos_msec = 0;
8754         gboolean ret = TRUE;
8755
8756         return_val_if_fail( player && position && player->pipeline && player->pipeline->mainbin,
8757                 MM_ERROR_PLAYER_NOT_INITIALIZED );
8758
8759         current_state = MMPLAYER_CURRENT_STATE(player);
8760
8761         /* NOTE : query position except paused state to overcome some bad operation
8762          * please refer to below comments in details
8763          */
8764         if ( current_state != MM_PLAYER_STATE_PAUSED )
8765         {
8766                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
8767         }
8768
8769         /* NOTE : get last point to overcome some bad operation of some elements
8770          * ( returning zero when getting current position in paused state
8771          * and when failed to get postion during seeking
8772          */
8773         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
8774                 || ( ! ret ))
8775                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
8776         {
8777                 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
8778
8779                 if(player->playback_rate < 0.0)
8780                         pos_msec = player->last_position - TRICKPLAY_OFFSET;
8781                 else
8782                         pos_msec = player->last_position;
8783
8784                 if (!ret)
8785                         pos_msec = player->last_position;
8786                 else
8787                         player->last_position = pos_msec;
8788
8789                 debug_log("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
8790
8791         }
8792         else
8793         {
8794                 if (player->duration > 0 && pos_msec > player->duration) {
8795                         pos_msec = player->duration;
8796                 }
8797
8798                 if (player->sm.keep_last_pos) {
8799                         debug_log("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position));
8800                         pos_msec = player->last_position;
8801                 }
8802                 else {
8803                         player->last_position = pos_msec;
8804                 }
8805         }
8806
8807         switch (format) {
8808                 case MM_PLAYER_POS_FORMAT_TIME:
8809                         *position = GST_TIME_AS_MSECONDS(pos_msec);
8810                         break;
8811
8812                 case MM_PLAYER_POS_FORMAT_PERCENT:
8813                 {
8814                         gint64 dur = 0;
8815                         gint64 pos = 0;
8816
8817                         dur = player->duration / GST_SECOND;
8818                         if (dur <= 0)
8819                         {
8820                                 debug_log ("duration is [%d], so returning position 0\n",dur);
8821                                 *position = 0;
8822                         }
8823                         else
8824                         {
8825                                 pos = pos_msec / GST_SECOND;
8826                                 *position = pos * 100 / dur;
8827                         }
8828                         break;
8829                 }
8830                 default:
8831                         return MM_ERROR_PLAYER_INTERNAL;
8832         }
8833
8834         return MM_ERROR_NONE;
8835 }
8836
8837
8838 static int      __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
8839 {
8840 #define STREAMING_IS_FINISHED   0
8841 #define BUFFERING_MAX_PER       100
8842
8843         GstQuery *query = NULL;
8844
8845         return_val_if_fail( player &&
8846                                                 player->pipeline &&
8847                                                 player->pipeline->mainbin,
8848                                                 MM_ERROR_PLAYER_NOT_INITIALIZED );
8849
8850         return_val_if_fail( start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT );
8851
8852         if (!MMPLAYER_IS_HTTP_STREAMING ( player ))
8853         {
8854                 /* and rtsp is not ready yet. */
8855                 debug_warning ( "it's only used for http streaming case.\n" );
8856                 return MM_ERROR_NONE;
8857         }
8858
8859         *start_pos = 0;
8860         *stop_pos = 0;
8861
8862         switch ( format )
8863         {
8864                 case MM_PLAYER_POS_FORMAT_PERCENT :
8865                 {
8866                         gint start_per = -1, stop_per = -1;
8867                         gint64 buffered_total = 0;
8868
8869                         unsigned long position = 0;
8870                         guint curr_size_bytes = 0;
8871                         gint64 buffering_left = -1;
8872                         gint buffered_sec = -1;
8873
8874                         gint64 content_duration = player->duration;
8875                         guint64 content_size = player->http_content_size;
8876
8877                         if (content_duration > 0)
8878                         {
8879                                 if (!__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position))
8880                                 {
8881                                         debug_log ("[Time] pos %d ms / dur %d sec / %lld bytes", position, (guint)(content_duration/GST_SECOND), content_size);
8882                                         start_per = 100 * (position*GST_MSECOND) / content_duration;
8883
8884                                         /* buffered size info from multiqueue */
8885                                         if (player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst)
8886                                         {
8887                                                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst), "curr-size-bytes", &curr_size_bytes, NULL);
8888                                                 debug_log ("[MQ] curr_size_bytes = %d", curr_size_bytes);
8889
8890                                                 buffered_total += curr_size_bytes;
8891                                         }
8892
8893                                         /* buffered size info from queue2 */
8894                                         if (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
8895                                         {
8896                                                 query = gst_query_new_buffering ( GST_FORMAT_BYTES );
8897                                                 if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query))
8898                                                 {
8899                                                         GstBufferingMode mode;
8900                                                         gint byte_in_rate = 0, byte_out_rate = 0;
8901                                                         gint64 start_byte = 0, stop_byte = 0;
8902                                                         guint num_of_ranges = 0;
8903                                                         guint idx = 0;
8904
8905                                                         num_of_ranges = gst_query_get_n_buffering_ranges(query);
8906                                                         for ( idx=0 ; idx<num_of_ranges ; idx++ )
8907                                                         {
8908                                                                 gst_query_parse_nth_buffering_range (query, idx, &start_byte, &stop_byte);
8909                                                                 debug_log ("[Q2][range %d] %lld ~ %lld\n", idx, start_byte, stop_byte);
8910
8911                                                                 buffered_total += (stop_byte - start_byte);
8912                                                         }
8913
8914                                                         gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, &buffering_left);
8915                                                         debug_log ("[Q2] in_rate %d, out_rate %d, left %lld\n", byte_in_rate, byte_out_rate, buffering_left);
8916                                                 }
8917                                                 gst_query_unref (query);
8918                                         }
8919
8920                                         if (buffering_left == STREAMING_IS_FINISHED)
8921                                         {
8922                                                 stop_per = BUFFERING_MAX_PER;
8923                                         }
8924                                         else
8925                                         {
8926                                                 guint dur_sec = (guint)(content_duration/GST_SECOND);
8927                                                 guint avg_byterate = (dur_sec>0)?((guint)(content_size/dur_sec)):(0);
8928
8929                                                 if (avg_byterate > 0)
8930                                                         buffered_sec = (gint)(buffered_total/avg_byterate);
8931                                                 else if (player->total_maximum_bitrate > 0)
8932                                                         buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_maximum_bitrate);
8933                                                 else if (player->total_bitrate > 0)
8934                                                         buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_bitrate);
8935
8936                                                 if ((buffered_sec >= 0) && (dur_sec > 0))
8937                                                         stop_per = start_per + (100 * buffered_sec / dur_sec);
8938                                         }
8939
8940                                         debug_log ("[Buffered Total] %lld bytes, %d sec, per %d~%d\n", buffered_total, buffered_sec, start_per, stop_per);
8941                                 }
8942                         }
8943
8944                         if (((buffered_total == 0) || (start_per < 0) || (stop_per < 0)) &&
8945                                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
8946                         {
8947                                 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
8948                                 if ( gst_element_query ( player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query ) )
8949                                 {
8950                                         GstFormat format;
8951                                         gint64 range_start_per = -1, range_stop_per = -1;
8952
8953                                         gst_query_parse_buffering_range ( query, &format, &range_start_per, &range_stop_per, NULL );
8954
8955                                         debug_log ("[Q2] range start %" G_GINT64_FORMAT " ~ stop %" G_GINT64_FORMAT "\n",  range_start_per , range_stop_per);
8956
8957                                         if (range_start_per != -1)
8958                                                 start_per = (gint)(100 * range_start_per / GST_FORMAT_PERCENT_MAX);
8959
8960                                         if (range_stop_per != -1)
8961                                                 stop_per = (gint)(100 * range_stop_per / GST_FORMAT_PERCENT_MAX);
8962                                 }
8963                                 gst_query_unref (query);
8964                         }
8965
8966                         if ( start_per > 0)
8967                                 *start_pos = (start_per < 100)?(start_per):(100);
8968                         else
8969                                 *start_pos = 0;
8970
8971                         if ( stop_per > 0)
8972                                 *stop_pos = (stop_per < 100)?(stop_per):(100);
8973                         else
8974                                 *stop_pos = 0;
8975
8976                         break;
8977                 }
8978                 case MM_PLAYER_POS_FORMAT_TIME :
8979                         debug_warning ( "Time format is not supported yet.\n" );
8980                         break;
8981
8982                 default :
8983                         break;
8984         }
8985
8986         debug_log("current buffer position : %lu~%lu \n", *start_pos, *stop_pos );
8987
8988         return MM_ERROR_NONE;
8989 }
8990
8991 static int
8992 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param) // @
8993 {
8994         MMPLAYER_FENTER();
8995
8996         if ( !player )
8997         {
8998                 debug_warning("set_message_callback is called with invalid player handle\n");
8999                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
9000         }
9001
9002         player->msg_cb = callback;
9003         player->msg_cb_param = user_param;
9004
9005         debug_log("msg_cb : 0x%x     msg_cb_param : 0x%x\n", (guint)callback, (guint)user_param);
9006
9007         MMPLAYER_FLEAVE();
9008
9009         return MM_ERROR_NONE;
9010 }
9011
9012 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
9013 {
9014         int ret = MM_ERROR_PLAYER_INVALID_URI;
9015         char *path = NULL;
9016
9017         MMPLAYER_FENTER();
9018
9019         return_val_if_fail ( uri , FALSE);
9020         return_val_if_fail ( data , FALSE);
9021         return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
9022
9023         memset(data, 0, sizeof(MMPlayerParseProfile));
9024
9025         if ((path = strstr(uri, "file://")))
9026         {
9027                 int file_stat = MM_ERROR_NONE;
9028
9029                 file_stat = util_exist_file_path(path + 7);
9030
9031                 if (file_stat == MM_ERROR_NONE)
9032                 {
9033                         strncpy(data->uri, path, MM_MAX_URL_LEN-1);
9034
9035                         if ( util_is_sdp_file ( path ) )
9036                         {
9037                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
9038                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9039                         }
9040                         else
9041                         {
9042                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
9043                         }
9044                         ret = MM_ERROR_NONE;
9045                 }
9046                 #if 0
9047                 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
9048                 {
9049                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
9050                 }
9051                 #endif
9052                 else
9053                 {
9054                         debug_warning("could  access %s.\n", path);
9055                 }
9056         }
9057 #ifdef TEST_ES
9058         else if ((path = strstr(uri, "es_buff://")))
9059         {
9060                 if (strlen(path))
9061                 {
9062                         strcpy(data->uri, uri);
9063                         data->uri_type = MM_PLAYER_URI_TYPE_ES_BUFF;
9064                         ret = MM_ERROR_NONE;
9065                 }
9066         }
9067 #endif
9068         else if ((path = strstr(uri, "buff://")))
9069         {
9070                         data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
9071                         ret = MM_ERROR_NONE;
9072         }
9073         else if ((path = strstr(uri, "rtsp://")))
9074         {
9075                 if (strlen(path)) {
9076                         if((path = strstr(uri, "/wfd1.0/"))) {
9077                                 strcpy(data->uri, uri);
9078                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_WFD;
9079                                 ret = MM_ERROR_NONE;
9080                                 debug_log("uri is actually a wfd client path. giving it to wfdrtspsrc\n");
9081                         }
9082                         else {
9083                                 strcpy(data->uri, uri);
9084                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9085                                 ret = MM_ERROR_NONE;
9086                         }
9087                 }
9088         }
9089         else if ((path = strstr(uri, "http://")))
9090         {
9091                 if (strlen(path)) {
9092                         strcpy(data->uri, uri);
9093 #ifdef MM_SMOOTH_STREAMING
9094                         if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
9095                                 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
9096                         {
9097                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
9098                         }
9099                         else
9100 #endif
9101                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
9102
9103                         ret = MM_ERROR_NONE;
9104                 }
9105         }
9106         else if ((path = strstr(uri, "https://")))
9107         {
9108                 if (strlen(path)) {
9109                         strcpy(data->uri, uri);
9110 #ifdef MM_SMOOTH_STREAMING
9111                 if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
9112                                 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
9113                         {
9114                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
9115                         }
9116 #endif
9117                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
9118
9119                         ret = MM_ERROR_NONE;
9120                 }
9121         }
9122         else if ((path = strstr(uri, "rtspu://")))
9123         {
9124                 if (strlen(path)) {
9125                         strcpy(data->uri, uri);
9126                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9127                         ret = MM_ERROR_NONE;
9128                 }
9129         }
9130         else if ((path = strstr(uri, "rtspr://")))
9131         {
9132                 strcpy(data->uri, path);
9133                 char *separater =strstr(path, "*");
9134
9135                 if (separater) {
9136                         int urgent_len = 0;
9137                         char *urgent = separater + strlen("*");
9138
9139                         if ((urgent_len = strlen(urgent))) {
9140                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
9141                                 strcpy(data->urgent, urgent);
9142                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9143                                 ret = MM_ERROR_NONE;
9144                         }
9145                 }
9146         }
9147         else if ((path = strstr(uri, "mms://")))
9148         {
9149                 if (strlen(path)) {
9150                         strcpy(data->uri, uri);
9151                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
9152                         ret = MM_ERROR_NONE;
9153                 }
9154         }
9155         else if ((path = strstr(uri, "mem://")))
9156         {
9157                 if (strlen(path)) {
9158                         int mem_size = 0;
9159                         char *buffer = NULL;
9160                         char *seperator = strchr(path, ',');
9161                         char ext[100] = {0,}, size[100] = {0,};
9162
9163                         if (seperator) {
9164                                 if ((buffer = strstr(path, "ext="))) {
9165                                         buffer += strlen("ext=");
9166
9167                                         if (strlen(buffer)) {
9168                                                 strcpy(ext, buffer);
9169
9170                                                 if ((seperator = strchr(ext, ','))
9171                                                         || (seperator = strchr(ext, ' '))
9172                                                         || (seperator = strchr(ext, '\0'))) {
9173                                                         seperator[0] = '\0';
9174                                                 }
9175                                         }
9176                                 }
9177
9178                                 if ((buffer = strstr(path, "size="))) {
9179                                         buffer += strlen("size=");
9180
9181                                         if (strlen(buffer) > 0) {
9182                                                 strcpy(size, buffer);
9183
9184                                                 if ((seperator = strchr(size, ','))
9185                                                         || (seperator = strchr(size, ' '))
9186                                                         || (seperator = strchr(size, '\0'))) {
9187                                                         seperator[0] = '\0';
9188                                                 }
9189
9190                                                 mem_size = atoi(size);
9191                                         }
9192                                 }
9193                         }
9194
9195                         debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
9196                         if ( mem_size && param)
9197                         {
9198                                 data->mem = param;
9199                                 data->mem_size = mem_size;
9200                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
9201                                 ret = MM_ERROR_NONE;
9202                         }
9203                 }
9204         }
9205         else
9206         {
9207                 int file_stat = MM_ERROR_NONE;
9208
9209                 file_stat = util_exist_file_path(uri);
9210
9211                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
9212                 if (file_stat == MM_ERROR_NONE)
9213                 {
9214                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", uri);
9215
9216                         if ( util_is_sdp_file( (char*)uri ) )
9217                         {
9218                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
9219                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9220                         }
9221                         else
9222                         {
9223                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
9224                         }
9225                         ret = MM_ERROR_NONE;
9226                 }
9227                 #if 0
9228                 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
9229                 {
9230                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
9231                 }
9232                 #endif
9233                 else
9234                 {
9235                         debug_error ("invalid uri, could not play..\n");
9236                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
9237                 }
9238         }
9239
9240         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
9241                 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
9242         } else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION){
9243 //              ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
9244         }
9245
9246         /* dump parse result */
9247         secure_debug_warning("incomming uri : %s\n", uri);
9248         debug_log("uri_type : %d, play_mode : %d, mem : 0x%x, mem_size : %d, urgent : %s\n",
9249                 data->uri_type, data->play_mode, (guint)data->mem, data->mem_size, data->urgent);
9250
9251         MMPLAYER_FLEAVE();
9252
9253         return ret;
9254 }
9255
9256 gboolean _asm_postmsg(gpointer *data)
9257 {
9258         mm_player_t* player = (mm_player_t*)data;
9259         MMMessageParamType msg = {0, };
9260
9261         MMPLAYER_FENTER();
9262         return_val_if_fail ( player, FALSE );
9263         debug_warning("get notified");
9264
9265         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
9266                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
9267         {
9268                 debug_warning("dispatched");
9269                 return FALSE;
9270         }
9271
9272
9273         msg.union_type = MM_MSG_UNION_CODE;
9274         msg.code = player->sm.event_src;
9275
9276 #if 0 // should remove
9277         if (player->sm.event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
9278         {
9279                 /* fill the message with state of player */
9280                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
9281                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
9282                 player->resumable_cancel_id = 0;
9283         }
9284         else
9285 #endif
9286         {
9287                 MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
9288                 player->resume_event_id = 0;
9289         }
9290
9291         debug_warning("dispatched");
9292         return FALSE;
9293 }
9294
9295 gboolean _asm_lazy_pause(gpointer *data)
9296 {
9297         mm_player_t* player = (mm_player_t*)data;
9298         int ret = MM_ERROR_NONE;
9299
9300         MMPLAYER_FENTER();
9301
9302         return_val_if_fail ( player, FALSE );
9303
9304         if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
9305         {
9306                 debug_log ("Ready to proceed lazy pause\n");
9307                 ret = _mmplayer_pause((MMHandleType)player);
9308                 if(MM_ERROR_NONE != ret)
9309                 {
9310                         debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
9311                 }
9312         }
9313         else
9314         {
9315                 debug_log ("Invalid state to proceed lazy pause\n");
9316         }
9317
9318         /* unset mute */
9319         if (player->pipeline && player->pipeline->audiobin)
9320                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
9321
9322         player->sm.by_asm_cb = FALSE; //should be reset here
9323
9324         MMPLAYER_FLEAVE();
9325
9326         return FALSE;
9327 }
9328
9329 static gboolean
9330 __mmplayer_can_do_interrupt(mm_player_t *player)
9331 {
9332         if (!player || !player->pipeline || !player->attrs)
9333         {
9334                 debug_warning("not initialized");
9335                 goto FAILED;
9336         }
9337
9338         if ((player->sm.exit_cb) || (player->set_mode.pcm_extraction))
9339         {
9340                 debug_warning("leave from asm cb right now, %d, %d", player->sm.exit_cb, player->set_mode.pcm_extraction);
9341                 goto FAILED;
9342         }
9343
9344         /* check if seeking */
9345         if (player->doing_seek)
9346         {
9347                 MMMessageParamType msg_param;
9348                 memset (&msg_param, 0, sizeof(MMMessageParamType));
9349                 msg_param.code = MM_ERROR_PLAYER_SEEK;
9350                 player->doing_seek = FALSE;
9351                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9352                 goto FAILED;
9353         }
9354
9355         /* check other thread */
9356         if (!g_mutex_trylock(&player->cmd_lock))
9357         {
9358                 debug_warning("locked already, cmd state : %d", player->cmd);
9359
9360                 /* check application command */
9361                 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)
9362                 {
9363                         debug_warning("playing.. should wait cmd lock then, will be interrupted");
9364                         g_mutex_lock(&player->cmd_lock);
9365                         goto INTERRUPT;
9366                 }
9367                 debug_warning("nothing to do");
9368                 goto FAILED;
9369         }
9370         else
9371         {
9372                 debug_warning("can interrupt immediately");
9373                 goto INTERRUPT;
9374         }
9375
9376 FAILED:
9377         return FALSE;
9378
9379 INTERRUPT:
9380         return TRUE;
9381 }
9382
9383 ASM_cb_result_t
9384 __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
9385 {
9386         mm_player_t* player = (mm_player_t*) cb_data;
9387         ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
9388         int result = MM_ERROR_NONE;
9389         gboolean lazy_pause = FALSE;
9390
9391         debug_warning("get notified");
9392
9393         if (!__mmplayer_can_do_interrupt(player))
9394         {
9395                 debug_warning("no need to interrupt, so leave");
9396                 goto EXIT;
9397         }
9398
9399         player->sm.cb_pending = TRUE;
9400         debug_warning("asm event src type : %d, command : 0x%x", event_src, command);
9401
9402         player->sm.by_asm_cb = TRUE;
9403         player->sm.event_src = event_src;
9404
9405         /* first, check event source */
9406         if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG)
9407         {
9408                 int stop_by_asm = 0;
9409                 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
9410                 if (!stop_by_asm)
9411                         goto DONE;
9412         }
9413         else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
9414         {
9415                 /* can use video overlay simultaneously */
9416                 /* video resource conflict */
9417                 if(player->pipeline->videobin)
9418                 {
9419                         debug_log("video conflict but, can support multiple video");
9420                         result = _mmplayer_pause((MMHandleType)player);
9421                         cb_res = ASM_CB_RES_PAUSE;
9422                 }
9423                 else if (player->pipeline->audiobin)
9424                 {
9425                         debug_log("audio resource conflict");
9426                         result = _mmplayer_pause((MMHandleType)player);
9427                         if (result != MM_ERROR_NONE)
9428                         {
9429                                 debug_warning("fail to set pause by asm");
9430                         }
9431                         cb_res = ASM_CB_RES_PAUSE;
9432                 }
9433                 goto DONE;
9434         }
9435 #if 0 // should remove
9436         else if (event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
9437         {
9438                 debug_warning("Got msg from asm for resumable canceled.\n");
9439                 player->sm.antishock = TRUE;
9440                 player->sm.by_asm_cb = FALSE;
9441
9442                 player->resumable_cancel_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
9443                 cb_res = ASM_CB_RES_IGNORE;
9444                 goto DONE;
9445         }
9446 #endif
9447         /* then, check command */
9448         switch(command)
9449         {
9450                 case ASM_COMMAND_PLAY:
9451                         debug_warning ("Got unexpected asm command (%d)", command);
9452                         break;
9453
9454                 case ASM_COMMAND_STOP: // notification case
9455                         {
9456                                 debug_warning("Got msg from asm to stop");
9457
9458                                 if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &player->last_position)) {
9459                                         debug_error("failed to get position");
9460                                         player->last_position = 0;
9461                                 }
9462
9463                                 debug_log ("pos_msec = %"GST_TIME_FORMAT"", GST_TIME_ARGS(player->last_position));
9464
9465                                 result = _mmplayer_stop((MMHandleType)player);
9466                                 if (result != MM_ERROR_NONE)
9467                                 {
9468                                         debug_warning("fail to set stop state by asm");
9469                                         cb_res = ASM_CB_RES_IGNORE;
9470                                 }
9471                                 else
9472                                 {
9473                                         cb_res = ASM_CB_RES_STOP;
9474                                 }
9475                                 player->sm.by_asm_cb = FALSE; // reset because no message any more from asm
9476                                 player->sm.keep_last_pos = TRUE;
9477                         }
9478                         break;
9479
9480                 case ASM_COMMAND_PAUSE:
9481                         {
9482                                 debug_warning("Got msg from asm to Pause");
9483                                 if(event_src == ASM_EVENT_SOURCE_CALL_START ||
9484                                         event_src == ASM_EVENT_SOURCE_ALARM_START ||
9485                                         event_src == ASM_EVENT_SOURCE_MEDIA)
9486                                 {
9487                                         if ( ! MMPLAYER_IS_RTSP_STREAMING(player) ) {
9488                                                 //hold 0.7 second to excute "fadedown mute" effect
9489                                                 debug_warning ("do fade down->pause->undo fade down");
9490
9491                                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
9492
9493                                                 result = _mmplayer_pause((MMHandleType)player);
9494                                                 if (result != MM_ERROR_NONE)
9495                                                 {
9496                                                         debug_warning("fail to set Pause state by asm");
9497                                                         cb_res = ASM_CB_RES_IGNORE;
9498                                                         break;
9499                                                 }
9500                                                 __mmplayer_undo_sound_fadedown(player);
9501                                         } else {
9502                                                 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
9503                                                 _mmplayer_unrealize((MMHandleType)player);
9504                                         }
9505                                 }
9506 #ifdef USE_LAZY_PAUSE // if enabled, should consider event id and context when removed
9507                                 else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
9508                                 {
9509                                         lazy_pause = TRUE; // return as soon as possible, for fast start of other app
9510
9511                                         if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
9512                                                 g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
9513
9514                                         player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
9515                                         debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
9516                                 }
9517 #endif
9518                                 else
9519                                 {
9520                                         debug_warning ("pause immediately");
9521                                         result = _mmplayer_pause((MMHandleType)player);
9522                                 }
9523                                 cb_res = ASM_CB_RES_PAUSE;
9524                         }
9525                         break;
9526
9527                 case ASM_COMMAND_RESUME:
9528                         {
9529                                 debug_warning("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
9530                                 player->sm.antishock = TRUE;
9531                                 player->sm.by_asm_cb = FALSE;
9532
9533                                 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
9534                                 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
9535                                 cb_res = ASM_CB_RES_IGNORE;
9536                                 goto DONE;
9537                         }
9538                         break;
9539
9540                 default:
9541                         break;
9542         }
9543
9544 DONE:
9545         if ( !lazy_pause )
9546         {
9547                 player->sm.by_asm_cb = FALSE;
9548         }
9549         player->sm.cb_pending = FALSE;
9550         MMPLAYER_CMD_UNLOCK( player );
9551
9552 EXIT:
9553         debug_warning("dispatched");
9554         return cb_res;
9555 }
9556
9557 int
9558 _mmplayer_create_player(MMHandleType handle) // @
9559 {
9560         mm_player_t* player = MM_PLAYER_CAST(handle);
9561
9562         MMPLAYER_FENTER();
9563
9564         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9565
9566         /* initialize player state */
9567         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
9568         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
9569         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
9570         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
9571
9572         /* check current state */
9573         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
9574
9575         /* construct attributes */
9576         player->attrs = _mmplayer_construct_attribute(handle);
9577
9578         if ( !player->attrs )
9579         {
9580                 debug_error("Failed to construct attributes\n");
9581                 goto ERROR;
9582         }
9583
9584         /* initialize gstreamer with configured parameter */
9585         if ( ! __mmplayer_init_gstreamer(player) )
9586         {
9587                 debug_error("Initializing gstreamer failed\n");
9588                 goto ERROR;
9589         }
9590
9591         /* initialize factories if not using decodebin */
9592         if( player->factories == NULL )
9593             __mmplayer_init_factories(player);
9594
9595         /* create lock. note that g_tread_init() has already called in gst_init() */
9596         g_mutex_init(&player->fsink_lock);
9597
9598         /* create repeat mutex */
9599         g_mutex_init(&player->repeat_thread_mutex);
9600
9601         /* create repeat cond */
9602         g_cond_init(&player->repeat_thread_cond);
9603
9604         /* create repeat thread */
9605         player->repeat_thread =
9606                 g_thread_try_new ("repeat_thread", __mmplayer_repeat_thread, (gpointer)player, NULL);
9607
9608
9609         /* create next play mutex */
9610         g_mutex_init(&player->next_play_thread_mutex);
9611
9612         /* create next play cond */
9613         g_cond_init(&player->next_play_thread_cond);
9614
9615         /* create next play thread */
9616         player->next_play_thread =
9617                 g_thread_try_new ("next_play_thread", __mmplayer_next_play_thread, (gpointer)player, NULL);
9618         if ( ! player->next_play_thread )
9619         {
9620                 debug_error("failed to create next play thread");
9621                 goto ERROR;
9622         }
9623
9624         if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
9625         {
9626                 debug_error("failed to initialize video capture\n");
9627                 goto ERROR;
9628         }
9629 #if 0
9630         /* register to asm */
9631         if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
9632         {
9633                 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
9634                 debug_error("failed to register asm server\n");
9635                 return MM_ERROR_POLICY_INTERNAL;
9636         }
9637
9638         /* to add active device callback */
9639         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))
9640         {
9641                 debug_error("failed mm_sound_add_device_information_changed_callback \n");
9642         }
9643 #endif
9644
9645         if (MMPLAYER_IS_HTTP_PD(player))
9646         {
9647                 player->pd_downloader = NULL;
9648                 player->pd_file_save_path = NULL;
9649         }
9650
9651         player->streaming_type = STREAMING_SERVICE_NONE;
9652
9653         /* give default value of audio effect setting */
9654         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
9655         player->playback_rate = DEFAULT_PLAYBACK_RATE;
9656
9657         player->play_subtitle = FALSE;
9658         player->use_textoverlay = FALSE;
9659         player->play_count = 0;
9660         player->use_decodebin = TRUE;
9661         player->ignore_asyncdone = FALSE;
9662         player->use_deinterleave = FALSE;
9663         player->pp_rebuilding = FALSE;
9664         player->max_audio_channels = 0;
9665         player->video_share_api_delta = 0;
9666         player->video_share_clock_delta = 0;
9667         player->has_closed_caption = FALSE;
9668
9669         __mmplayer_post_proc_reset(player);
9670
9671         if (player->ini.dump_element_keyword[0][0] == '\0')
9672         {
9673                 player->ini.set_dump_element_flag= FALSE;
9674         }
9675         else
9676         {
9677                 player->ini.set_dump_element_flag = TRUE;
9678         }
9679
9680         /* set player state to null */
9681         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
9682         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
9683
9684         return MM_ERROR_NONE;
9685
9686 ERROR:
9687         /* free lock */
9688         g_mutex_clear(&player->fsink_lock );
9689
9690         /* free thread */
9691         if ( player->repeat_thread )
9692         {
9693                 player->repeat_thread_exit = TRUE;
9694                 g_cond_signal( &player->repeat_thread_cond );
9695
9696                 g_thread_join( player->repeat_thread );
9697                 player->repeat_thread = NULL;
9698
9699                 g_mutex_clear(&player->repeat_thread_mutex );
9700
9701                 g_cond_clear (&player->repeat_thread_cond );
9702         }
9703         /* clear repeat thread mutex/cond if still alive
9704          * this can happen if only thread creating has failed
9705          */
9706         g_mutex_clear(&player->repeat_thread_mutex );
9707         g_cond_clear ( &player->repeat_thread_cond );
9708
9709         /* free next play thread */
9710         if ( player->next_play_thread )
9711         {
9712                 player->next_play_thread_exit = TRUE;
9713                 g_cond_signal( &player->next_play_thread_cond );
9714
9715                 g_thread_join( player->next_play_thread );
9716                 player->next_play_thread = NULL;
9717
9718                 g_mutex_clear(&player->next_play_thread_mutex );
9719
9720                 g_cond_clear ( &player->next_play_thread_cond );
9721         }
9722         /* clear next play thread mutex/cond if still alive
9723          * this can happen if only thread creating has failed
9724          */
9725         g_mutex_clear(&player->next_play_thread_mutex );
9726
9727         g_cond_clear ( &player->next_play_thread_cond );
9728
9729         /* release attributes */
9730         _mmplayer_deconstruct_attribute(handle);
9731
9732         MMPLAYER_FLEAVE();
9733
9734         return MM_ERROR_PLAYER_INTERNAL;
9735 }
9736
9737 static gboolean
9738 __mmplayer_init_gstreamer(mm_player_t* player) // @
9739 {
9740         static gboolean initialized = FALSE;
9741         static const int max_argc = 50;
9742         gint* argc = NULL;
9743         gchar** argv = NULL;
9744         gchar** argv2 = NULL;
9745         GError *err = NULL;
9746         int i = 0;
9747         int arg_count = 0;
9748
9749         if ( initialized )
9750         {
9751                 debug_log("gstreamer already initialized.\n");
9752                 return TRUE;
9753         }
9754
9755         /* alloc */
9756         argc = malloc( sizeof(int) );
9757         argv = malloc( sizeof(gchar*) * max_argc );
9758         argv2 = malloc( sizeof(gchar*) * max_argc );
9759
9760         if ( !argc || !argv )
9761                 goto ERROR;
9762
9763         memset( argv, 0, sizeof(gchar*) * max_argc );
9764         memset( argv2, 0, sizeof(gchar*) * max_argc );
9765
9766         /* add initial */
9767         *argc = 1;
9768         argv[0] = g_strdup( "mmplayer" );
9769
9770         /* add gst_param */
9771         for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
9772         {
9773                 if ( strlen( player->ini.gst_param[i] ) > 0 )
9774                 {
9775                         argv[*argc] = g_strdup( player->ini.gst_param[i] );
9776                         (*argc)++;
9777                 }
9778         }
9779
9780         /* we would not do fork for scanning plugins */
9781         argv[*argc] = g_strdup("--gst-disable-registry-fork");
9782         (*argc)++;
9783
9784         /* check disable registry scan */
9785         if ( player->ini.skip_rescan )
9786         {
9787                 argv[*argc] = g_strdup("--gst-disable-registry-update");
9788                 (*argc)++;
9789         }
9790
9791         /* check disable segtrap */
9792         if ( player->ini.disable_segtrap )
9793         {
9794                 argv[*argc] = g_strdup("--gst-disable-segtrap");
9795                 (*argc)++;
9796         }
9797
9798         debug_log("initializing gstreamer with following parameter\n");
9799         debug_log("argc : %d\n", *argc);
9800         arg_count = *argc;
9801
9802         for ( i = 0; i < arg_count; i++ )
9803         {
9804                 argv2[i] = argv[i];
9805                 debug_log("argv[%d] : %s\n", i, argv2[i]);
9806         }
9807
9808
9809         /* initializing gstreamer */
9810         if ( ! gst_init_check (argc, &argv, &err))
9811         {
9812                 debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
9813                 if (err)
9814                 {
9815                         g_error_free (err);
9816                 }
9817
9818                 goto ERROR;
9819         }
9820         /* release */
9821         for ( i = 0; i < arg_count; i++ )
9822         {
9823                 //debug_log("release - argv[%d] : %s\n", i, argv2[i]);
9824                 MMPLAYER_FREEIF( argv2[i] );
9825         }
9826
9827         MMPLAYER_FREEIF( argv );
9828         MMPLAYER_FREEIF( argv2 );
9829         MMPLAYER_FREEIF( argc );
9830
9831         /* done */
9832         initialized = TRUE;
9833
9834         return TRUE;
9835
9836 ERROR:
9837
9838         /* release */
9839         for ( i = 0; i < arg_count; i++ )
9840         {
9841                 debug_log("free[%d] : %s\n", i, argv2[i]);
9842                 MMPLAYER_FREEIF( argv2[i] );
9843         }
9844
9845         MMPLAYER_FREEIF( argv );
9846         MMPLAYER_FREEIF( argv2 );
9847         MMPLAYER_FREEIF( argc );
9848
9849         return FALSE;
9850 }
9851
9852 int
9853 __mmplayer_destroy_streaming_ext(mm_player_t* player)
9854 {
9855         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9856
9857         if (player->pd_downloader)
9858         {
9859                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
9860                 MMPLAYER_FREEIF(player->pd_downloader);
9861         }
9862
9863         if (MMPLAYER_IS_HTTP_PD(player))
9864         {
9865                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
9866                 MMPLAYER_FREEIF(player->pd_file_save_path);
9867         }
9868
9869         return MM_ERROR_NONE;
9870 }
9871
9872 int
9873 _mmplayer_destroy(MMHandleType handle) // @
9874 {
9875         mm_player_t* player = MM_PLAYER_CAST(handle);
9876
9877         MMPLAYER_FENTER();
9878
9879         /* check player handle */
9880         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9881
9882         /* destroy can called at anytime */
9883         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
9884
9885         __mmplayer_destroy_streaming_ext(player);
9886
9887         /* release repeat thread */
9888         if ( player->repeat_thread )
9889         {
9890                 player->repeat_thread_exit = TRUE;
9891                 g_cond_signal( &player->repeat_thread_cond );
9892
9893                 debug_log("waitting for repeat thread exit\n");
9894                 g_thread_join ( player->repeat_thread );
9895                 g_mutex_clear(&player->repeat_thread_mutex );
9896                 g_cond_clear (&player->repeat_thread_cond );
9897                 debug_log("repeat thread released\n");
9898         }
9899
9900         /* release next play thread */
9901         if ( player->next_play_thread )
9902         {
9903                 player->next_play_thread_exit = TRUE;
9904                 g_cond_signal( &player->next_play_thread_cond );
9905
9906                 debug_log("waitting for next play thread exit\n");
9907                 g_thread_join ( player->next_play_thread );
9908                 g_mutex_clear(&player->next_play_thread_mutex );
9909                 g_cond_clear(&player->next_play_thread_cond );
9910                 debug_log("next play thread released\n");
9911         }
9912
9913         _mmplayer_release_video_capture(player);
9914
9915         /* flush any pending asm_cb */
9916         if (player->sm.cb_pending)
9917         {
9918                 /* set a flag for make sure asm_cb to be returned immediately */
9919                 debug_warning("asm cb has pending state");
9920                 player->sm.exit_cb = TRUE;
9921
9922                 /* make sure to release any pending asm_cb which locked by cmd_lock */
9923                 MMPLAYER_CMD_UNLOCK(player);
9924                 sched_yield();
9925                 MMPLAYER_CMD_LOCK(player);
9926         }
9927 #if 0
9928         /* withdraw asm */
9929         if ( MM_ERROR_NONE != _mmplayer_asm_unregister(&player->sm) )
9930         {
9931                 debug_error("failed to deregister asm server\n");
9932         }
9933 #endif
9934 #ifdef USE_LAZY_PAUSE
9935         if (player->lazy_pause_event_id)
9936         {
9937                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->lazy_pause_event_id);
9938                 player->lazy_pause_event_id = 0;
9939         }
9940 #endif
9941
9942         if (player->resume_event_id)
9943         {
9944                 g_source_remove (player->resume_event_id);
9945                 player->resume_event_id = 0;
9946         }
9947
9948         if (player->resumable_cancel_id)
9949         {
9950                 g_source_remove (player->resumable_cancel_id);
9951                 player->resumable_cancel_id = 0;
9952         }
9953
9954         /* release pipeline */
9955         if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
9956         {
9957                 debug_error("failed to destory pipeline\n");
9958                 return MM_ERROR_PLAYER_INTERNAL;
9959         }
9960
9961         if (player->is_external_subtitle_present && player->subtitle_language_list)
9962         {
9963           g_list_free (player->subtitle_language_list);
9964           player->subtitle_language_list = NULL;
9965         }
9966
9967         __mmplayer_release_dump_list (player->dump_list);
9968
9969         /* release miscellaneous information.
9970            these info needs to be released after pipeline is destroyed. */
9971         __mmplayer_release_misc_post( player );
9972
9973         /* release attributes */
9974         _mmplayer_deconstruct_attribute( handle );
9975
9976         /* release factories */
9977         __mmplayer_release_factories( player );
9978
9979         /* release lock */
9980         g_mutex_clear(&player->fsink_lock );
9981
9982         g_mutex_clear(&player->msg_cb_lock );
9983
9984         MMPLAYER_FLEAVE();
9985
9986         return MM_ERROR_NONE;
9987 }
9988
9989 int
9990 __mmplayer_realize_streaming_ext(mm_player_t* player)
9991 {
9992         int ret = MM_ERROR_NONE;
9993
9994         MMPLAYER_FENTER();
9995         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9996
9997         if (MMPLAYER_IS_HTTP_PD(player))
9998         {
9999                 gboolean bret = FALSE;
10000
10001                 player->pd_downloader = _mmplayer_create_pd_downloader();
10002                 if ( !player->pd_downloader )
10003                 {
10004                         debug_error ("Unable to create PD Downloader...");
10005                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
10006                 }
10007
10008                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
10009
10010                 if (FALSE == bret)
10011                 {
10012                         debug_error ("Unable to create PD Downloader...");
10013                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
10014                 }
10015         }
10016
10017         MMPLAYER_FLEAVE();
10018         return ret;
10019 }
10020
10021 int
10022 _mmplayer_realize(MMHandleType hplayer) // @
10023 {
10024         mm_player_t* player =  (mm_player_t*)hplayer;
10025         char *uri =NULL;
10026         void *param = NULL;
10027         int application_pid = -1;
10028         gboolean update_registry = FALSE;
10029         MMHandleType attrs = 0;
10030         int ret = MM_ERROR_NONE;
10031
10032         MMPLAYER_FENTER();
10033
10034         /* check player handle */
10035         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
10036
10037         /* check current state */
10038         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
10039
10040         attrs = MMPLAYER_GET_ATTRS(player);
10041         if ( !attrs )
10042         {
10043                 debug_error("fail to get attributes.\n");
10044                 return MM_ERROR_PLAYER_INTERNAL;
10045         }
10046
10047         mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
10048         player->sm.pid = application_pid;
10049
10050         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
10051         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
10052
10053         ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
10054
10055         if (ret != MM_ERROR_NONE)
10056         {
10057                 debug_error("failed to parse profile\n");
10058                 return ret;
10059         }
10060
10061         /* FIXIT : we can use thouse in player->profile directly */
10062         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
10063         {
10064                 player->mem_buf.buf = (char *)player->profile.mem;
10065                 player->mem_buf.len = player->profile.mem_size;
10066                 player->mem_buf.offset = 0;
10067         }
10068
10069 #ifdef TEST_ES  // es_player_push_mode is needed?
10070         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF)
10071         {
10072                 if (strstr(uri, "es_buff://push_mode"))
10073                 {
10074                         player->es_player_push_mode = TRUE;
10075                 }
10076                 else
10077                 {
10078                         player->es_player_push_mode = FALSE;
10079                 }
10080         }
10081 #endif
10082         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
10083         {
10084                 debug_warning("mms protocol is not supported format.\n");
10085                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
10086         }
10087
10088         if (MMPLAYER_IS_STREAMING(player))
10089                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
10090         else
10091                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
10092
10093         player->needed_v_parser = FALSE;
10094         player->smooth_streaming = FALSE;
10095         player->videodec_linked  = 0;
10096         player->videosink_linked = 0;
10097         player->audiodec_linked  = 0;
10098         player->audiosink_linked = 0;
10099         player->textsink_linked = 0;
10100         player->is_external_subtitle_present = FALSE;
10101         /* set the subtitle ON default */
10102         player->is_subtitle_off = FALSE;
10103
10104         /* registry should be updated for downloadable codec */
10105         mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
10106
10107         if ( update_registry )
10108         {
10109                 debug_log("updating registry...\n");
10110                 gst_update_registry();
10111
10112                 /* then we have to rebuild factories */
10113                 __mmplayer_release_factories( player );
10114                 __mmplayer_init_factories(player);
10115         }
10116
10117         /* realize pipeline */
10118         ret = __gst_realize( player );
10119         if ( ret != MM_ERROR_NONE )
10120         {
10121                 debug_error("fail to realize the player.\n");
10122         }
10123         else
10124         {
10125                 ret = __mmplayer_realize_streaming_ext(player);
10126         }
10127
10128         MMPLAYER_FLEAVE();
10129
10130         return ret;
10131 }
10132
10133 int
10134 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
10135 {
10136         MMPLAYER_FENTER();
10137         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10138
10139         /* destroy can called at anytime */
10140         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
10141         {
10142                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
10143                 MMPLAYER_FREEIF(player->pd_downloader);
10144         }
10145
10146         MMPLAYER_FLEAVE();
10147         return MM_ERROR_NONE;
10148 }
10149
10150 int
10151 _mmplayer_unrealize(MMHandleType hplayer)
10152 {
10153         mm_player_t* player = (mm_player_t*)hplayer;
10154         int ret = MM_ERROR_NONE;
10155
10156         MMPLAYER_FENTER();
10157
10158         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
10159
10160         /* check current state */
10161         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
10162
10163         __mmplayer_unrealize_streaming_ext(player);
10164
10165         /* unrealize pipeline */
10166         ret = __gst_unrealize( player );
10167
10168         /* set asm stop if success */
10169         if (MM_ERROR_NONE == ret)
10170         {
10171                 if (player->sm.state != ASM_STATE_STOP)
10172                 {
10173                         /* NOTE : Stop asm after pipeline unrealize. Keep this sequence. */
10174                         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP, FALSE);
10175                         if ( ret )
10176                         {
10177                                 debug_error("failed to set asm state to STOP");
10178                                 return ret;
10179                         }
10180                 }
10181         }
10182         else
10183         {
10184                 debug_error("failed and don't change asm state to stop");
10185         }
10186
10187         MMPLAYER_FLEAVE();
10188
10189         return ret;
10190 }
10191
10192 int
10193 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
10194 {
10195         mm_player_t* player = (mm_player_t*)hplayer;
10196
10197         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10198
10199         return __gst_set_message_callback(player, callback, user_param);
10200 }
10201
10202 int
10203 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
10204 {
10205         mm_player_t *player = (mm_player_t*)hplayer;
10206
10207         return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
10208
10209         *state = MMPLAYER_CURRENT_STATE(player);
10210
10211         return MM_ERROR_NONE;
10212 }
10213
10214
10215 int
10216 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
10217 {
10218         mm_player_t* player = (mm_player_t*) hplayer;
10219         GstElement* vol_element = NULL;
10220         int i = 0;
10221
10222         MMPLAYER_FENTER();
10223
10224         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10225
10226         debug_log("volume [L]=%f:[R]=%f\n",
10227                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
10228
10229         /* invalid factor range or not */
10230         for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
10231         {
10232                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
10233                         debug_error("Invalid factor! (valid factor:0~1.0)\n");
10234                         return MM_ERROR_INVALID_ARGUMENT;
10235                 }
10236         }
10237
10238         /* not support to set other value into each channel */
10239         if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
10240                 return MM_ERROR_INVALID_ARGUMENT;
10241
10242         /* Save volume to handle. Currently the first array element will be saved. */
10243         player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
10244
10245         /* check pipeline handle */
10246         if ( ! player->pipeline || ! player->pipeline->audiobin )
10247         {
10248                 debug_log("audiobin is not created yet\n");
10249                 debug_log("but, current stored volume will be set when it's created.\n");
10250
10251                 /* NOTE : stored volume will be used in create_audiobin
10252                  * returning MM_ERROR_NONE here makes application to able to
10253                  * set volume at anytime.
10254                  */
10255                 return MM_ERROR_NONE;
10256         }
10257
10258         /* setting volume to volume element */
10259         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
10260
10261         if ( vol_element )
10262         {
10263                 debug_log("volume is set [%f]\n", player->sound.volume);
10264                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
10265         }
10266
10267         MMPLAYER_FLEAVE();
10268
10269         return MM_ERROR_NONE;
10270 }
10271
10272
10273 int
10274 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
10275 {
10276         mm_player_t* player = (mm_player_t*) hplayer;
10277         int i = 0;
10278
10279         MMPLAYER_FENTER();
10280
10281         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10282         return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
10283
10284         /* returning stored volume */
10285         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
10286                 volume->level[i] = player->sound.volume;
10287
10288         MMPLAYER_FLEAVE();
10289
10290         return MM_ERROR_NONE;
10291 }
10292
10293
10294
10295 int
10296 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
10297 {
10298         mm_player_t* player = (mm_player_t*) hplayer;
10299         GstElement* vol_element = NULL;
10300
10301         MMPLAYER_FENTER();
10302
10303         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10304
10305         /* mute value shoud 0 or 1 */
10306         if ( mute != 0 && mute != 1 )
10307         {
10308                 debug_error("bad mute value\n");
10309
10310                 /* FIXIT : definitly, we need _BAD_PARAM error code */
10311                 return MM_ERROR_INVALID_ARGUMENT;
10312         }
10313
10314         player->sound.mute = mute;
10315
10316         /* just hold mute value if pipeline is not ready */
10317         if ( !player->pipeline || !player->pipeline->audiobin )
10318         {
10319                 debug_log("pipeline is not ready. holding mute value\n");
10320                 return MM_ERROR_NONE;
10321         }
10322
10323         vol_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
10324
10325         /* NOTE : volume will only created when the bt is enabled */
10326         if ( vol_element )
10327         {
10328                 debug_log("mute : %d\n", mute);
10329                 g_object_set(vol_element, "mute", mute, NULL);
10330         }
10331         else
10332         {
10333                 debug_log("volume elemnet is not created. using volume in audiosink\n");
10334         }
10335
10336         MMPLAYER_FLEAVE();
10337
10338         return MM_ERROR_NONE;
10339 }
10340
10341 int
10342 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
10343 {
10344         mm_player_t* player = (mm_player_t*) hplayer;
10345
10346         MMPLAYER_FENTER();
10347
10348         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10349         return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
10350
10351         /* just hold mute value if pipeline is not ready */
10352         if ( !player->pipeline || !player->pipeline->audiobin )
10353         {
10354                 debug_log("pipeline is not ready. returning stored value\n");
10355                 *pmute = player->sound.mute;
10356                 return MM_ERROR_NONE;
10357         }
10358
10359         *pmute = player->sound.mute;
10360
10361         MMPLAYER_FLEAVE();
10362
10363         return MM_ERROR_NONE;
10364 }
10365
10366 int
10367 _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
10368 {
10369         mm_player_t* player = (mm_player_t*) hplayer;
10370
10371         MMPLAYER_FENTER();
10372
10373         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10374
10375         player->video_stream_changed_cb = callback;
10376         player->video_stream_changed_cb_user_param = user_param;
10377         debug_log("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
10378
10379         MMPLAYER_FLEAVE();
10380
10381         return MM_ERROR_NONE;
10382 }
10383
10384 int
10385 _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
10386 {
10387         mm_player_t* player = (mm_player_t*) hplayer;
10388
10389         MMPLAYER_FENTER();
10390
10391         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10392
10393         player->audio_stream_changed_cb = callback;
10394         player->audio_stream_changed_cb_user_param = user_param;
10395         debug_log("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
10396
10397         MMPLAYER_FLEAVE();
10398
10399         return MM_ERROR_NONE;
10400 }
10401
10402 int
10403 _mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param) // @
10404 {
10405         mm_player_t* player = (mm_player_t*) hplayer;
10406
10407         MMPLAYER_FENTER();
10408
10409         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10410
10411         player->audio_stream_render_cb_ex = callback;
10412         player->audio_stream_cb_user_param = user_param;
10413         player->audio_stream_sink_sync = sync;
10414         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);
10415
10416         MMPLAYER_FLEAVE();
10417
10418         return MM_ERROR_NONE;
10419 }
10420
10421 int
10422 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
10423 {
10424         mm_player_t* player = (mm_player_t*) hplayer;
10425
10426         MMPLAYER_FENTER();
10427
10428         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10429
10430         player->video_stream_cb = callback;
10431         player->video_stream_cb_user_param = user_param;
10432         player->use_video_stream = TRUE;
10433         debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
10434
10435         MMPLAYER_FLEAVE();
10436
10437         return MM_ERROR_NONE;
10438 }
10439
10440 int
10441 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
10442 {
10443         mm_player_t* player = (mm_player_t*) hplayer;
10444
10445         MMPLAYER_FENTER();
10446
10447         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10448
10449         player->audio_stream_cb = callback;
10450         player->audio_stream_cb_user_param = user_param;
10451         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
10452
10453         MMPLAYER_FLEAVE();
10454
10455         return MM_ERROR_NONE;
10456 }
10457
10458 // set prepare size
10459 int
10460 _mmplayer_set_prepare_buffering_time(MMHandleType hplayer, int second)
10461 {
10462         mm_player_t* player = (mm_player_t*) hplayer;
10463
10464         MMPLAYER_FENTER();
10465
10466         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10467
10468         if (MMPLAYER_CURRENT_STATE(player) !=  MM_PLAYER_STATE_NULL)
10469                 return MM_ERROR_PLAYER_INVALID_STATE;
10470
10471         debug_log("pre buffer size : %d sec\n", second);
10472
10473         if ( second <= 0 )
10474         {
10475                 debug_error("bad size value\n");
10476                 return MM_ERROR_INVALID_ARGUMENT;
10477         }
10478
10479         if (player->streamer == NULL)
10480         {
10481                 player->streamer = __mm_player_streaming_create();
10482                 __mm_player_streaming_initialize(player->streamer);
10483         }
10484
10485         player->streamer->buffering_req.initial_second = second;
10486
10487         MMPLAYER_FLEAVE();
10488
10489         return MM_ERROR_NONE;
10490 }
10491
10492 // set runtime mode
10493 int
10494 _mmplayer_set_runtime_buffering_mode(MMHandleType hplayer, MMPlayerBufferingMode mode, int second)
10495 {
10496         mm_player_t* player = (mm_player_t*) hplayer;
10497
10498         MMPLAYER_FENTER();
10499
10500         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10501
10502         debug_log("mode %d\n", mode);
10503
10504         if ((mode < 0) || (mode > MM_PLAYER_BUFFERING_MODE_MAX) ||
10505                 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) && (second <= 0)))
10506                 return MM_ERROR_INVALID_ARGUMENT;
10507
10508         if (player->streamer == NULL)
10509         {
10510                 player->streamer = __mm_player_streaming_create();
10511                 __mm_player_streaming_initialize(player->streamer);
10512         }
10513
10514         player->streamer->buffering_req.mode = mode;
10515
10516         if ((second > 0) &&
10517                 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) ||
10518                  (mode == MM_PLAYER_BUFFERING_MODE_ADAPTIVE)))
10519                 player->streamer->buffering_req.runtime_second = second;
10520
10521         MMPLAYER_FLEAVE();
10522
10523         return MM_ERROR_NONE;
10524 }
10525
10526 int
10527 _mmplayer_set_videoframe_render_error_cb(MMHandleType hplayer, mm_player_video_frame_render_error_callback callback, void *user_param) // @
10528 {
10529         mm_player_t* player = (mm_player_t*) hplayer;
10530
10531         MMPLAYER_FENTER();
10532
10533         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10534         return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
10535
10536         player->video_frame_render_error_cb = callback;
10537         player->video_frame_render_error_cb_user_param = user_param;
10538
10539         debug_log("Video frame render error cb Handle value is %p : %p\n", player, player->video_frame_render_error_cb);
10540
10541         MMPLAYER_FLEAVE();
10542
10543         return MM_ERROR_NONE;
10544 }
10545
10546 int
10547 __mmplayer_start_streaming_ext(mm_player_t *player)
10548 {
10549         gint ret = MM_ERROR_NONE;
10550
10551         MMPLAYER_FENTER();
10552         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10553
10554         if (MMPLAYER_IS_HTTP_PD(player))
10555         {
10556                 if ( !player->pd_downloader )
10557                 {
10558                         ret = __mmplayer_realize_streaming_ext(player);
10559
10560                         if ( ret != MM_ERROR_NONE)
10561                         {
10562                                 debug_error ("failed to realize streaming ext\n");
10563                                 return ret;
10564                         }
10565                 }
10566
10567                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
10568                 {
10569                         ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
10570                         if ( !ret )
10571                         {
10572                                 debug_error ("ERROR while starting PD...\n");
10573                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
10574                         }
10575                         ret = MM_ERROR_NONE;
10576                 }
10577         }
10578
10579         MMPLAYER_FLEAVE();
10580         return ret;
10581 }
10582
10583 int
10584 _mmplayer_start(MMHandleType hplayer) // @
10585 {
10586         mm_player_t* player = (mm_player_t*) hplayer;
10587         gint ret = MM_ERROR_NONE;
10588
10589         MMPLAYER_FENTER();
10590
10591         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10592
10593         /* check current state */
10594         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
10595
10596         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
10597         if ( ret != MM_ERROR_NONE )
10598         {
10599                 debug_error("failed to set asm state to PLAYING\n");
10600                 return ret;
10601         }
10602
10603         /* NOTE : we should check and create pipeline again if not created as we destroy
10604          * whole pipeline when stopping in streamming playback
10605          */
10606         if ( ! player->pipeline )
10607         {
10608                 ret = __gst_realize( player );
10609                 if ( MM_ERROR_NONE != ret )
10610                 {
10611                         debug_error("failed to realize before starting. only in streamming\n");
10612                         /* unlock */
10613                         return ret;
10614                 }
10615         }
10616
10617         ret = __mmplayer_start_streaming_ext(player);
10618         if ( ret != MM_ERROR_NONE )
10619         {
10620                 debug_error("failed to start streaming ext \n");
10621         }
10622
10623         /* start pipeline */
10624         ret = __gst_start( player );
10625         if ( ret != MM_ERROR_NONE )
10626         {
10627                 debug_error("failed to start player.\n");
10628         }
10629
10630         MMPLAYER_FLEAVE();
10631
10632         return ret;
10633 }
10634
10635 /* NOTE: post "not supported codec message" to application
10636  * when one codec is not found during AUTOPLUGGING in MSL.
10637  * So, it's separated with error of __mmplayer_gst_callback().
10638  * And, if any codec is not found, don't send message here.
10639  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
10640  */
10641 int
10642 __mmplayer_handle_missed_plugin(mm_player_t* player)
10643 {
10644         MMMessageParamType msg_param;
10645         memset (&msg_param, 0, sizeof(MMMessageParamType));
10646         gboolean post_msg_direct = FALSE;
10647
10648         MMPLAYER_FENTER();
10649
10650         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10651
10652         debug_log("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
10653                         player->not_supported_codec, player->can_support_codec);
10654
10655         if( player->not_found_demuxer )
10656         {
10657                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
10658                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
10659
10660                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10661                 MMPLAYER_FREEIF(msg_param.data);
10662
10663                 return MM_ERROR_NONE;
10664         }
10665
10666         if (player->not_supported_codec)
10667         {
10668                 if ( player->can_support_codec ) // There is one codec to play
10669                 {
10670                         post_msg_direct = TRUE;
10671                 }
10672                 else
10673                 {
10674                         if ( player->pipeline->audiobin ) // Some content has only PCM data in container.
10675                                 post_msg_direct = TRUE;
10676                 }
10677
10678                 if ( post_msg_direct )
10679                 {
10680                         MMMessageParamType msg_param;
10681                         memset (&msg_param, 0, sizeof(MMMessageParamType));
10682
10683                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
10684                         {
10685                                 debug_warning("not found AUDIO codec, posting error code to application.\n");
10686
10687                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
10688                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
10689                         }
10690                         else if ( player->not_supported_codec ==  MISSING_PLUGIN_VIDEO )
10691                         {
10692                                 debug_warning("not found VIDEO codec, posting error code to application.\n");
10693
10694                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
10695                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
10696                         }
10697
10698                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10699
10700                         MMPLAYER_FREEIF(msg_param.data);
10701
10702                         return MM_ERROR_NONE;
10703                 }
10704                 else // no any supported codec case
10705                 {
10706                         debug_warning("not found any codec, posting error code to application.\n");
10707
10708                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
10709                         {
10710                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
10711                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
10712                         }
10713                         else
10714                         {
10715                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
10716                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
10717                         }
10718
10719                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10720
10721                         MMPLAYER_FREEIF(msg_param.data);
10722                 }
10723         }
10724
10725         MMPLAYER_FLEAVE();
10726
10727         return MM_ERROR_NONE;
10728 }
10729
10730 static void __mmplayer_check_pipeline(mm_player_t* player)
10731 {
10732         GstState element_state = GST_STATE_VOID_PENDING;
10733         GstState element_pending_state = GST_STATE_VOID_PENDING;
10734         gint timeout = 0;
10735         int ret = MM_ERROR_NONE;
10736
10737         if (player->pp_rebuilding)
10738         {
10739                 debug_warning("pipeline is under construction.\n");
10740
10741                 MMPLAYER_PLAYBACK_LOCK(player);
10742                 MMPLAYER_PLAYBACK_UNLOCK(player);
10743
10744                 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
10745
10746                 /* wait for state transition */
10747                 ret = gst_element_get_state( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND );
10748
10749                 if ( ret == GST_STATE_CHANGE_FAILURE )
10750                 {
10751                         debug_error("failed to change pipeline state within %d sec\n", timeout );
10752                 }
10753         }
10754 }
10755
10756 /* NOTE : it should be able to call 'stop' anytime*/
10757 int
10758 _mmplayer_stop(MMHandleType hplayer) // @
10759 {
10760         mm_player_t* player = (mm_player_t*)hplayer;
10761         int ret = MM_ERROR_NONE;
10762
10763         MMPLAYER_FENTER();
10764
10765         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10766
10767         /* check current state */
10768         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
10769
10770         /* check pipline building state */
10771         __mmplayer_check_pipeline(player);
10772
10773         /* NOTE : application should not wait for EOS after calling STOP */
10774         __mmplayer_cancel_eos_timer( player );
10775
10776         __mmplayer_unrealize_streaming_ext(player);
10777
10778         /* reset */
10779         player->doing_seek = FALSE;
10780
10781         /* stop pipeline */
10782         ret = __gst_stop( player );
10783
10784         if ( ret != MM_ERROR_NONE )
10785         {
10786                 debug_error("failed to stop player.\n");
10787         }
10788
10789         MMPLAYER_FLEAVE();
10790
10791         return ret;
10792 }
10793
10794 int
10795 _mmplayer_pause(MMHandleType hplayer) // @
10796 {
10797         mm_player_t* player = (mm_player_t*)hplayer;
10798         gint64 pos_msec = 0;
10799         gboolean async = FALSE;
10800         gint ret = MM_ERROR_NONE;
10801
10802         MMPLAYER_FENTER();
10803
10804         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10805
10806         /* check current state */
10807         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
10808
10809         /* check pipline building state */
10810         __mmplayer_check_pipeline(player);
10811
10812         switch (MMPLAYER_CURRENT_STATE(player))
10813         {
10814                 case MM_PLAYER_STATE_READY:
10815                 {
10816                         /* check prepare async or not.
10817                          * In the case of streaming playback, it's recommned to avoid blocking wait.
10818                          */
10819                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10820                         debug_log("prepare working mode : %s", (async ? "async" : "sync"));
10821                 }
10822                 break;
10823
10824                 case MM_PLAYER_STATE_PLAYING:
10825                 {
10826                         /* NOTE : store current point to overcome some bad operation
10827                         * ( returning zero when getting current position in paused state) of some
10828                         * elements
10829                         */
10830                         if ( !gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec))
10831                                 debug_warning("getting current position failed in paused\n");
10832
10833                         player->last_position = pos_msec;
10834                 }
10835                 break;
10836         }
10837
10838         /* pause pipeline */
10839         ret = __gst_pause( player, async );
10840
10841         if ( ret != MM_ERROR_NONE )
10842         {
10843                 debug_error("failed to pause player. ret : 0x%x\n", ret);
10844         }
10845
10846         MMPLAYER_FLEAVE();
10847
10848         return ret;
10849 }
10850
10851 int
10852 _mmplayer_resume(MMHandleType hplayer)
10853 {
10854         mm_player_t* player = (mm_player_t*)hplayer;
10855         int ret = MM_ERROR_NONE;
10856         gboolean async = FALSE;
10857
10858         MMPLAYER_FENTER();
10859
10860         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10861
10862         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
10863         if ( ret )
10864         {
10865                 debug_error("failed to set asm state to PLAYING\n");
10866                 return ret;
10867         }
10868
10869         /* check current state */
10870         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
10871
10872         /* resume pipeline */
10873 #if 0
10874 #ifdef TEST_ES
10875         if(MMPLAYER_IS_ES_BUFF_SRC(player))
10876                 //async = TRUE;
10877 #endif
10878 #endif
10879
10880         ret = __gst_resume( player, async );
10881
10882         if ( ret != MM_ERROR_NONE )
10883         {
10884                 debug_error("failed to resume player.\n");
10885         }
10886
10887         MMPLAYER_FLEAVE();
10888
10889         return ret;
10890 }
10891
10892 int
10893 __mmplayer_set_play_count(mm_player_t* player, gint count)
10894 {
10895         MMHandleType attrs = 0;
10896
10897         MMPLAYER_FENTER();
10898
10899         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10900
10901         attrs =  MMPLAYER_GET_ATTRS(player);
10902         if ( !attrs )
10903         {
10904                 debug_error("fail to get attributes.\n");
10905                 return MM_ERROR_PLAYER_INTERNAL;
10906         }
10907
10908         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
10909         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
10910                 debug_error("failed to commit\n");
10911
10912         MMPLAYER_FLEAVE();
10913
10914         return  MM_ERROR_NONE;
10915 }
10916
10917 int
10918 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
10919 {
10920         mm_player_t* player = (mm_player_t*)hplayer;
10921         gint64 start_pos = 0;
10922         gint64 end_pos = 0;
10923         gint infinity = -1;
10924
10925         MMPLAYER_FENTER();
10926
10927         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10928         return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
10929
10930         player->section_repeat = TRUE;
10931         player->section_repeat_start = start;
10932         player->section_repeat_end = end;
10933
10934         start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
10935         end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
10936
10937         __mmplayer_set_play_count( player, infinity );
10938
10939         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10940                                         player->playback_rate,
10941                                         GST_FORMAT_TIME,
10942                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10943                                         GST_SEEK_TYPE_SET, start_pos,
10944                                         GST_SEEK_TYPE_SET, end_pos)))
10945         {
10946                 debug_error("failed to activate section repeat\n");
10947
10948                 return MM_ERROR_PLAYER_SEEK;
10949         }
10950
10951         debug_log("succeeded to set section repeat from %d to %d\n",
10952                 player->section_repeat_start, player->section_repeat_end);
10953
10954         MMPLAYER_FLEAVE();
10955
10956         return  MM_ERROR_NONE;
10957 }
10958
10959 static int
10960 __mmplayer_set_pcm_extraction(mm_player_t* player)
10961 {
10962         gint64 start_nsec = 0;
10963         gint64 end_nsec = 0;
10964         gint64 dur_nsec = 0;
10965         gint64 dur_msec = 0;
10966         int required_start = 0;
10967         int required_end = 0;
10968         int ret = 0;
10969
10970         MMPLAYER_FENTER();
10971
10972         return_val_if_fail( player, FALSE );
10973
10974         mm_attrs_multiple_get(player->attrs,
10975                 NULL,
10976                 "pcm_extraction_start_msec", &required_start,
10977                 "pcm_extraction_end_msec", &required_end,
10978                 NULL);
10979
10980         debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
10981
10982         if (required_start == 0 && required_end == 0)
10983         {
10984                 debug_log("extracting entire stream");
10985                 return MM_ERROR_NONE;
10986         }
10987         else if (required_start < 0 || required_start > required_end || required_end < 0 )
10988         {
10989                 debug_log("invalid range for pcm extraction");
10990                 return MM_ERROR_INVALID_ARGUMENT;
10991         }
10992
10993         /* get duration */
10994         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
10995         if ( !ret )
10996         {
10997                 debug_error("failed to get duration");
10998                 return MM_ERROR_PLAYER_INTERNAL;
10999         }
11000         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
11001
11002         if (dur_msec < required_end) // FIXME
11003         {
11004                 debug_log("invalid end pos for pcm extraction");
11005                 return MM_ERROR_INVALID_ARGUMENT;
11006         }
11007
11008         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
11009         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
11010
11011         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
11012                                         1.0,
11013                                         GST_FORMAT_TIME,
11014                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
11015                                         GST_SEEK_TYPE_SET, start_nsec,
11016                                         GST_SEEK_TYPE_SET, end_nsec)))
11017         {
11018                 debug_error("failed to seek for pcm extraction\n");
11019
11020                 return MM_ERROR_PLAYER_SEEK;
11021         }
11022
11023         debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
11024
11025         MMPLAYER_FLEAVE();
11026
11027         return MM_ERROR_NONE;
11028 }
11029
11030 int
11031 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
11032 {
11033         mm_player_t* player = (mm_player_t*)hplayer;
11034         gint64 cur_pos = 0;
11035         gint onetime = 1;
11036
11037         MMPLAYER_FENTER();
11038
11039         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11040
11041         player->section_repeat = FALSE;
11042
11043         __mmplayer_set_play_count( player, onetime );
11044
11045         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_pos);
11046
11047         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
11048                                         1.0,
11049                                         GST_FORMAT_TIME,
11050                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
11051                                         GST_SEEK_TYPE_SET, cur_pos,
11052                                         GST_SEEK_TYPE_SET, player->duration )))
11053         {
11054                 debug_error("failed to deactivate section repeat\n");
11055
11056                 return MM_ERROR_PLAYER_SEEK;
11057         }
11058
11059         MMPLAYER_FENTER();
11060
11061         return MM_ERROR_NONE;
11062 }
11063
11064 int
11065 _mmplayer_set_playspeed(MMHandleType hplayer, float rate)
11066 {
11067         mm_player_t* player = (mm_player_t*)hplayer;
11068         signed long long pos_msec = 0;
11069         int ret = MM_ERROR_NONE;
11070         int mute = FALSE;
11071         signed long long start = 0, stop = 0;
11072         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
11073         MMPLAYER_FENTER();
11074
11075         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
11076         return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
11077
11078         /* The sound of video is not supported under 0.0 and over 2.0. */
11079         if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
11080         {
11081                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
11082                         mute = TRUE;
11083         }
11084         _mmplayer_set_mute(hplayer, mute);
11085
11086         if (player->playback_rate == rate)
11087                 return MM_ERROR_NONE;
11088
11089         /* If the position is reached at start potion during fast backward, EOS is posted.
11090          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
11091          * */
11092         player->playback_rate = rate;
11093
11094         current_state = MMPLAYER_CURRENT_STATE(player);
11095
11096         if ( current_state != MM_PLAYER_STATE_PAUSED )
11097                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
11098
11099         debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
11100
11101         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
11102                 || ( ! ret ))
11103                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
11104         {
11105                 debug_warning("returning last point : %lld\n", player->last_position );
11106                 pos_msec = player->last_position;
11107         }
11108
11109
11110         if(rate >= 0)
11111         {
11112                 start = pos_msec;
11113                 stop = GST_CLOCK_TIME_NONE;
11114         }
11115         else
11116         {
11117                 start = GST_CLOCK_TIME_NONE;
11118                 stop = pos_msec;
11119         }
11120         if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
11121                                 rate,
11122                                 GST_FORMAT_TIME,
11123                                 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
11124                                 GST_SEEK_TYPE_SET, start,
11125                                 GST_SEEK_TYPE_SET, stop)))
11126         {
11127                 debug_error("failed to set speed playback\n");
11128                 return MM_ERROR_PLAYER_SEEK;
11129         }
11130
11131         debug_log("succeeded to set speed playback as %0.1f\n", rate);
11132
11133         MMPLAYER_FLEAVE();
11134
11135         return MM_ERROR_NONE;;
11136 }
11137
11138 int
11139 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
11140 {
11141         mm_player_t* player = (mm_player_t*)hplayer;
11142         int ret = MM_ERROR_NONE;
11143
11144         MMPLAYER_FENTER();
11145
11146         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11147
11148         ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
11149
11150         MMPLAYER_FLEAVE();
11151
11152         return ret;
11153 }
11154
11155 int
11156 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
11157 {
11158         mm_player_t* player = (mm_player_t*)hplayer;
11159         int ret = MM_ERROR_NONE;
11160
11161         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11162
11163         ret = __gst_get_position ( player, format, position );
11164
11165         return ret;
11166 }
11167
11168 int
11169 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
11170 {
11171         mm_player_t* player = (mm_player_t*)hplayer;
11172         int ret = MM_ERROR_NONE;
11173
11174         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11175
11176         ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
11177
11178         return ret;
11179 }
11180
11181 int
11182 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
11183 {
11184         mm_player_t* player = (mm_player_t*)hplayer;
11185         int ret = MM_ERROR_NONE;
11186
11187         MMPLAYER_FENTER();
11188
11189         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11190
11191         ret = __gst_adjust_subtitle_position(player, format, position);
11192
11193         MMPLAYER_FLEAVE();
11194
11195         return ret;
11196 }
11197 int
11198 _mmplayer_adjust_video_postion(MMHandleType hplayer, int offset) // @
11199 {
11200         mm_player_t* player = (mm_player_t*)hplayer;
11201         int ret = MM_ERROR_NONE;
11202
11203         MMPLAYER_FENTER();
11204
11205         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11206
11207         ret = __gst_adjust_video_position(player, offset);
11208
11209         MMPLAYER_FLEAVE();
11210
11211         return ret;
11212 }
11213
11214 static gboolean
11215 __mmplayer_is_midi_type( gchar* str_caps)
11216 {
11217         if ( ( g_strrstr(str_caps, "audio/midi") ) ||
11218                 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
11219                 ( g_strrstr(str_caps, "application/x-smaf") ) ||
11220                 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
11221                 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
11222                 ( g_strrstr(str_caps, "audio/xmf") ) ||
11223                 ( g_strrstr(str_caps, "audio/mxmf") ) )
11224         {
11225                 debug_log("midi\n");
11226
11227                 return TRUE;
11228         }
11229
11230         return FALSE;
11231 }
11232
11233 static gboolean
11234 __mmplayer_is_only_mp3_type (gchar *str_caps)
11235 {
11236         if (g_strrstr(str_caps, "application/x-id3") ||
11237                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
11238         {
11239                 return TRUE;
11240         }
11241         return FALSE;
11242 }
11243
11244 /* try to use ALP decoder first instead of selected decoder */
11245 static gboolean
11246 __mmplayer_is_omx_decoder_type (mm_player_t* player)
11247 {
11248         #define MIN_THRESHOLD_SIZE  320 * 1024 // 320K
11249         gboolean ret = FALSE;
11250         gchar* path = NULL;
11251         guint64 data_size = 0;
11252         struct stat sb;
11253
11254         return_val_if_fail (player, FALSE);
11255
11256         /* consider mp3 audio only */
11257         if ((!MMPLAYER_IS_STREAMING(player)) &&
11258                 (__mmplayer_is_only_mp3_type(player->type)))
11259         {
11260                 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
11261
11262                 if (stat(path, &sb) == 0)
11263                 {
11264                         data_size = (guint64)sb.st_size;
11265
11266                         if (data_size > MIN_THRESHOLD_SIZE)
11267                         {
11268                                 ret = TRUE;
11269                         }
11270                 }
11271         }
11272
11273         debug_log ("need to select omx_decoder ? [%s]\n", (ret)?"YES":"NO");
11274         return ret;
11275 }
11276
11277 static void
11278 __mmplayer_set_audio_attrs (mm_player_t* player, GstCaps* caps)
11279 {
11280         GstStructure* caps_structure = NULL;
11281         gint samplerate = 0;
11282         gint channels = 0;
11283
11284         MMPLAYER_FENTER();
11285         return_if_fail (player && caps);
11286
11287         caps_structure = gst_caps_get_structure(caps, 0);
11288
11289         /* set stream information */
11290         gst_structure_get_int (caps_structure, "rate", &samplerate);
11291         mm_attrs_set_int_by_name (player->attrs, "content_audio_samplerate", samplerate);
11292
11293         gst_structure_get_int (caps_structure, "channels", &channels);
11294         mm_attrs_set_int_by_name (player->attrs, "content_audio_channels", channels);
11295
11296         debug_log ("audio samplerate : %d       channels : %d\n", samplerate, channels);
11297 }
11298
11299 static void
11300 __mmplayer_typefind_have_type(  GstElement *tf, guint probability,  // @
11301 GstCaps *caps, gpointer data)
11302 {
11303         mm_player_t* player = (mm_player_t*)data;
11304         GstPad* pad = NULL;
11305
11306         MMPLAYER_FENTER();
11307
11308         return_if_fail( player && tf && caps );
11309
11310         /* store type string */
11311         MMPLAYER_FREEIF(player->type);
11312         player->type = gst_caps_to_string(caps);
11313         if (player->type)
11314                 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
11315
11316         if ( (!MMPLAYER_IS_WFD_STREAMING( player )) &&
11317                  (!MMPLAYER_IS_RTSP_STREAMING( player )) &&
11318                  (g_strrstr(player->type, "audio/x-raw-int")))
11319         {
11320                 debug_error("not support media format\n");
11321
11322                 if (player->msg_posted == FALSE)
11323                 {
11324                         MMMessageParamType msg_param;
11325                         memset (&msg_param, 0, sizeof(MMMessageParamType));
11326
11327                         msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
11328                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
11329
11330                         /* don't post more if one was sent already */
11331                         player->msg_posted = TRUE;
11332                 }
11333                 return;
11334         }
11335
11336         /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
11337         if ( __mmplayer_is_midi_type(player->type))
11338         {
11339                 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
11340                 player->bypass_audio_effect = TRUE;
11341         }
11342         else if ( g_strrstr(player->type, "application/x-hls"))
11343         {
11344                 /* If it can't know exact type when it parses uri because of redirection case,
11345                   * it will be fixed by typefinder here.
11346                   */
11347                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
11348         }
11349         else if ( g_strrstr(player->type, "application/dash+xml"))
11350         {
11351                 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
11352         }
11353
11354         pad = gst_element_get_static_pad(tf, "src");
11355         if ( !pad )
11356         {
11357                 debug_error("fail to get typefind src pad.\n");
11358                 return;
11359         }
11360
11361         if (player->use_decodebin)
11362         {
11363                 if(!__mmplayer_try_to_plug_decodebin( player, pad, caps ))
11364                 {
11365                         gboolean async = FALSE;
11366                         debug_error("failed to autoplug %s\n", player->type);
11367
11368                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
11369
11370                         if ( async && player->msg_posted == FALSE )
11371                         {
11372                                 __mmplayer_handle_missed_plugin( player );
11373                         }
11374
11375                         goto DONE;
11376                 }
11377         }
11378         else
11379         {
11380                 /* try to plug */
11381                 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
11382                 {
11383                         gboolean async = FALSE;
11384                         debug_error("failed to autoplug %s\n", player->type);
11385
11386                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
11387
11388                         if ( async && player->msg_posted == FALSE )
11389                         {
11390                                 __mmplayer_handle_missed_plugin( player );
11391                         }
11392
11393                         goto DONE;
11394                 }
11395
11396                 /* finish autopluging if no dynamic pad waiting */
11397                 if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
11398                 {
11399                         if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
11400                         {
11401                                 __mmplayer_pipeline_complete( NULL, (gpointer)player );
11402                         }
11403                 }
11404         }
11405
11406 DONE:
11407         gst_object_unref( GST_OBJECT(pad) );
11408
11409         MMPLAYER_FLEAVE();
11410
11411         return;
11412 }
11413
11414 #ifdef _MM_PLAYER_ALP_PARSER
11415 void check_name (void *data, void *user_data)
11416 {
11417         mm_player_t* player = user_data;
11418
11419         if (g_strrstr((gchar*)data, "mpegaudioparse"))
11420         {
11421                 debug_log("mpegaudioparse - set alp-mp3dec\n");
11422                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "alp-mp3dec", TRUE, NULL);
11423         }
11424 }
11425 #endif
11426
11427 static GstElement *
11428 __mmplayer_create_decodebin (mm_player_t* player)
11429 {
11430         GstElement *decodebin = NULL;
11431
11432         MMPLAYER_FENTER();
11433
11434         /* create decodebin */
11435         decodebin = gst_element_factory_make("decodebin", NULL);
11436
11437         if (!decodebin)
11438         {
11439                 debug_error("fail to create decodebin\n");
11440                 goto ERROR;
11441         }
11442
11443         /* raw pad handling signal */
11444         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
11445                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
11446
11447         /* no-more-pad pad handling signal */
11448         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
11449                                                 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
11450
11451         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
11452                                                 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
11453
11454         /* This signal is emitted when a pad for which there is no further possible
11455            decoding is added to the decodebin.*/
11456         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
11457                                                 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player );
11458
11459         /* This signal is emitted whenever decodebin2 finds a new stream. It is emitted
11460            before looking for any elements that can handle that stream.*/
11461         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
11462                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
11463
11464         /* This signal is emitted whenever decodebin2 finds a new stream. It is emitted
11465            before looking for any elements that can handle that stream.*/
11466         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
11467                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
11468
11469         /* Once decodebin2 has found the possible GstElementFactory objects to try for
11470            caps on pad, this signal is emited. The purpose of the signal is for the
11471            application to perform additional sorting or filtering on the element factory
11472            array.*/
11473         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
11474                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_sort), player);
11475
11476         /* This signal is emitted once decodebin2 has finished decoding all the data.*/
11477         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
11478                                                 G_CALLBACK(__mmplayer_gst_decode_drained), player);
11479
11480         /* This signal is emitted when a element is added to the bin.*/
11481         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
11482                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
11483
11484 ERROR:
11485         return decodebin;
11486 }
11487
11488 static gboolean
11489 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
11490 {
11491         MMPlayerGstElement* mainbin = NULL;
11492         GstElement* decodebin2 = NULL;
11493         GstElement* queue2 = NULL;
11494         GstElement* id3demux = NULL;
11495         GstPad* sinkpad = NULL;
11496         GstPad* qsrcpad= NULL;
11497         gchar *caps_str = NULL;
11498         gint64 dur_bytes = 0L;
11499         gchar* file_buffering_path = NULL;
11500         gboolean use_file_buffer = FALSE;
11501
11502         guint max_buffer_size_bytes = 0;
11503         gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
11504
11505         MMPLAYER_FENTER();
11506         return_val_if_fail (player && player->pipeline && player->pipeline->mainbin, FALSE);
11507
11508         mainbin = player->pipeline->mainbin;
11509
11510         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
11511                 (MMPLAYER_IS_HTTP_STREAMING(player)))
11512         {
11513                 debug_log ("creating http streaming buffering queue (queue2)\n");
11514
11515                 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
11516                 {
11517                         debug_error ("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
11518                 }
11519                 else
11520             {
11521                         queue2 = gst_element_factory_make ("queue2", "queue2");
11522                         if (!queue2)
11523                         {
11524                                 debug_error ("failed to create buffering queue element\n");
11525                                 goto ERROR;
11526                         }
11527
11528                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2))
11529                         {
11530                                 debug_error("failed to add buffering queue\n");
11531                                 goto ERROR;
11532                         }
11533
11534                         sinkpad = gst_element_get_static_pad(queue2, "sink");
11535                         qsrcpad = gst_element_get_static_pad(queue2, "src");
11536
11537                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11538                         {
11539                                 debug_error("failed to link buffering queue\n");
11540                                 goto ERROR;
11541                         }
11542
11543                         // if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
11544                         {
11545                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
11546                                         debug_error("fail to get duration.\n");
11547
11548                                 debug_log("dur_bytes = %lld\n", dur_bytes);
11549
11550                                 if (dur_bytes > 0)
11551                                 {
11552                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
11553                                         file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
11554                                 }
11555                                 else
11556                                 {
11557                                         dur_bytes = 0;
11558                                 }
11559                         }
11560
11561                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
11562                         // if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
11563                         if(!g_strrstr(player->type, "video/mpegts"))
11564                         {
11565                                 max_buffer_size_bytes = (use_file_buffer)?(player->ini.http_max_size_bytes):(5*1024*1024);
11566                                 debug_log("max_buffer_size_bytes = %d\n", max_buffer_size_bytes);
11567
11568                                 __mm_player_streaming_set_queue2(player->streamer,
11569                                                                                                 queue2,
11570                                                                                                 FALSE,
11571                                                                                                 max_buffer_size_bytes,
11572                                                                                                 player->ini.http_buffering_time,
11573                                                                                                 1.0,                                                            // no meaning
11574                                                                                                 player->ini.http_buffering_limit,       // no meaning
11575                                                                                                 use_file_buffer,
11576                                                                                                 file_buffering_path,
11577                                                                                                 (guint64)dur_bytes);
11578                         }
11579
11580                         MMPLAYER_FREEIF(file_buffering_path);
11581                         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (queue2))
11582                         {
11583                                 debug_error("failed to sync queue2 state with parent\n");
11584                                 goto ERROR;
11585                         }
11586
11587                         srcpad = qsrcpad;
11588
11589                         gst_object_unref(GST_OBJECT(sinkpad));
11590
11591                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
11592                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
11593                 }
11594         }
11595
11596         /* create decodebin */
11597         decodebin2 = __mmplayer_create_decodebin(player);
11598
11599         if (!decodebin2)
11600         {
11601                 debug_error("can not create autoplug element\n");
11602                 goto ERROR;
11603         }
11604
11605         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin2))
11606         {
11607                 debug_error("failed to add decodebin2\n");
11608                 goto ERROR;
11609         }
11610
11611         /* to force caps on the decodebin element and avoid reparsing stuff by
11612         * typefind. It also avoids a deadlock in the way typefind activates pads in
11613         * the state change */
11614         g_object_set (decodebin2, "sink-caps", caps, NULL);
11615
11616         sinkpad = gst_element_get_static_pad(decodebin2, "sink");
11617
11618         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11619         {
11620                 debug_error("failed to link decodebin2\n");
11621                 goto ERROR;
11622         }
11623
11624         gst_object_unref(GST_OBJECT(sinkpad));
11625
11626         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
11627         mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin2;
11628
11629         if ( ((!MMPLAYER_IS_HTTP_PD(player)) &&
11630             (MMPLAYER_IS_HTTP_STREAMING(player))) || MMPLAYER_IS_DASH_STREAMING (player))
11631         {
11632                 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
11633
11634                 g_object_set (G_OBJECT(decodebin2), "use-buffering", TRUE,
11635                                                                                         "high-percent", (gint)player->ini.http_buffering_limit,
11636                                                                                         "low-percent", 1,   // 1%
11637                                                                                         "max-size-bytes", MAX_DECODEBIN_BUFFER_BYTES,
11638                                                                                         "max-size-time", (guint64)(MAX_DECODEBIN_BUFFER_TIME * GST_SECOND),
11639                                                                                         "max-size-buffers", 0, NULL);  // disable or automatic
11640         }
11641
11642         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin2))
11643         {
11644                 debug_error("failed to sync decodebin2 state with parent\n");
11645                 goto ERROR;
11646         }
11647
11648         MMPLAYER_FLEAVE();
11649
11650         return TRUE;
11651
11652 ERROR:
11653
11654         MMPLAYER_FREEIF( caps_str );
11655
11656         if (sinkpad)
11657                 gst_object_unref(GST_OBJECT(sinkpad));
11658
11659         if (queue2)
11660         {
11661                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
11662                  * You need to explicitly set elements to the NULL state before
11663                  * dropping the final reference, to allow them to clean up.
11664                  */
11665                 gst_element_set_state(queue2, GST_STATE_NULL);
11666
11667                 /* And, it still has a parent "player".
11668                  * You need to let the parent manage the object instead of unreffing the object directly.
11669                  */
11670                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
11671                 gst_object_unref (queue2);
11672                 queue2 = NULL;
11673         }
11674
11675         if (id3demux)
11676         {
11677                 /* NOTE : Trying to dispose element id3demux, but it is in READY instead of the NULL state.
11678                  * You need to explicitly set elements to the NULL state before
11679                  * dropping the final reference, to allow them to clean up.
11680                  */
11681                 gst_element_set_state(id3demux, GST_STATE_NULL);
11682
11683                 /* And, it still has a parent "player".
11684                  * You need to let the parent manage the object instead of unreffing the object directly.
11685                  */
11686                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), id3demux);
11687                 gst_object_unref (id3demux);
11688                 id3demux = NULL;
11689         }
11690
11691         if (decodebin2)
11692         {
11693                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
11694                  * You need to explicitly set elements to the NULL state before
11695                  * dropping the final reference, to allow them to clean up.
11696                  */
11697                 gst_element_set_state(decodebin2, GST_STATE_NULL);
11698
11699                 /* And, it still has a parent "player".
11700                  * You need to let the parent manage the object instead of unreffing the object directly.
11701                  */
11702
11703                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin2);
11704                 gst_object_unref (decodebin2);
11705                 decodebin2 = NULL;
11706         }
11707
11708         return FALSE;
11709 }
11710
11711 /* it will return first created element */
11712 static gboolean
11713 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
11714 {
11715         MMPlayerGstElement* mainbin = NULL;
11716         const char* mime = NULL;
11717         const GList* item = NULL;
11718         const gchar* klass = NULL;
11719         GstCaps* res = NULL;
11720         gboolean skip = FALSE;
11721         GstPad* queue_pad = NULL;
11722         GstElement* queue = NULL;
11723         GstElement *element = NULL;
11724
11725         MMPLAYER_FENTER();
11726
11727         return_val_if_fail( player && player->pipeline && player->pipeline->mainbin, FALSE );
11728
11729         mainbin = player->pipeline->mainbin;
11730
11731         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
11732
11733         /* return if we got raw output */
11734         if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
11735                 || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup"))
11736         {
11737
11738                 element = (GstElement*)gst_pad_get_parent(pad);
11739 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
11740  * No queue will be added. I think it can caused breaking sound when playing raw audio
11741  * frames but there's no different. Decodebin also doesn't add with those wav fils.
11742  * Anyway, currentely raw-queue seems not necessary.
11743  */
11744 #if 1
11745                 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
11746                  * has linked. if so, we need to add queue for quality of output. note that
11747                  * decodebin also has same problem.
11748                  */
11749                 klass = gst_element_factory_get_klass( gst_element_get_factory(element) );
11750
11751                 /* add queue if needed */
11752                 if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
11753                         || g_strrstr(klass, "Parse")) &&  !g_str_has_prefix(mime, "text"))
11754                 {
11755                         debug_log("adding raw queue\n");
11756
11757                         queue = gst_element_factory_make("queue", NULL);
11758                         if ( ! queue )
11759                         {
11760                                 debug_warning("failed to create queue\n");
11761                                 goto ERROR;
11762                         }
11763
11764                         /* warmup */
11765                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
11766                         {
11767                                 debug_warning("failed to set state READY to queue\n");
11768                                 goto ERROR;
11769                         }
11770
11771                         /* add to pipeline */
11772                         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
11773                         {
11774                                 debug_warning("failed to add queue\n");
11775                                 goto ERROR;
11776                         }
11777
11778                         /* link queue */
11779                         queue_pad = gst_element_get_static_pad(queue, "sink");
11780
11781                         if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
11782                         {
11783                                 debug_warning("failed to link queue\n");
11784                                 goto ERROR;
11785                         }
11786                         gst_object_unref ( GST_OBJECT(queue_pad) );
11787                         queue_pad = NULL;
11788
11789                         /* running */
11790                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
11791                         {
11792                                 debug_warning("failed to set state READY to queue\n");
11793                                 goto ERROR;
11794                         }
11795
11796                         /* replace given pad to queue:src */
11797                         pad = gst_element_get_static_pad(queue, "src");
11798                         if ( ! pad )
11799                         {
11800                                 debug_warning("failed to get pad from queue\n");
11801                                 goto ERROR;
11802                         }
11803                 }
11804 #endif
11805                 /* check if player can do start continually */
11806                 MMPLAYER_CHECK_CMD_IF_EXIT(player);
11807
11808                 if(__mmplayer_link_sink(player,pad))
11809                         __mmplayer_gst_decode_callback(element, pad, player);
11810
11811                 gst_object_unref( GST_OBJECT(element));
11812                 element = NULL;
11813
11814                 return TRUE;
11815         }
11816
11817         item = player->factories;
11818         for(; item != NULL ; item = item->next)
11819         {
11820                 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
11821                 const GList *pads;
11822                 gint idx = 0;
11823
11824                 skip = FALSE;
11825
11826                 /* filtering exclude keyword */
11827                 for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
11828                 {
11829                         if ( g_strrstr(GST_OBJECT_NAME (factory),
11830                                         player->ini.exclude_element_keyword[idx] ) )
11831                         {
11832                                 debug_warning("skipping [%s] by exculde keyword [%s]\n",
11833                                         GST_OBJECT_NAME (factory),
11834                                         player->ini.exclude_element_keyword[idx] );
11835
11836                                 skip = TRUE;
11837                                 break;
11838                         }
11839                 }
11840
11841                 if ( MMPLAYER_IS_RTSP_STREAMING(player) && g_strrstr(GST_OBJECT_NAME (factory), "omx_mpeg4dec"))
11842                 {
11843                         // omx decoder can not support mpeg4video data partitioned
11844                         // rtsp streaming didn't know mpeg4video data partitioned format
11845                         // so, if rtsp playback, player will skip omx_mpeg4dec.
11846                         debug_warning("skipping [%s] when rtsp streaming \n",
11847                                         GST_OBJECT_NAME (factory));
11848
11849                         skip = TRUE;
11850                 }
11851
11852                 if ( skip ) continue;
11853
11854                 /* check factory class for filtering */
11855                 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory));
11856
11857 #ifdef TEST_ES
11858                 /*parsers are not required in case of external feeder*/
11859                 if (g_strrstr(klass, "Codec/Parser") && MMPLAYER_IS_ES_BUFF_SRC(player))
11860                         continue;
11861 #endif
11862                 /* NOTE : msl don't need to use image plugins.
11863                  * So, those plugins should be skipped for error handling.
11864                  */
11865                 if ( g_strrstr(klass, "Codec/Decoder/Image") )
11866                 {
11867                         debug_log("skipping [%s] by not required\n", GST_OBJECT_NAME (factory));
11868                         continue;
11869                 }
11870
11871                 /* check pad compatability */
11872                 for(pads = gst_element_factory_get_static_pad_templates(factory);
11873                                         pads != NULL; pads=pads->next)
11874                 {
11875                         GstStaticPadTemplate *temp1 = pads->data;
11876                         GstCaps* static_caps = NULL;
11877
11878                         if( temp1->direction != GST_PAD_SINK
11879                                 || temp1->presence != GST_PAD_ALWAYS)
11880                                 continue;
11881
11882                         if ( GST_IS_CAPS( &temp1->static_caps.caps) )
11883                         {
11884                                 /* using existing caps */
11885                                 static_caps = gst_caps_ref(temp1->static_caps.caps );
11886                         }
11887                         else
11888                         {
11889                                 /* create one */
11890                                 static_caps = gst_caps_from_string ( temp1->static_caps.string );
11891                         }
11892
11893                         res = gst_caps_intersect((GstCaps*)caps, static_caps);
11894                         gst_caps_unref( static_caps );
11895                         static_caps = NULL;
11896
11897                         if( res && !gst_caps_is_empty(res) )
11898                         {
11899                                 GstElement *new_element;
11900                                 GList *elements = player->parsers;
11901                                 char *name_template = g_strdup(temp1->name_template);
11902                                 gchar *name_to_plug = GST_OBJECT_NAME(factory);
11903                                 gst_caps_unref(res);
11904
11905                                 /* check ALP Codec can be used or not */
11906                                 if ((g_strrstr(klass, "Codec/Decoder/Audio")))
11907                                 {
11908                                         /* consider mp3 audio only */
11909                                         if ( !MMPLAYER_IS_STREAMING(player) && __mmplayer_is_only_mp3_type(player->type) )
11910                                         {
11911                                                 /* try to use ALP decoder first instead of selected decoder */
11912                                                 GstElement *element = NULL;
11913                                                 GstElementFactory * element_facory;
11914                                                 gchar *path = NULL;
11915                                                 guint64 data_size = 0;
11916                                                 #define MIN_THRESHOLD_SIZE  320 * 1024 // 320K
11917                                                 struct stat sb;
11918
11919                                                 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
11920
11921                                                 if (stat(path, &sb) == 0)
11922                                                 {
11923                                                         data_size = (guint64)sb.st_size;
11924                                                 }
11925                                                 debug_log("file size : %u", data_size);
11926
11927                                                 if (data_size > MIN_THRESHOLD_SIZE)
11928                                                 {
11929                                                         debug_log("checking if ALP can be used or not");
11930                                                         element = gst_element_factory_make("omx_mp3dec", "omx mp3 decoder");
11931                                                         if ( element )
11932                                                         {
11933                                                                 /* check availability because multi-instance is not supported */
11934                                                                 GstStateChangeReturn ret = gst_element_set_state(element, GST_STATE_READY);
11935
11936                                                                 if (ret != GST_STATE_CHANGE_SUCCESS) // use just selected decoder
11937                                                                 {
11938                                                                         gst_object_unref (element);
11939                                                                 }
11940                                                                 else if (ret == GST_STATE_CHANGE_SUCCESS) // replace facotry to use omx
11941                                                                 {
11942                                                                         /* clean  */
11943                                                                         gst_element_set_state(element, GST_STATE_NULL);
11944                                                                         gst_object_unref (element);
11945
11946                                                                         element_facory = gst_element_factory_find("omx_mp3dec");
11947                                                                         /* replace, otherwise use selected thing instead */
11948                                                                         if (element_facory)
11949                                                                         {
11950                                                                                 factory = element_facory;
11951                                                                                 name_to_plug = GST_OBJECT_NAME(factory);
11952                                                                         }
11953
11954                                                                         /* make parser alp mode */
11955                                                                         #ifdef _MM_PLAYER_ALP_PARSER
11956                                                                         g_list_foreach (player->parsers, check_name, player);
11957                                                                         #endif
11958                                                                 }
11959                                                         }
11960                                                 }
11961                                         }
11962                                 }
11963                                 else if ((g_strrstr(klass, "Codec/Decoder/Video")))
11964                                 {
11965                                         if ( g_strrstr(GST_OBJECT_NAME(factory), "omx_") )
11966                                         {
11967                                                 char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
11968                                                 if (env != NULL)
11969                                                 {
11970                                                         if (strncasecmp(env, "yes", 3) == 0)
11971                                                         {
11972                                                                 debug_log("skipping [%s] by disabled\n", name_to_plug);
11973                                                                 MMPLAYER_FREEIF(name_template);
11974                                                                 continue;
11975                                                         }
11976                                                 }
11977                                         }
11978                                 }
11979
11980                                 debug_log("found %s to plug\n", name_to_plug);
11981
11982                                 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
11983                                 if ( ! new_element )
11984                                 {
11985                                         debug_error("failed to create element [%s]. continue with next.\n",
11986                                                 GST_OBJECT_NAME (factory));
11987
11988                                         MMPLAYER_FREEIF(name_template);
11989
11990                                         continue;
11991                                 }
11992
11993                                 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
11994                                  * because parser can accept its own output as input.
11995                                  */
11996                                 if (g_strrstr(klass, "Parser"))
11997                                 {
11998                                         gchar *selected = NULL;
11999
12000                                         for ( ; elements; elements = g_list_next(elements))
12001                                         {
12002                                                 gchar *element_name = elements->data;
12003
12004                                                 if (g_strrstr(element_name, name_to_plug))
12005                                                 {
12006                                                         debug_log("but, %s already linked, so skipping it\n", name_to_plug);
12007                                                         skip = TRUE;
12008                                                 }
12009                                         }
12010
12011                                         if (skip)
12012                                         {
12013                                                 MMPLAYER_FREEIF(name_template);
12014                                                 continue;
12015                                         }
12016
12017                                         selected = g_strdup(name_to_plug);
12018                                         player->parsers = g_list_append(player->parsers, selected);
12019                                 }
12020
12021                                 /* store specific handles for futher control */
12022                                 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
12023                                 {
12024                                         /* FIXIT : first value will be overwritten if there's more
12025                                          * than 1 demuxer/parser
12026                                          */
12027                                         debug_log("plugged element is demuxer. take it\n");
12028                                         mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
12029                                         mainbin[MMPLAYER_M_DEMUX].gst = new_element;
12030
12031                                         /*Added for multi audio support */
12032                                         if(g_strrstr(klass, "Demux"))
12033                                         {
12034                                                 mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
12035                                                 mainbin[MMPLAYER_M_DEMUX_EX].gst = new_element;
12036
12037                                                 /* NOTE : workaround for bug in mpegtsdemux since doesn't emit
12038                                                 no-more-pad signal. this may cause wrong content attributes at PAUSED state
12039                                                 this code should be removed after mpegtsdemux is fixed */
12040                                                 if ( g_strrstr(GST_OBJECT_NAME(factory), "mpegtsdemux") )
12041                                                 {
12042                                                         debug_warning("force no-more-pad to TRUE since mpegtsdemux os not giving no-more-pad signal. content attributes may wrong");
12043                                                         player->no_more_pad = TRUE;
12044                                                 }
12045                                         }
12046                                         if (g_strrstr(name_to_plug, "asfdemux")) // to support trust-zone only
12047                                         {
12048                                                 g_object_set(mainbin[MMPLAYER_M_DEMUX_EX].gst, "file-location", player->profile.uri,NULL);
12049                                         }
12050                                 }
12051                                 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
12052                                 {
12053                                         if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
12054                                         {
12055                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
12056                                                 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
12057                                                 mainbin[MMPLAYER_M_DEC1].gst = new_element;
12058                                         }
12059                                         else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
12060                                         {
12061                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
12062                                                 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
12063                                                 mainbin[MMPLAYER_M_DEC2].gst = new_element;
12064                                         }
12065                                         /* NOTE : IF one codec is found, add it to supported_codec and remove from
12066                                          * missing plugin. Both of them are used to check what's supported codec
12067                                          * before returning result of play start. And, missing plugin should be
12068                                          * updated here for multi track files.
12069                                          */
12070                                         if(g_str_has_prefix(mime, "video"))
12071                                         {
12072                                                 GstPad *src_pad = NULL;
12073                                                 GstPadTemplate *pad_templ = NULL;
12074                                                 GstCaps *caps = NULL;
12075                                                 gchar *caps_str = NULL;
12076
12077                                                 debug_log("found VIDEO decoder\n");
12078                                                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
12079                                                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
12080
12081                                                 src_pad = gst_element_get_static_pad (new_element, "src");
12082                                                 pad_templ = gst_pad_get_pad_template (src_pad);
12083                                                 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
12084
12085                                                 caps_str = gst_caps_to_string(caps);
12086
12087                                                 /* clean */
12088                                                 MMPLAYER_FREEIF( caps_str );
12089                                                 gst_object_unref (src_pad);
12090                                         }
12091                                         else if (g_str_has_prefix(mime, "audio"))
12092                                         {
12093                                                 debug_log("found AUDIO decoder\n");
12094                                                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
12095                                                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
12096                                         }
12097                                 }
12098
12099                                 if ( ! __mmplayer_close_link(player, pad, new_element,
12100                                                         name_template,gst_element_factory_get_static_pad_templates(factory)) )
12101                                 {
12102                                         MMPLAYER_FREEIF(name_template);
12103                                         if (player->keep_detecting_vcodec)
12104                                         continue;
12105
12106                                         /* Link is failed even though a supportable codec is found. */
12107                                         __mmplayer_check_not_supported_codec(player, klass, mime);
12108
12109                                         debug_error("failed to call _close_link\n");
12110                                         return FALSE;
12111                                 }
12112
12113                                 MMPLAYER_FREEIF(name_template);
12114                                 return TRUE;
12115                         }
12116
12117                         gst_caps_unref(res);
12118                         break;
12119                 }
12120         }
12121
12122         /* There is no available codec. */
12123         __mmplayer_check_not_supported_codec(player, klass, mime);
12124
12125         MMPLAYER_FLEAVE();
12126         return FALSE;
12127
12128 ERROR:
12129         /* release */
12130         if ( queue )
12131                 gst_object_unref( queue );
12132
12133         if ( queue_pad )
12134                 gst_object_unref( queue_pad );
12135
12136         if ( element )
12137                 gst_object_unref ( element );
12138
12139         return FALSE;
12140 }
12141
12142
12143 static int
12144 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
12145 {
12146         MMPLAYER_FENTER();
12147
12148         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
12149         return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
12150
12151         debug_log("class : %s, mime : %s \n", factory_class, mime );
12152
12153         /* add missing plugin */
12154         /* NOTE : msl should check missing plugin for image mime type.
12155          * Some motion jpeg clips can have playable audio track.
12156          * So, msl have to play audio after displaying popup written video format not supported.
12157          */
12158         if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
12159         {
12160                 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
12161                 {
12162                         debug_log("not found demuxer\n");
12163                         player->not_found_demuxer = TRUE;
12164                         player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
12165
12166                         goto DONE;
12167                 }
12168         }
12169
12170         if( !g_strrstr(factory_class, "Demuxer"))
12171         {
12172                 if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
12173                 {
12174                         debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
12175                                 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
12176
12177                         /* check that clip have multi tracks or not */
12178                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
12179                         {
12180                                 debug_log("video plugin is already linked\n");
12181                         }
12182                         else
12183                         {
12184                                 debug_warning("add VIDEO to missing plugin\n");
12185                                 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
12186                         }
12187                 }
12188                 else if ( g_str_has_prefix(mime, "audio") )
12189                 {
12190                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
12191                         {
12192                                 debug_log("audio plugin is already linked\n");
12193                         }
12194                         else
12195                         {
12196                                 debug_warning("add AUDIO to missing plugin\n");
12197                                 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
12198                         }
12199                 }
12200         }
12201
12202 DONE:
12203         MMPLAYER_FLEAVE();
12204
12205         return MM_ERROR_NONE;
12206 }
12207
12208
12209 static void
12210 __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
12211 {
12212     mm_player_t* player = (mm_player_t*)data;
12213
12214         MMPLAYER_FENTER();
12215
12216         return_if_fail( player );
12217
12218         /* remove fakesink. */
12219         if ( !__mmplayer_gst_remove_fakesink( player,
12220                                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
12221         {
12222                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
12223                  * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
12224                  * source element are not same. To overcome this situation, this function will called
12225                  * several places and several times. Therefore, this is not an error case.
12226                  */
12227                 return;
12228         }
12229
12230         debug_log("pipeline has completely constructed\n");
12231
12232         if (( player->ini.async_start ) &&
12233                 ( player->msg_posted == FALSE ) &&
12234                 ( player->cmd >= MMPLAYER_COMMAND_START ))
12235         {
12236                 __mmplayer_handle_missed_plugin( player );
12237         }
12238
12239         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complete" );
12240 }
12241
12242 static gboolean
12243 __mmplayer_verify_next_play_path(mm_player_t *player)
12244 {
12245         MMHandleType attrs = 0;
12246         MMPlayerParseProfile profile;
12247         gint uri_idx = 0, check_cnt = 0;
12248         char *uri = NULL;
12249         gint mode = MM_PLAYER_PD_MODE_NONE;
12250         gint count = 0;
12251         guint num_of_list = 0;
12252
12253         MMPLAYER_FENTER();
12254
12255         debug_log("checking for next play");
12256
12257         if (player->pipeline->textbin)
12258         {
12259                 debug_error("subtitle path is enabled. next play is not supported.\n");
12260                 goto ERROR;
12261         }
12262
12263         attrs = MMPLAYER_GET_ATTRS(player);
12264         if ( !attrs )
12265         {
12266                 debug_error("fail to get attributes.\n");
12267                 goto ERROR;
12268         }
12269
12270         /* seamless playback is supported in case of audio only */
12271         mm_attrs_get_int_by_name(attrs, "content_video_found", &mode);
12272         if (mode)
12273         {
12274                 debug_log("video found");
12275                 goto ERROR;
12276         }
12277
12278         if (mm_attrs_get_int_by_name (attrs, "pd_mode", &mode) == MM_ERROR_NONE)
12279         {
12280                 if (mode == TRUE)
12281                 {
12282                         debug_warning("pd mode\n");
12283                         goto ERROR;
12284                 }
12285         }
12286
12287         if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
12288         {
12289                 debug_error("can not get play count\n");
12290         }
12291
12292         num_of_list = g_list_length(player->uri_info.uri_list);
12293
12294         debug_log("repeat count = %d, num_of_list = %d\n", count, num_of_list);
12295
12296         if ( num_of_list == 0 )
12297         {
12298                 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE)
12299                 {
12300                         debug_error("can not get profile_uri\n");
12301                         goto ERROR;
12302                 }
12303
12304                 if (!uri)
12305                 {
12306                         debug_error("uri list is empty.\n");
12307                         goto ERROR;
12308                 }
12309
12310                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12311                 debug_log("add original path : %s ", uri);
12312
12313                 num_of_list = 1;
12314                 uri= NULL;
12315         }
12316
12317         uri_idx = player->uri_info.uri_idx;
12318
12319         while(TRUE)
12320         {
12321                 check_cnt++;
12322
12323                 if (check_cnt > num_of_list)
12324                 {
12325                         debug_error("there is no valid uri.");
12326                         goto ERROR;
12327                 }
12328
12329                 debug_log("uri idx : %d / %d\n", uri_idx, num_of_list);
12330
12331                 if ( uri_idx < num_of_list-1 )
12332                 {
12333                         uri_idx++;
12334                 }
12335                 else
12336                 {
12337                         if ((count <= 1) && (count != -1))
12338                         {
12339                                 debug_log("no repeat.");
12340                                 goto ERROR;
12341                         }
12342                         else if ( count > 1 )   /* decrease play count */
12343                         {
12344                                 /* we successeded to rewind. update play count and then wait for next EOS */
12345                                 count--;
12346
12347                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
12348
12349                                 /* commit attribute */
12350                                 if ( mmf_attrs_commit ( attrs ) )
12351                                 {
12352                                         debug_error("failed to commit attribute\n");
12353                                 }
12354                         }
12355
12356                         /* count < 0 : repeat continually */
12357                         uri_idx = 0;
12358                 }
12359
12360                 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12361                 debug_log("uri idx : %d, uri = %s\n", uri_idx, uri);
12362
12363                 if (uri == NULL)
12364                 {
12365                         debug_warning("next uri does not exist\n");
12366                         continue;
12367                 }
12368
12369                 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE)
12370                 {
12371                         debug_error("failed to parse profile\n");
12372                         continue;
12373                 }
12374
12375                 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
12376                         (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP))
12377                 {
12378                         debug_warning("uri type is not supported (%d).", profile.uri_type);
12379                         continue;
12380                 }
12381
12382                 break;
12383         }
12384
12385         player->uri_info.uri_idx = uri_idx;
12386         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
12387
12388
12389         if (mmf_attrs_commit(player->attrs))
12390         {
12391                 debug_error("failed to commit.\n");
12392                 goto ERROR;
12393         }
12394
12395         debug_log("next uri %s (%d)\n", uri, uri_idx);
12396
12397         return TRUE;
12398
12399 ERROR:
12400
12401         debug_error("unable to play next path. EOS will be posted soon.\n");
12402         return FALSE;
12403 }
12404
12405 static void
12406 __mmplayer_initialize_next_play(mm_player_t *player)
12407 {
12408         int i;
12409
12410         MMPLAYER_FENTER();
12411
12412         player->needed_v_parser = FALSE;
12413         player->smooth_streaming = FALSE;
12414         player->videodec_linked = 0;
12415         player->audiodec_linked = 0;
12416         player->videosink_linked = 0;
12417         player->audiosink_linked = 0;
12418         player->textsink_linked = 0;
12419         player->is_external_subtitle_present = FALSE;
12420         player->not_supported_codec = MISSING_PLUGIN_NONE;
12421         player->can_support_codec = FOUND_PLUGIN_NONE;
12422         player->pending_seek.is_pending = FALSE;
12423         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
12424         player->pending_seek.pos = 0;
12425         player->msg_posted = FALSE;
12426         player->has_many_types = FALSE;
12427         player->no_more_pad = FALSE;
12428         player->is_drm_file = FALSE;
12429         player->not_found_demuxer = 0;
12430         player->doing_seek = FALSE;
12431         player->max_audio_channels = 0;
12432         player->is_subtitle_force_drop = FALSE;
12433         player->play_subtitle = FALSE;
12434         player->use_textoverlay = FALSE;
12435         player->adjust_subtitle_pos = 0;
12436
12437         player->updated_bitrate_count = 0;
12438         player->total_bitrate = 0;
12439         player->updated_maximum_bitrate_count = 0;
12440         player->total_maximum_bitrate = 0;
12441
12442         _mmplayer_track_initialize(player);
12443
12444         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
12445         {
12446                 player->bitrate[i] = 0;
12447                 player->maximum_bitrate[i] = 0;
12448         }
12449
12450         if (player->v_stream_caps)
12451         {
12452                 gst_caps_unref(player->v_stream_caps);
12453                 player->v_stream_caps = NULL;
12454         }
12455
12456         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
12457         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
12458
12459         /* clean found parsers */
12460         if (player->parsers)
12461         {
12462                 GList *parsers = player->parsers;
12463                 for ( ;parsers ; parsers = g_list_next(parsers))
12464                 {
12465                         gchar *name = parsers->data;
12466                         MMPLAYER_FREEIF(name);
12467                 }
12468                 g_list_free(player->parsers);
12469                 player->parsers = NULL;
12470         }
12471
12472         /* clean found audio decoders */
12473         if (player->audio_decoders)
12474         {
12475                 GList *a_dec = player->audio_decoders;
12476                 for ( ;a_dec ; a_dec = g_list_next(a_dec))
12477                 {
12478                         gchar *name = a_dec->data;
12479                         MMPLAYER_FREEIF(name);
12480                 }
12481                 g_list_free(player->audio_decoders);
12482                 player->audio_decoders = NULL;
12483         }
12484
12485         MMPLAYER_FLEAVE();
12486 }
12487
12488 static void
12489 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
12490 {
12491         MMPlayerGstElement *mainbin = NULL;
12492         MMMessageParamType msg_param = {0,};
12493         GstElement *element = NULL;
12494         MMHandleType attrs = 0;
12495         char *uri = NULL;
12496         enum MainElementID elemId = MMPLAYER_M_NUM;
12497
12498         MMPLAYER_FENTER();
12499
12500         if ((player == NULL) ||
12501                 (player->pipeline == NULL) ||
12502                 (player->pipeline->mainbin == NULL))
12503         {
12504                 debug_error("player is null.\n");
12505                 goto ERROR;
12506         }
12507
12508         mainbin = player->pipeline->mainbin;
12509         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
12510
12511         attrs = MMPLAYER_GET_ATTRS(player);
12512         if ( !attrs )
12513         {
12514                 debug_error("fail to get attributes.\n");
12515                 goto ERROR;
12516         }
12517
12518         /* Initialize Player values */
12519         __mmplayer_initialize_next_play(player);
12520
12521         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
12522
12523         if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE)
12524         {
12525                 debug_error("failed to parse profile\n");
12526                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
12527                 goto ERROR;
12528         }
12529
12530         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
12531                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player)))
12532         {
12533                 debug_error("it's dash or hls. not support.");
12534                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
12535                 goto ERROR;
12536         }
12537
12538         /* setup source */
12539         switch ( player->profile.uri_type )
12540         {
12541                 /* file source */
12542                 case MM_PLAYER_URI_TYPE_FILE:
12543                 {
12544                         debug_log("using filesrc for 'file://' handler.\n");
12545
12546                         element = gst_element_factory_make("filesrc", "source");
12547
12548                         if ( !element )
12549                         {
12550                                 debug_error("failed to create filesrc\n");
12551                                 break;
12552                         }
12553
12554                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
12555                         break;
12556                 }
12557                 case MM_PLAYER_URI_TYPE_URL_HTTP:
12558                 {
12559                         gchar *user_agent, *proxy, *cookies, **cookie_list;
12560                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
12561                         user_agent = proxy = cookies = NULL;
12562                         cookie_list = NULL;
12563
12564                         element = gst_element_factory_make(player->ini.name_of_httpsrc, "http_streaming_source");
12565                         if ( !element )
12566                         {
12567                                 debug_error("failed to create http streaming source element[%s].\n", player->ini.name_of_httpsrc);
12568                                 break;
12569                         }
12570                         debug_log("using http streamming source [%s].\n", player->ini.name_of_httpsrc);
12571
12572                         /* get attribute */
12573                         mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
12574                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
12575                         mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
12576                         mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
12577
12578                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
12579                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
12580                         {
12581                                 debug_log("get timeout from ini\n");
12582                                 http_timeout = player->ini.http_timeout;
12583                         }
12584
12585                         /* get attribute */
12586                         secure_debug_log("location : %s\n", player->profile.uri);
12587                         secure_debug_log("cookies : %s\n", cookies);
12588                         secure_debug_log("proxy : %s\n", proxy);
12589                         secure_debug_log("user_agent :  %s\n", user_agent);
12590                         debug_log("timeout : %d\n", http_timeout);
12591
12592                         /* setting property to streaming source */
12593                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
12594                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
12595                         g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
12596
12597                         /* check if prosy is vailid or not */
12598                         if ( util_check_valid_url ( proxy ) )
12599                                 g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
12600                         /* parsing cookies */
12601                         if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
12602                                 g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
12603                         if ( user_agent )
12604                                 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
12605                         break;
12606                 }
12607                 default:
12608                         debug_error("not support uri type %d\n", player->profile.uri_type);
12609                         break;
12610         }
12611
12612         if ( !element )
12613         {
12614                 debug_error("no source element was created.\n");
12615                 goto ERROR;
12616         }
12617
12618         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
12619         {
12620                 debug_error("failed to add source element to pipeline\n");
12621                 gst_object_unref(GST_OBJECT(element));
12622                 element = NULL;
12623                 goto ERROR;
12624         }
12625
12626         /* take source element */
12627         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
12628         mainbin[MMPLAYER_M_SRC].gst = element;
12629
12630         element = NULL;
12631
12632         if (MMPLAYER_IS_HTTP_STREAMING(player))
12633         {
12634                 if (player->streamer == NULL)
12635                 {
12636                         player->streamer = __mm_player_streaming_create();
12637                         __mm_player_streaming_initialize(player->streamer);
12638                 }
12639
12640                 elemId = MMPLAYER_M_TYPEFIND;
12641                 element = gst_element_factory_make("typefind", "typefinder");
12642                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
12643                         G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
12644         }
12645         else
12646         {
12647                 elemId = MMPLAYER_M_AUTOPLUG;
12648                 element = __mmplayer_create_decodebin(player);
12649         }
12650
12651         /* check autoplug element is OK */
12652         if ( ! element )
12653         {
12654                 debug_error("can not create element (%d)\n", elemId);
12655                 goto ERROR;
12656         }
12657
12658         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
12659         {
12660                 debug_error("failed to add sinkbin to pipeline\n");
12661                 gst_object_unref(GST_OBJECT(element));
12662                 element = NULL;
12663                 goto ERROR;
12664         }
12665
12666         mainbin[elemId].id = elemId;
12667         mainbin[elemId].gst = element;
12668
12669         if ( gst_element_link (mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE )
12670         {
12671                 debug_error("Failed to link src - autoplug (or typefind)\n");
12672                 goto ERROR;
12673         }
12674
12675         if (gst_element_set_state (mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE)
12676         {
12677                 debug_error("Failed to change state of src element\n");
12678                 goto ERROR;
12679         }
12680
12681         if (!MMPLAYER_IS_HTTP_STREAMING(player))
12682         {
12683                 if (gst_element_set_state (mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE)
12684                 {
12685                         debug_error("Failed to change state of decodebin2\n");
12686                         goto ERROR;
12687                 }
12688         }
12689         else
12690         {
12691                 if (gst_element_set_state (mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE)
12692                 {
12693                         debug_error("Failed to change state of src element\n");
12694                         goto ERROR;
12695                 }
12696         }
12697
12698         player->src_changed = TRUE;
12699         MMPLAYER_FLEAVE();
12700         return;
12701
12702 ERROR:
12703         MMPLAYER_PLAYBACK_UNLOCK(player);
12704
12705         if (!player->msg_posted)
12706         {
12707                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
12708                 player->msg_posted = TRUE;
12709         }
12710         return;
12711 }
12712
12713 static gboolean
12714 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
12715 {
12716         mm_player_selector_t *selector = &player->selector[type];
12717         MMPlayerGstElement *sinkbin = NULL;
12718         enum MainElementID selectorId = MMPLAYER_M_NUM;
12719         enum MainElementID sinkId = MMPLAYER_M_NUM;
12720         GstPad *srcpad = NULL;
12721         GstPad *sinkpad = NULL;
12722
12723         MMPLAYER_FENTER();
12724         return_val_if_fail (player, FALSE);
12725
12726         debug_log("type %d", type);
12727
12728         switch (type)
12729         {
12730 #ifdef _USE_M_V_INPUT_SELECTOR_
12731                 case MM_PLAYER_TRACK_TYPE_VIDEO:
12732                         selectorId = MMPLAYER_M_V_INPUT_SELECTOR;
12733                         sinkId = MMPLAYER_V_BIN;
12734                         sinkbin = player->pipeline->videobin;
12735                         debug_log("not supported yet");
12736                 break;
12737 #endif
12738                 case MM_PLAYER_TRACK_TYPE_AUDIO:
12739                         selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
12740                         sinkId = MMPLAYER_A_BIN;
12741                         sinkbin = player->pipeline->audiobin;
12742                 break;
12743                 case MM_PLAYER_TRACK_TYPE_TEXT:
12744                         selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
12745                         sinkId = MMPLAYER_T_BIN;
12746                         sinkbin = player->pipeline->textbin;
12747                 break;
12748                 default:
12749                         debug_error("requested type is not supportable");
12750                         return FALSE;
12751                 break;
12752         }
12753
12754         if (player->pipeline->mainbin[selectorId].gst)
12755         {
12756                 gint n;
12757
12758                 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
12759
12760                 if ((sinkbin) && (sinkbin[sinkId].gst))
12761                 {
12762                         sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
12763
12764                         if (srcpad && sinkpad)
12765                         {
12766                                 /* after getting drained signal there is no data flows, so no need to do pad_block */
12767                                 debug_log("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
12768                                 gst_pad_unlink (srcpad, sinkpad);
12769                         }
12770
12771                         gst_object_unref (sinkpad);
12772                         sinkpad = NULL;
12773                 }
12774                 gst_object_unref (srcpad);
12775                 srcpad = NULL;
12776
12777                 debug_log("selector release");
12778
12779                 /* release and unref requests pad from the selector */
12780                 for (n = 0; n < selector->channels->len; n++)
12781                 {
12782                         GstPad *sinkpad = g_ptr_array_index (selector->channels, n);
12783                         gst_element_release_request_pad ((player->pipeline->mainbin[selectorId].gst), sinkpad);
12784                 }
12785                 g_ptr_array_set_size (selector->channels, 0);
12786
12787                 gst_element_set_state (player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
12788                 gst_bin_remove (GST_BIN_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
12789
12790                 player->pipeline->mainbin[selectorId].gst = NULL;
12791                 selector = NULL;
12792         }
12793
12794         return TRUE;
12795 }
12796
12797 static void
12798 __mmplayer_deactivate_old_path(mm_player_t *player)
12799 {
12800         MMPLAYER_FENTER();
12801         return_if_fail ( player );
12802
12803         g_object_set(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEC1].gst), "remove-buffer-signal", TRUE, NULL);
12804 #ifdef _USE_M_V_INPUT_SELECTOR_
12805         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
12806                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
12807                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT)))
12808 #else
12809         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
12810                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT)))
12811 #endif
12812         {
12813                 debug_error("deactivate selector error");
12814                 goto ERROR;
12815         }
12816
12817         _mmplayer_track_destroy(player);
12818         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG );
12819
12820         if (player->streamer)
12821         {
12822                 __mm_player_streaming_deinitialize (player->streamer);
12823                 __mm_player_streaming_destroy(player->streamer);
12824                 player->streamer = NULL;
12825         }
12826
12827         MMPLAYER_PLAYBACK_LOCK(player);
12828         g_cond_signal( &player->next_play_thread_cond );
12829
12830         MMPLAYER_FLEAVE();
12831         return;
12832
12833 ERROR:
12834
12835         if (!player->msg_posted)
12836         {
12837                 MMMessageParamType msg = {0,};
12838
12839                 /*post error*/
12840                 msg.code = MM_ERROR_PLAYER_INTERNAL;
12841                 debug_error("next_uri_play> deactivate error");
12842
12843                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
12844                 player->msg_posted = TRUE;
12845         }
12846         return;
12847 }
12848
12849 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
12850 {
12851         int result = MM_ERROR_NONE;
12852         mm_player_t* player = (mm_player_t*) hplayer;
12853         MMPLAYER_FENTER();
12854
12855         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12856
12857         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
12858         if (mmf_attrs_commit(player->attrs))
12859         {
12860                 debug_error("failed to commit the original uri.\n");
12861                 result = MM_ERROR_PLAYER_INTERNAL;
12862         }
12863         else
12864         {
12865                 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
12866                 {
12867                         debug_error("failed to add the original uri in the uri list.\n");
12868                 }
12869         }
12870
12871         MMPLAYER_FLEAVE();
12872         return result;
12873 }
12874
12875 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
12876 {
12877         mm_player_t* player = (mm_player_t*) hplayer;
12878         guint num_of_list = 0;
12879
12880         MMPLAYER_FENTER();
12881
12882         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12883         return_val_if_fail (uri, MM_ERROR_INVALID_ARGUMENT);
12884
12885         if (player->pipeline && player->pipeline->textbin)
12886         {
12887                 debug_error("subtitle path is enabled.\n");
12888                 return MM_ERROR_PLAYER_INVALID_STATE;
12889         }
12890
12891         num_of_list = g_list_length(player->uri_info.uri_list);
12892
12893         if (is_first_path == TRUE)
12894         {
12895                 if (num_of_list == 0)
12896                 {
12897                         player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12898                         debug_log("add original path : %s", uri);
12899                 }
12900                 else
12901                 {
12902                         player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
12903                         player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
12904
12905                         debug_log("change original path : %s", uri);
12906                 }
12907         }
12908         else
12909         {
12910                 if (num_of_list == 0)
12911                 {
12912                         MMHandleType attrs = 0;
12913                         char *original_uri = NULL;
12914
12915                         attrs = MMPLAYER_GET_ATTRS(player);
12916                         if ( attrs )
12917                         {
12918                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
12919
12920                                 if (!original_uri)
12921                                 {
12922                                         debug_error("there is no original uri.");
12923                                         return MM_ERROR_PLAYER_INVALID_STATE;
12924                                 }
12925
12926                                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
12927                                 player->uri_info.uri_idx = 0;
12928
12929                                 debug_log("add original path at first : %s (%d)", original_uri);
12930                         }
12931                 }
12932
12933                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12934                 debug_log("add new path : %s (total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
12935         }
12936
12937         MMPLAYER_FLEAVE();
12938         return MM_ERROR_NONE;
12939 }
12940
12941 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
12942 {
12943         mm_player_t* player = (mm_player_t*) hplayer;
12944         char *next_uri = NULL;
12945         guint num_of_list = 0;
12946
12947         MMPLAYER_FENTER();
12948         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12949
12950         num_of_list = g_list_length(player->uri_info.uri_list);
12951
12952         if (num_of_list > 0)
12953         {
12954                 gint uri_idx = player->uri_info.uri_idx;
12955
12956                 if ( uri_idx < num_of_list-1 )
12957                         uri_idx++;
12958                 else
12959                         uri_idx = 0;
12960
12961                 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12962                 debug_error("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
12963
12964                 *uri = g_strdup(next_uri);
12965         }
12966
12967         MMPLAYER_FLEAVE();
12968         return MM_ERROR_NONE;
12969 }
12970
12971 static void
12972 __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad,
12973 GstCaps *caps, gpointer data)
12974 {
12975         mm_player_t* player = (mm_player_t*)data;
12976         const gchar* klass = NULL;
12977         const gchar* mime = NULL;
12978         gchar* caps_str = NULL;
12979
12980         klass = gst_element_factory_get_klass (gst_element_get_factory(elem));
12981         mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12982         caps_str = gst_caps_to_string(caps);
12983
12984         debug_warning("unknown type of caps : %s from %s",
12985                                         caps_str, GST_ELEMENT_NAME (elem));
12986
12987         MMPLAYER_FREEIF(caps_str);
12988
12989         /* There is no available codec. */
12990         __mmplayer_check_not_supported_codec (player, klass, mime);
12991 }
12992
12993 static gboolean
12994 __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad,
12995 GstCaps * caps,  gpointer data)
12996 {
12997         mm_player_t* player = (mm_player_t*)data;
12998         const char* mime = NULL;
12999         gboolean ret = TRUE;
13000
13001         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
13002         mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
13003
13004         if (g_str_has_prefix(mime, "audio")) {
13005                 GstStructure* caps_structure = NULL;
13006                 gint samplerate = 0;
13007                 gint channels = 0;
13008                 gchar *caps_str = NULL;
13009
13010                 caps_structure = gst_caps_get_structure(caps, 0);
13011                 gst_structure_get_int (caps_structure, "rate", &samplerate);
13012                 gst_structure_get_int (caps_structure, "channels", &channels);
13013
13014                 if ( (channels > 0 && samplerate == 0)) {
13015                         debug_log("exclude audio...");
13016                         ret = FALSE;
13017                 }
13018
13019                 caps_str = gst_caps_to_string(caps);
13020                 /* set it directly because not sent by TAG */
13021                 if (g_strrstr(caps_str, "mobile-xmf")) {
13022                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
13023                 }
13024                 MMPLAYER_FREEIF (caps_str);
13025         } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
13026                 debug_log("already video linked");
13027                 ret = FALSE;
13028         } else {
13029                 debug_log("found new stream");
13030         }
13031
13032         return ret;
13033 }
13034
13035 static gint
13036 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad,
13037 GstCaps* caps, GstElementFactory* factory, gpointer data)
13038 {
13039         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
13040          We are defining our own and will be removed when it actually exposed */
13041         typedef enum {
13042                 GST_AUTOPLUG_SELECT_TRY,
13043                 GST_AUTOPLUG_SELECT_EXPOSE,
13044                 GST_AUTOPLUG_SELECT_SKIP
13045         } GstAutoplugSelectResult;
13046
13047         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
13048         mm_player_t* player = (mm_player_t*)data;
13049
13050         gchar* factory_name = NULL;
13051         gchar* caps_str = NULL;
13052         const gchar* klass = NULL;
13053         gint idx = 0;
13054
13055         factory_name = GST_OBJECT_NAME (factory);
13056         klass = gst_element_factory_get_klass(factory);
13057         caps_str = gst_caps_to_string(caps);
13058
13059 //      debug_log("found new element [%s] to link for caps [%s]", factory_name, caps_str);
13060         debug_log("found new element [%s] to link", factory_name);
13061
13062         /* store type string */
13063         if (player->type == NULL)
13064         {
13065                 player->type = gst_caps_to_string(caps);
13066
13067                 /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
13068                 if (__mmplayer_is_midi_type(player->type))
13069                 {
13070                         player->profile.play_mode = MM_PLAYER_MODE_MIDI;
13071                         player->bypass_audio_effect = TRUE;
13072                 }
13073                 else if (g_strrstr(player->type, "application/x-hls"))
13074                 {
13075                         /* If it can't know exact type when it parses uri because of redirection case,
13076                          * it will be fixed by typefinder here.
13077                          */
13078                         player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
13079                 }
13080                 else if (g_strrstr(player->type, "application/dash+xml"))
13081                 {
13082                         player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
13083                 }
13084         }
13085
13086         /* filtering exclude keyword */
13087         for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
13088         {
13089                 if ( strstr(factory_name, player->ini.exclude_element_keyword[idx] ) )
13090                 {
13091                         debug_warning("skipping [%s] by exculde keyword [%s]\n",
13092                         factory_name, player->ini.exclude_element_keyword[idx] );
13093
13094                         // NOTE : does we need to check n_value against the number of item selected?
13095                         result = GST_AUTOPLUG_SELECT_SKIP;
13096                         goto DONE;
13097                 }
13098         }
13099
13100         /* check factory class for filtering */
13101         /* NOTE : msl don't need to use image plugins.
13102          * So, those plugins should be skipped for error handling.
13103          */
13104         if (g_strrstr(klass, "Codec/Decoder/Image"))
13105         {
13106                 debug_log("skipping [%s] by not required\n", factory_name);
13107                 result = GST_AUTOPLUG_SELECT_SKIP;
13108                 goto DONE;
13109         }
13110
13111 #ifdef TEST_ES
13112         if ((MMPLAYER_IS_ES_BUFF_SRC(player)) &&
13113                 (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser"))))
13114         {
13115                 // TO CHECK : subtitle if needed, add subparse exception.
13116                 debug_log("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
13117                 result = GST_AUTOPLUG_SELECT_SKIP;
13118                 goto DONE;
13119         }
13120 #endif
13121
13122         if (g_strrstr(factory_name, "mpegpsdemux"))
13123         {
13124                 debug_log("skipping PS container - not support\n");
13125                 result = GST_AUTOPLUG_SELECT_SKIP;
13126                 goto DONE;
13127         }
13128
13129         if (g_strrstr(factory_name, "mpegtsdemux") || g_strrstr(factory_name, SMOOTH_STREAMING_DEMUX))
13130         {
13131                 if (g_strrstr(factory_name, SMOOTH_STREAMING_DEMUX))
13132                         player->smooth_streaming = TRUE;
13133
13134                 if (g_strrstr(caps_str, "video/x-h264"))
13135                 {
13136                         player->needed_v_parser = TRUE;
13137                 }
13138                 else if (g_strrstr(caps_str, "video/mpeg"))
13139                 {
13140                         player->needed_v_parser = TRUE;
13141                 }
13142         }
13143
13144         /* check ALP Codec can be used or not */
13145         if ((g_strrstr(klass, "Codec/Decoder/Audio")))
13146         {
13147                 GstStructure* str = NULL;
13148                 gint channels = 0;
13149
13150                 str = gst_caps_get_structure( caps, 0 );
13151                 if ( str )
13152                 {
13153                         gst_structure_get_int (str, "channels", &channels);
13154
13155                         debug_log ("check audio ch : %d %d\n", player->max_audio_channels, channels);
13156                         if (player->max_audio_channels < channels)
13157                         {
13158                                 player->max_audio_channels = channels;
13159                         }
13160                 }
13161
13162                 if (!player->audiodec_linked)
13163                 {
13164                         /* set stream information */
13165                         __mmplayer_set_audio_attrs (player, caps);
13166                 }
13167         }
13168         else if ((g_strrstr(klass, "Codec/Decoder/Video")))
13169         {
13170                 if (g_strrstr(factory_name, "omx_"))
13171                 {
13172                         char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
13173                         if (env != NULL)
13174                         {
13175                                 if (strncasecmp(env, "yes", 3) == 0)
13176                                 {
13177                                         debug_log ("skipping [%s] by disabled\n", factory_name);
13178                                         result = GST_AUTOPLUG_SELECT_SKIP;
13179                                         goto DONE;
13180                                 }
13181                         }
13182                 }
13183         }
13184
13185         if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
13186                 (g_strrstr(klass, "Codec/Decoder/Video")))
13187         {
13188                 gint stype = 0;
13189                 gint width = 0;
13190                 GstStructure *str = NULL;
13191                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
13192
13193                 /* don't make video because of not required */
13194                 if (stype == MM_DISPLAY_SURFACE_NULL)
13195                 {
13196                         debug_log ("no video because it's not required. -> return expose");
13197                         if (player->set_mode.media_packet_video_stream == FALSE)
13198                         {
13199                                 result = GST_AUTOPLUG_SELECT_EXPOSE;
13200                                 goto DONE;
13201                         }
13202                 }
13203
13204                 /* get w/h for omx state-tune */
13205                 str = gst_caps_get_structure (caps, 0);
13206                 gst_structure_get_int (str, "width", &width);
13207
13208                 if (width != 0) {
13209                         if (player->v_stream_caps) {
13210                                 gst_caps_unref(player->v_stream_caps);
13211                                 player->v_stream_caps = NULL;
13212                         }
13213
13214                         player->v_stream_caps = gst_caps_copy(caps);
13215                         debug_log ("take caps for video state tune");
13216                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
13217                 }
13218         }
13219
13220         if (g_strrstr(klass, "Decoder"))
13221         {
13222                 const char* mime = NULL;
13223                 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
13224
13225                 if (g_str_has_prefix(mime, "video"))
13226                 {
13227                         // __mmplayer_check_video_zero_cpoy(player, factory);
13228
13229                         player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
13230                         player->can_support_codec |= FOUND_PLUGIN_VIDEO;
13231
13232                         player->videodec_linked = 1;
13233                 }
13234                 else if(g_str_has_prefix(mime, "audio"))
13235                 {
13236                         player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
13237                         player->can_support_codec |= FOUND_PLUGIN_AUDIO;
13238
13239                         player->audiodec_linked = 1;
13240                 }
13241         }
13242
13243 DONE:
13244         MMPLAYER_FREEIF(caps_str);
13245
13246         return result;
13247 }
13248
13249
13250 #if 0
13251 static GValueArray*
13252 __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad,
13253 GstCaps * caps,  gpointer data)
13254 {
13255         //mm_player_t* player = (mm_player_t*)data;
13256
13257         debug_log("decodebin is requesting factories for caps [%s] from element[%s]",
13258                 gst_caps_to_string(caps),
13259                 GST_ELEMENT_NAME(GST_PAD_PARENT(pad)));
13260
13261         return NULL;
13262 }
13263 #endif
13264
13265 static GValueArray*
13266         __mmplayer_gst_decode_autoplug_sort(GstElement *bin,  GstPad* pad,
13267                 GstCaps* caps, GValueArray* factories, gpointer data) // @
13268 {
13269 #define DEFAULT_IDX 0xFFFF
13270
13271         guint idx = 0;
13272         guint a_omx_idx = DEFAULT_IDX;
13273         guint a_dec_idx = DEFAULT_IDX;
13274         guint v_dec_idx = DEFAULT_IDX;
13275         guint v_parser_idx = DEFAULT_IDX;
13276         guint new_pos = DEFAULT_IDX;
13277         guint elem_idx = DEFAULT_IDX;
13278
13279         GValueArray* new_factories = NULL;
13280         GValue val = { 0, };
13281
13282         GstElementFactory *factory = NULL;
13283         const gchar* klass = NULL;
13284         gchar* factory_name = NULL;
13285         gchar* caps_str = NULL;
13286
13287         mm_player_t* player = (mm_player_t*)data;
13288         caps_str = gst_caps_to_string(caps);
13289
13290         //debug_log("autoplug-sort signal [num: %d]\n", factories->n_values);
13291         debug_log("requesting custom sorting for the factories for caps [%s]", caps_str);
13292
13293         MMPLAYER_FREEIF(caps_str);
13294
13295         for(idx=0; idx < factories->n_values; idx++)
13296         {
13297                 factory = g_value_get_object(g_value_array_get_nth(factories, idx));
13298                 klass = gst_element_factory_get_klass(factory);
13299                 factory_name = GST_OBJECT_NAME (factory);
13300
13301                 //debug_log("Klass [%s] Factory [%s]\n", klass, factory_name);
13302
13303                 if (g_strrstr(klass, "Codec/Decoder/Audio"))
13304                 {
13305                         if (a_dec_idx == DEFAULT_IDX)
13306                                 a_dec_idx = idx;
13307
13308                         /* check ALP Codec can be used or not */
13309                         if ((a_omx_idx == DEFAULT_IDX) &&
13310                                 (g_strrstr(factory_name, "omx_mp3dec")) &&
13311                                 (__mmplayer_is_omx_decoder_type(player)))
13312                         {
13313                                 debug_log("--> mp3_local : Priority of omx is higher than the others\n");
13314                                 a_omx_idx = idx;
13315                                 break;
13316                         }
13317                 }
13318                 else if ((v_dec_idx == DEFAULT_IDX) && (g_strrstr(klass, "Codec/Decoder/Video")))
13319                 {
13320                         v_dec_idx = idx;
13321                 }
13322
13323                 if ((v_parser_idx == DEFAULT_IDX) &&
13324                         (((player->smooth_streaming) &&
13325                           (g_strrstr(factory_name, "legacyh264parse"))) ||
13326                          // (g_strrstr(factory_name, "h264parse")) ||
13327                          (g_strrstr(factory_name, "mpeg4videoparse"))))
13328                 {
13329                         v_parser_idx = idx;
13330                 }
13331         }
13332
13333         if (player->needed_v_parser || player->smooth_streaming)
13334         {
13335                 debug_log("needed parser? %s, ss? %s\n",
13336                                         (player->needed_v_parser)?"OO":"XX",
13337                                         (player->smooth_streaming)?"OO":"XX");
13338         }
13339
13340         new_pos = (a_dec_idx!=DEFAULT_IDX)?(a_dec_idx):((player->needed_v_parser)?(v_dec_idx):(v_parser_idx));
13341         elem_idx = (a_omx_idx!=DEFAULT_IDX)?(a_omx_idx):((player->needed_v_parser)?(v_parser_idx):(v_dec_idx));
13342
13343         /* consider file mp3 audio only */
13344         if ((elem_idx != DEFAULT_IDX) && (new_pos < elem_idx))
13345         {
13346                 debug_log("[Re-arrange] factories sequence, new_pos : %d, elem_idx : %d\n", new_pos, elem_idx);
13347
13348                 new_factories = g_value_array_copy(factories);
13349
13350                 // insert omx decoder in front of other decoders
13351                 factory = g_value_get_object(g_value_array_get_nth(factories, elem_idx));
13352
13353                 g_value_init (&val, G_TYPE_OBJECT);
13354                 g_value_set_object (&val, factory);
13355                 g_value_array_insert(new_factories, new_pos, &val);
13356                 g_value_unset (&val);
13357
13358                 // remove duplicated omx element
13359                 g_value_array_remove(new_factories, elem_idx+1);
13360
13361                 for(idx=0; idx < new_factories->n_values; idx++)
13362                 {
13363                         factory = g_value_get_object(g_value_array_get_nth(new_factories, idx));
13364
13365                         debug_log("[Re-arranged] Klass [%s] Factory [%s]\n",
13366                                 gst_element_factory_get_klass(factory), GST_OBJECT_NAME (factory));
13367                 }
13368         }
13369
13370         /* returning NULL to keep current order */
13371         return (new_factories)?(new_factories):(NULL);
13372 }
13373
13374 static void
13375 __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad,
13376 gpointer data) // @
13377 {
13378         //mm_player_t* player = (mm_player_t*)data;
13379         GstCaps* caps = NULL;
13380
13381         debug_log("[Decodebin2] pad-removed signal\n");
13382
13383         caps = gst_pad_query_caps(new_pad, NULL);
13384         if (caps)
13385         {
13386                 gchar* caps_str = NULL;
13387                 caps_str = gst_caps_to_string(caps);
13388
13389                 debug_log("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem) );
13390
13391                 MMPLAYER_FREEIF(caps_str);
13392         }
13393 }
13394
13395 static void
13396 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
13397 {
13398         mm_player_t* player = (mm_player_t*)data;
13399
13400         MMPLAYER_FENTER();
13401         return_if_fail ( player );
13402
13403         debug_log("__mmplayer_gst_decode_drained");
13404
13405         if (player->use_deinterleave == TRUE)
13406         {
13407                 debug_log("group playing mode.");
13408                 return;
13409         }
13410
13411         if (!g_mutex_trylock(&player->cmd_lock))
13412         {
13413                 debug_warning("Fail to get cmd lock");
13414                 return;
13415         }
13416
13417         if (!__mmplayer_verify_next_play_path(player))
13418         {
13419                 debug_log("decoding is finished.");
13420                 g_mutex_unlock(&player->cmd_lock);
13421                 return;
13422         }
13423
13424         player->pp_rebuilding = TRUE;
13425
13426         /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
13427         __mmplayer_deactivate_old_path(player);
13428
13429         g_mutex_unlock(&player->cmd_lock);
13430
13431         MMPLAYER_FLEAVE();
13432 }
13433
13434 static void
13435 __mmplayer_gst_element_added (GstElement *bin, GstElement *element, gpointer data)
13436 {
13437         mm_player_t* player = (mm_player_t*)data;
13438         const gchar* klass = NULL;
13439         gchar* factory_name = NULL;
13440
13441         klass = gst_element_factory_get_klass (gst_element_get_factory(element));
13442         factory_name = GST_OBJECT_NAME (gst_element_get_factory(element));
13443
13444         debug_log("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
13445
13446         if (__mmplayer_add_dump_buffer_probe(player, element))
13447                 debug_log("add buffer probe");
13448
13449         //<-
13450         if (g_strrstr(klass, "Codec/Decoder/Audio"))
13451         {
13452                 gchar* selected = NULL;
13453                 selected = g_strdup( GST_ELEMENT_NAME(element));
13454                 player->audio_decoders = g_list_append (player->audio_decoders, selected);
13455         }
13456         //-> temp code
13457
13458         if (g_strrstr(klass, "Parser"))
13459         {
13460                 gchar* selected = NULL;
13461
13462                 selected = g_strdup (factory_name);
13463                 player->parsers = g_list_append (player->parsers, selected);
13464         }
13465
13466         if ((g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) && !(g_strrstr(klass, "Adaptive")))
13467         {
13468                 /* FIXIT : first value will be overwritten if there's more
13469                  * than 1 demuxer/parser
13470                  */
13471
13472                 //debug_log ("plugged element is demuxer. take it\n");
13473                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
13474                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
13475
13476                 /*Added for multi audio support */ // Q. del?
13477                 if (g_strrstr(klass, "Demux"))
13478                 {
13479                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
13480                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
13481                 }
13482         }
13483
13484         if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux"))
13485         {
13486                 int surface_type = 0;
13487
13488                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
13489
13490 #if 0   // this is for 0.10 plugin with downstream modification
13491                 /* playback protection if drm file */
13492                 if (player->use_video_stream || surface_type == MM_DISPLAY_SURFACE_EVAS || surface_type == MM_DISPLAY_SURFACE_X_EXT)
13493                 {
13494                         debug_log("playback can be protected if playready drm");
13495                         g_object_set (G_OBJECT(element), "playback-protection", TRUE, NULL);
13496                 }
13497 #endif
13498         }
13499
13500         // to support trust-zone only
13501         if (g_strrstr(factory_name, "asfdemux"))
13502         {
13503                 debug_log ("set file-location %s\n", player->profile.uri);
13504                 g_object_set (G_OBJECT(element), "file-location", player->profile.uri, NULL);
13505
13506                 if (player->video_hub_download_mode == TRUE)
13507                 {
13508                         g_object_set (G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
13509                 }
13510         }
13511         else if (g_strrstr(factory_name, "legacyh264parse"))    // SMOOTH_STREAMING_DEMUX
13512         {
13513                 debug_log ("[%s] output-format to legacyh264parse\n", SMOOTH_STREAMING_DEMUX);
13514                 g_object_set (G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
13515         }
13516         else if (g_strrstr(factory_name, "mpegaudioparse"))
13517         {
13518                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
13519                         (__mmplayer_is_only_mp3_type(player->type)))
13520                 {
13521                         debug_log ("[mpegaudioparse] set streaming pull mode.");
13522                         g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
13523                 }
13524         }
13525         else if (g_strrstr(factory_name, "omx"))
13526         {
13527                 if (g_strrstr(klass, "Codec/Decoder/Video"))
13528                 {
13529                         gboolean ret = FALSE;
13530
13531                         if (player->v_stream_caps != NULL)
13532                         {
13533                                 GstPad *pad = gst_element_get_static_pad(element, "sink");
13534
13535                                 if (pad)
13536                                 {
13537                                         ret = gst_pad_set_caps(pad, player->v_stream_caps);
13538                                         debug_log("found omx decoder, setting gst_pad_set_caps for omx (ret:%d)", ret);
13539                                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
13540                                         gst_object_unref (pad);
13541                                 }
13542                         }
13543                         g_object_set (G_OBJECT(element), "state-tuning", TRUE, NULL);
13544                 }
13545 #ifdef _MM_PLAYER_ALP_PARSER
13546                 if (g_strrstr(factory_name, "omx_mp3dec"))
13547                 {
13548                         g_list_foreach (player->parsers, check_name, player);
13549                 }
13550 #endif
13551                 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
13552         }
13553
13554         if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
13555                 (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue")))
13556         {
13557                 debug_log ("plugged element is multiqueue. take it\n");
13558
13559                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
13560                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
13561
13562                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
13563                         (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)))
13564                 {
13565
13566                         if ((MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) &&
13567                                 (player->streamer->buffering_req.initial_second == 0))
13568                                 player->streamer->buffering_req.initial_second = DEFAULT_LIVE_PLAYING_TIME;
13569
13570                         __mm_player_streaming_set_multiqueue(player->streamer,
13571                                 element,
13572                                 TRUE,
13573                                 MAX_DECODEBIN_BUFFER_BYTES, // player->ini.http_max_size_bytes,
13574                                 player->ini.http_buffering_time,
13575                                 1.0,
13576                                 player->ini.http_buffering_limit);
13577
13578                         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
13579                 }
13580         }
13581
13582         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-added" );
13583         return;
13584 }
13585
13586 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
13587 {
13588         MMPLAYER_FENTER();
13589         return_val_if_fail ( player, FALSE );
13590
13591         if ( MMPLAYER_IS_STREAMING(player) )
13592                 return FALSE;
13593
13594         /* This callback can be set to music player only. */
13595         if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
13596         {
13597                 debug_warning("audio callback is not supported for video");
13598                 return FALSE;
13599         }
13600
13601         if (player->audio_stream_cb)
13602         {
13603                 {
13604                         GstPad *pad = NULL;
13605
13606                         pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
13607
13608                         if ( !pad )
13609                         {
13610                                 debug_error("failed to get sink pad from audiosink to probe data\n");
13611                                 return FALSE;
13612                         }
13613                         player->audio_cb_probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
13614                                 __mmplayer_audio_stream_probe, player, NULL);
13615
13616                         gst_object_unref (pad);
13617
13618                         pad = NULL;
13619                }
13620         }
13621         else
13622         {
13623                 debug_error("There is no audio callback to configure.\n");
13624                 return FALSE;
13625         }
13626
13627         MMPLAYER_FLEAVE();
13628
13629         return TRUE;
13630 }
13631
13632 static void
13633 __mmplayer_init_factories(mm_player_t* player) // @
13634 {
13635         return_if_fail ( player );
13636
13637         player->factories = gst_registry_feature_filter(gst_registry_get(),
13638                                         (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
13639         player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
13640 }
13641
13642 static void
13643 __mmplayer_release_factories(mm_player_t* player) // @
13644 {
13645         MMPLAYER_FENTER();
13646         return_if_fail ( player );
13647
13648         if (player->factories)
13649         {
13650                 gst_plugin_feature_list_free (player->factories);
13651                 player->factories = NULL;
13652         }
13653
13654         MMPLAYER_FLEAVE();
13655 }
13656
13657 static void
13658 __mmplayer_release_misc(mm_player_t* player)
13659 {
13660         int i;
13661         gboolean cur_mode = player->set_mode.rich_audio;
13662         MMPLAYER_FENTER();
13663
13664         return_if_fail ( player );
13665
13666         player->use_video_stream = FALSE;
13667         player->video_stream_cb = NULL;
13668         player->video_stream_cb_user_param = NULL;
13669
13670         player->audio_stream_cb = NULL;
13671         player->audio_stream_render_cb_ex = NULL;
13672         player->audio_stream_cb_user_param = NULL;
13673         player->audio_stream_sink_sync = false;
13674
13675         player->video_stream_changed_cb = NULL;
13676         player->video_stream_changed_cb_user_param = NULL;
13677
13678         player->audio_stream_changed_cb = NULL;
13679         player->audio_stream_changed_cb_user_param = NULL;
13680
13681         player->sent_bos = FALSE;
13682         player->playback_rate = DEFAULT_PLAYBACK_RATE;
13683
13684         player->doing_seek = FALSE;
13685
13686         player->updated_bitrate_count = 0;
13687         player->total_bitrate = 0;
13688         player->updated_maximum_bitrate_count = 0;
13689         player->total_maximum_bitrate = 0;
13690
13691         player->not_found_demuxer = 0;
13692
13693         player->last_position = 0;
13694         player->duration = 0;
13695         player->http_content_size = 0;
13696         player->not_supported_codec = MISSING_PLUGIN_NONE;
13697         player->can_support_codec = FOUND_PLUGIN_NONE;
13698         player->pending_seek.is_pending = FALSE;
13699         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
13700         player->pending_seek.pos = 0;
13701         player->msg_posted = FALSE;
13702         player->has_many_types = FALSE;
13703         player->is_drm_file = FALSE;
13704         player->max_audio_channels = 0;
13705         player->video_share_api_delta = 0;
13706         player->video_share_clock_delta = 0;
13707         player->sm.keep_last_pos = FALSE;
13708         player->is_subtitle_force_drop = FALSE;
13709         player->play_subtitle = FALSE;
13710         player->use_textoverlay = FALSE;
13711         player->adjust_subtitle_pos = 0;
13712         player->last_multiwin_status = FALSE;
13713         player->has_closed_caption = FALSE;
13714         player->set_mode.media_packet_video_stream = FALSE;
13715
13716         memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
13717         /* recover mode */
13718         player->set_mode.rich_audio = cur_mode;
13719
13720         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
13721         {
13722                 player->bitrate[i] = 0;
13723                 player->maximum_bitrate[i] = 0;
13724         }
13725
13726         /* remove media stream cb (appsrc cb) */
13727         for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++)
13728         {
13729                 player->media_stream_buffer_status_cb[i] = NULL;
13730                 player->media_stream_seek_data_cb[i] = NULL;
13731         }
13732
13733         /* free memory related to audio effect */
13734         MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
13735
13736         if (player->state_tune_caps)
13737         {
13738                 gst_caps_unref(player->state_tune_caps);
13739                 player->state_tune_caps = NULL;
13740         }
13741
13742         if (player->video_cb_probe_id)
13743         {
13744                 GstPad *pad = NULL;
13745
13746                 pad = gst_element_get_static_pad (player->video_fakesink, "sink");
13747
13748                 if (pad) {
13749                         debug_log("release video probe\n");
13750
13751                         /* release audio callback */
13752                         gst_pad_remove_probe (pad, player->video_cb_probe_id);
13753                         player->video_cb_probe_id = 0;
13754                         player->video_stream_cb = NULL;
13755                         player->video_stream_cb_user_param = NULL;
13756                 }
13757         }
13758
13759         MMPLAYER_FLEAVE();
13760 }
13761
13762 static void
13763 __mmplayer_release_misc_post(mm_player_t* player)
13764 {
13765         char *original_uri = NULL;
13766         MMPLAYER_FENTER();
13767
13768         /* player->pipeline is already released before. */
13769
13770         return_if_fail ( player );
13771
13772         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
13773         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
13774
13775         /* clean found parsers */
13776         if (player->parsers)
13777         {
13778                 GList *parsers = player->parsers;
13779                 for ( ;parsers ; parsers = g_list_next(parsers))
13780                 {
13781                         gchar *name = parsers->data;
13782                         MMPLAYER_FREEIF(name);
13783                 }
13784                 g_list_free(player->parsers);
13785                 player->parsers = NULL;
13786         }
13787
13788         /* clean found audio decoders */
13789         if (player->audio_decoders)
13790         {
13791                 GList *a_dec = player->audio_decoders;
13792                 for ( ;a_dec ; a_dec = g_list_next(a_dec))
13793                 {
13794                         gchar *name = a_dec->data;
13795                         MMPLAYER_FREEIF(name);
13796                 }
13797                 g_list_free(player->audio_decoders);
13798                 player->audio_decoders = NULL;
13799         }
13800
13801         /* clean the uri list except original uri */
13802         if (player->uri_info.uri_list)
13803         {
13804                 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
13805
13806                 if (player->attrs)
13807                 {
13808                         mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
13809                         debug_log("restore original uri = %s\n", original_uri);
13810
13811                         if (mmf_attrs_commit(player->attrs))
13812                         {
13813                                 debug_error("failed to commit the original uri.\n");
13814                         }
13815                 }
13816
13817                 GList *uri_list = player->uri_info.uri_list;
13818                 for ( ;uri_list ; uri_list = g_list_next(uri_list))
13819                 {
13820                         gchar *uri = uri_list->data;
13821                         MMPLAYER_FREEIF(uri);
13822                 }
13823                 g_list_free(player->uri_info.uri_list);
13824                 player->uri_info.uri_list = NULL;
13825         }
13826
13827         player->uri_info.uri_idx = 0;
13828         player->src_changed = FALSE;
13829
13830         MMPLAYER_FLEAVE();
13831 }
13832
13833 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
13834 {
13835         GstElement *element = NULL;
13836         GstPad *sinkpad;
13837
13838         debug_log("creating %s to plug\n", name);
13839
13840         element = gst_element_factory_make(name, NULL);
13841         if ( ! element )
13842         {
13843                 debug_error("failed to create queue\n");
13844                 return NULL;
13845         }
13846
13847         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
13848         {
13849                 debug_error("failed to set state READY to %s\n", name);
13850                 gst_object_unref (element);
13851                 return NULL;
13852         }
13853
13854         if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
13855         {
13856                 debug_error("failed to add %s\n", name);
13857                 gst_object_unref (element);
13858                 return NULL;
13859         }
13860
13861         sinkpad = gst_element_get_static_pad(element, "sink");
13862
13863         if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
13864         {
13865                 debug_error("failed to link %s\n", name);
13866                 gst_object_unref (sinkpad);
13867                 gst_object_unref (element);
13868                 return NULL;
13869         }
13870
13871         debug_log("linked %s to pipeline successfully\n", name);
13872
13873         gst_object_unref (sinkpad);
13874
13875         return element;
13876 }
13877
13878 static gboolean
13879 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
13880 const char *padname, const GList *templlist)
13881 {
13882         GstPad *pad = NULL;
13883         gboolean has_dynamic_pads = FALSE;
13884         gboolean has_many_types = FALSE;
13885         const char *klass = NULL;
13886         GstStaticPadTemplate *padtemplate = NULL;
13887         GstElementFactory *factory = NULL;
13888         GstElement* queue = NULL;
13889         GstElement* parser = NULL;
13890         GstPad *pssrcpad = NULL;
13891         GstPad *qsrcpad = NULL, *qsinkpad = NULL;
13892         MMPlayerGstElement *mainbin = NULL;
13893         GstStructure* str = NULL;
13894         GstCaps* srccaps = NULL;
13895         GstState target_state = GST_STATE_READY;
13896         gboolean isvideo_decoder = FALSE;
13897         guint q_max_size_time = 0;
13898
13899         MMPLAYER_FENTER();
13900
13901         return_val_if_fail ( player &&
13902                 player->pipeline &&
13903                 player->pipeline->mainbin,
13904                 FALSE );
13905
13906         mainbin = player->pipeline->mainbin;
13907
13908         debug_log("plugging pad %s:%s to newly create %s:%s\n",
13909                         GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
13910                         GST_PAD_NAME( srcpad ),
13911                         GST_ELEMENT_NAME( sinkelement ),
13912                         padname);
13913
13914         factory = gst_element_get_factory(sinkelement);
13915         klass = gst_element_factory_get_klass(factory);
13916
13917         /* check if player can do start continually */
13918         MMPLAYER_CHECK_CMD_IF_EXIT(player);
13919
13920         /* need it to warm up omx before linking to pipeline */
13921         if (g_strrstr(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ), "demux"))
13922         {
13923                 debug_log("get demux caps.\n");
13924                 if (player->state_tune_caps)
13925                 {
13926                         gst_caps_unref(player->state_tune_caps);
13927                         player->state_tune_caps = NULL;
13928                 }
13929                 player->state_tune_caps = gst_caps_copy(gst_pad_get_current_caps(srcpad));
13930         }
13931
13932         /* NOTE : OMX Codec can check if resource is available or not at this state. */
13933         if (g_strrstr(GST_ELEMENT_NAME(sinkelement), "omx"))
13934         {
13935                 if (player->state_tune_caps != NULL)
13936                 {
13937                         debug_log("set demux's caps to omx codec if resource is available");
13938                         if (gst_pad_set_caps(gst_element_get_static_pad(sinkelement, "sink"), player->state_tune_caps))
13939                         {
13940                                 target_state = GST_STATE_PAUSED;
13941                                 isvideo_decoder = TRUE;
13942                                 g_object_set(G_OBJECT(sinkelement), "state-tuning", TRUE, NULL);
13943                         }
13944                         else
13945                         {
13946                                 debug_warning("failed to set caps for state tuning");
13947                         }
13948                 }
13949                 gst_caps_unref(player->state_tune_caps);
13950                 player->state_tune_caps = NULL;
13951         }
13952
13953         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, target_state) )
13954         {
13955                 debug_error("failed to set %d state to %s\n", target_state, GST_ELEMENT_NAME( sinkelement ));
13956                 if (isvideo_decoder)
13957                 {
13958                         gst_element_set_state(sinkelement, GST_STATE_NULL);
13959                         gst_object_unref(G_OBJECT(sinkelement));
13960                         player->keep_detecting_vcodec = TRUE;
13961                 }
13962                 goto ERROR;
13963         }
13964
13965         /* add to pipeline */
13966         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
13967         {
13968                 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
13969                 goto ERROR;
13970         }
13971
13972         debug_log("element klass : %s\n", klass);
13973
13974         /* added to support multi track files */
13975         /* only decoder case and any of the video/audio still need to link*/
13976         if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
13977         {
13978                 gchar *name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
13979
13980                 if (g_strrstr(name, "mpegtsdemux")|| g_strrstr(name, SMOOTH_STREAMING_DEMUX))
13981                 {
13982                         gchar *src_demux_caps_str = NULL;
13983                         gchar *needed_parser = NULL;
13984                         GstCaps *src_demux_caps = NULL;
13985                         gboolean smooth_streaming = FALSE;
13986
13987                         src_demux_caps = gst_pad_query_caps(srcpad, NULL);
13988                         src_demux_caps_str = gst_caps_to_string(src_demux_caps);
13989
13990                         gst_caps_unref(src_demux_caps);
13991
13992                         if (g_strrstr(src_demux_caps_str, "video/x-h264"))
13993                         {
13994                                 if (g_strrstr(name, SMOOTH_STREAMING_DEMUX))
13995                                 {
13996                                         needed_parser = g_strdup("legacyh264parse");
13997                                         smooth_streaming = TRUE;
13998                                 }
13999                                 else
14000                                 {
14001                                         needed_parser = g_strdup("h264parse");
14002                                 }
14003                         }
14004                         else if (g_strrstr(src_demux_caps_str, "video/mpeg"))
14005                         {
14006                                 needed_parser = g_strdup("mpeg4videoparse");
14007                         }
14008                         MMPLAYER_FREEIF(src_demux_caps_str);
14009
14010                         if (needed_parser)
14011                         {
14012                                 parser = __mmplayer_element_create_and_link(player, srcpad, needed_parser);
14013                                 MMPLAYER_FREEIF(needed_parser);
14014
14015                                 if ( !parser )
14016                                 {
14017                                         debug_error("failed to create parser\n");
14018                                 }
14019                                 else
14020                                 {
14021                                         if (smooth_streaming)
14022                                         {
14023                                                 g_object_set (parser, "output-format", 1, NULL); /* NALU/Byte Stream format */
14024                                         }
14025
14026                                         /* update srcpad if parser is created */
14027                                         pssrcpad = gst_element_get_static_pad(parser, "src");
14028                                         srcpad = pssrcpad;
14029                                 }
14030                         }
14031                 }
14032                 MMPLAYER_FREEIF(name);
14033
14034                 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
14035                 if ( ! queue )
14036                 {
14037                         debug_error("failed to create queue\n");
14038                         goto ERROR;
14039                 }
14040
14041                 /* update srcpad to link with decoder */
14042                 qsrcpad = gst_element_get_static_pad(queue, "src");
14043                 srcpad = qsrcpad;
14044
14045                 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
14046
14047                 /* assigning queue handle for futher manipulation purpose */
14048                 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
14049                 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
14050                 {
14051                         mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
14052                         mainbin[MMPLAYER_M_Q1].gst = queue;
14053
14054                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
14055                         {
14056                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", 0 , NULL);
14057                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-buffers", 2, NULL);
14058                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-bytes", 0, NULL);
14059                         }
14060                         else
14061                         {
14062                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
14063                                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
14064                         }
14065                 }
14066                 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
14067                 {
14068                         mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
14069                         mainbin[MMPLAYER_M_Q2].gst = queue;
14070
14071                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
14072                         {
14073                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", 0 , NULL);
14074                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-buffers", 2, NULL);
14075                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-bytes", 0, NULL);
14076                         }
14077                         else
14078                         {
14079                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
14080                                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
14081                         }
14082                 }
14083                 else
14084                 {
14085                         debug_error("Not supporting more then two elementary stream\n");
14086                         g_assert(1);
14087                 }
14088
14089                 pad = gst_element_get_static_pad(sinkelement, padname);
14090
14091                 if ( ! pad )
14092                 {
14093                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
14094                                 padname, GST_ELEMENT_NAME(sinkelement) );
14095
14096                         pad = gst_element_get_static_pad(sinkelement, "sink");
14097                         if ( ! pad )
14098                         {
14099                                 debug_error("failed to get pad(sink) from %s. \n",
14100                                 GST_ELEMENT_NAME(sinkelement) );
14101                                 goto ERROR;
14102                         }
14103                 }
14104
14105                 /*  to check the video/audio type set the proper flag*/
14106                 const gchar *mime_type = NULL;
14107                 {
14108                         srccaps = gst_pad_query_caps(srcpad, NULL);
14109                         if ( !srccaps )
14110                                 goto ERROR;
14111
14112                         str = gst_caps_get_structure( srccaps, 0 );
14113                         if ( ! str )
14114                                 goto ERROR;
14115
14116                         mime_type = gst_structure_get_name(str);
14117                         if ( ! mime_type )
14118                                 goto ERROR;
14119                 }
14120
14121                 /* link queue and decoder. so, it will be queue - decoder. */
14122                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
14123                 {
14124                         gst_object_unref(GST_OBJECT(pad));
14125                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
14126
14127                         /* reconstitute supportable codec */
14128                         if (strstr(mime_type, "video"))
14129                         {
14130                                 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
14131                         }
14132                         else if (strstr(mime_type, "audio"))
14133                         {
14134                                 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
14135                         }
14136                         goto ERROR;
14137                 }
14138
14139                 if (strstr(mime_type, "video"))
14140                 {
14141                         player->videodec_linked = 1;
14142                         debug_msg("player->videodec_linked set to 1\n");
14143
14144                 }
14145                 else if (strstr(mime_type, "audio"))
14146                 {
14147                         player->audiodec_linked = 1;
14148                         debug_msg("player->auddiodec_linked set to 1\n");
14149                 }
14150
14151                 gst_object_unref(GST_OBJECT(pad));
14152                 gst_caps_unref(GST_CAPS(srccaps));
14153                 srccaps = NULL;
14154         }
14155
14156         if ( !MMPLAYER_IS_HTTP_PD(player) )
14157         {
14158                 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
14159                 {
14160                         if (MMPLAYER_IS_HTTP_STREAMING(player))
14161                         {
14162                                 gint64 dur_bytes = 0L;
14163                                 gchar *file_buffering_path = NULL;
14164                                 gboolean use_file_buffer = FALSE;
14165
14166                                 if ( !mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
14167                                 {
14168                                         debug_log("creating http streaming buffering queue\n");
14169
14170                                         queue = gst_element_factory_make("queue2", "queue2");
14171                                         if ( ! queue )
14172                                         {
14173                                                 debug_error ( "failed to create buffering queue element\n" );
14174                                                 goto ERROR;
14175                                         }
14176
14177                                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
14178                                         {
14179                                                 debug_error("failed to set state READY to buffering queue\n");
14180                                                 goto ERROR;
14181                                         }
14182
14183                                         if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
14184                                         {
14185                                                 debug_error("failed to add buffering queue\n");
14186                                                 goto ERROR;
14187                                         }
14188
14189                                         qsinkpad = gst_element_get_static_pad(queue, "sink");
14190                                         qsrcpad = gst_element_get_static_pad(queue, "src");
14191
14192                                         if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
14193                                         {
14194                                                 debug_error("failed to link buffering queue\n");
14195                                                 goto ERROR;
14196                                         }
14197                                         srcpad = qsrcpad;
14198
14199
14200                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
14201                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue;
14202
14203                                         if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
14204                                         {
14205                                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
14206                                                         debug_error("fail to get duration.\n");
14207
14208                                                 if (dur_bytes > 0)
14209                                                 {
14210                                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
14211                                                         file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
14212                                                 }
14213                                                 else
14214                                                 {
14215                                                         dur_bytes = 0;
14216                                                 }
14217                                         }
14218
14219                                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
14220                                         if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
14221                                         {
14222                                                 __mm_player_streaming_set_queue2(player->streamer,
14223                                                         queue,
14224                                                         TRUE,
14225                                                         player->ini.http_max_size_bytes,
14226                                                         player->ini.http_buffering_time,
14227                                                         1.0,
14228                                                         player->ini.http_buffering_limit,
14229                                                         use_file_buffer,
14230                                                         file_buffering_path,
14231                                                         (guint64)dur_bytes);
14232                                         }
14233
14234                                         MMPLAYER_FREEIF(file_buffering_path);
14235                                 }
14236                         }
14237                 }
14238         }
14239         /* if it is not decoder or */
14240         /* in decoder case any of the video/audio still need to link*/
14241         if(!g_strrstr(klass, "Decoder"))
14242         {
14243
14244                 pad = gst_element_get_static_pad(sinkelement, padname);
14245                 if ( ! pad )
14246                 {
14247                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
14248                                         padname, GST_ELEMENT_NAME(sinkelement) );
14249
14250                         pad = gst_element_get_static_pad(sinkelement, "sink");
14251
14252                         if ( ! pad )
14253                         {
14254                                 debug_error("failed to get pad(sink) from %s. \n",
14255                                         GST_ELEMENT_NAME(sinkelement) );
14256                                 goto ERROR;
14257                         }
14258                 }
14259
14260                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
14261                 {
14262                         gst_object_unref(GST_OBJECT(pad));
14263                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
14264                         goto ERROR;
14265                 }
14266
14267                 gst_object_unref(GST_OBJECT(pad));
14268         }
14269
14270         for(;templlist != NULL; templlist = templlist->next)
14271         {
14272                 padtemplate = templlist->data;
14273
14274                 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
14275
14276                 if(     padtemplate->direction != GST_PAD_SRC ||
14277                         padtemplate->presence == GST_PAD_REQUEST        )
14278                         continue;
14279
14280                 switch(padtemplate->presence)
14281                 {
14282                         case GST_PAD_ALWAYS:
14283                         {
14284                                 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
14285                                 GstCaps *caps = gst_pad_query_caps(srcpad, NULL);
14286
14287                                 /* Check whether caps has many types */
14288                                 if ( !gst_caps_is_fixed(caps))
14289                                 {
14290                                         debug_log ("always pad but, caps has many types");
14291                                         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
14292                                         has_many_types = TRUE;
14293                                         break;
14294                                 }
14295
14296                                 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
14297                                 {
14298                                         gst_object_unref(GST_OBJECT(srcpad));
14299                                         gst_caps_unref(GST_CAPS(caps));
14300
14301                                         debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
14302                                         goto ERROR;
14303                                 }
14304
14305                                 gst_caps_unref(GST_CAPS(caps));
14306                                 gst_object_unref(GST_OBJECT(srcpad));
14307
14308                         }
14309                         break;
14310
14311
14312                         case GST_PAD_SOMETIMES:
14313                                 has_dynamic_pads = TRUE;
14314                         break;
14315
14316                         default:
14317                                 break;
14318                 }
14319         }
14320
14321         /* check if player can do start continually */
14322         MMPLAYER_CHECK_CMD_IF_EXIT(player);
14323
14324         if( has_dynamic_pads )
14325         {
14326                 player->have_dynamic_pad = TRUE;
14327                 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
14328                         G_CALLBACK(__mmplayer_add_new_pad), player);
14329
14330                 /* for streaming, more then one typefind will used for each elementary stream
14331                  * so this doesn't mean the whole pipeline completion
14332                  */
14333                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
14334                 {
14335                         MMPLAYER_SIGNAL_CONNECT( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
14336                                 G_CALLBACK(__mmplayer_pipeline_complete), player);
14337                 }
14338         }
14339
14340         if (has_many_types)
14341         {
14342                 GstPad *pad = NULL;
14343
14344                 player->has_many_types = has_many_types;
14345
14346                 pad = gst_element_get_static_pad(sinkelement, "src");
14347                 MMPLAYER_SIGNAL_CONNECT (player, pad, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
14348                 gst_object_unref (GST_OBJECT(pad));
14349         }
14350
14351
14352         /* check if player can do start continually */
14353         MMPLAYER_CHECK_CMD_IF_EXIT(player);
14354
14355         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
14356         {
14357                 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
14358                 goto ERROR;
14359         }
14360
14361         if ( queue )
14362         {
14363                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
14364                 {
14365                         debug_error("failed to set state PAUSED to queue\n");
14366                         goto ERROR;
14367                 }
14368
14369                 queue = NULL;
14370
14371                 gst_object_unref (GST_OBJECT(qsrcpad));
14372                 qsrcpad = NULL;
14373         }
14374
14375         if ( parser )
14376         {
14377                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
14378                 {
14379                         debug_error("failed to set state PAUSED to queue\n");
14380                         goto ERROR;
14381                 }
14382
14383                 parser = NULL;
14384
14385                 gst_object_unref (GST_OBJECT(pssrcpad));
14386                 pssrcpad = NULL;
14387         }
14388
14389         MMPLAYER_FLEAVE();
14390
14391         return TRUE;
14392
14393 ERROR:
14394
14395         if ( queue )
14396         {
14397                 gst_object_unref(GST_OBJECT(qsrcpad));
14398
14399                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
14400                  * You need to explicitly set elements to the NULL state before
14401                  * dropping the final reference, to allow them to clean up.
14402                  */
14403                 gst_element_set_state(queue, GST_STATE_NULL);
14404                 /* And, it still has a parent "player".
14405                  * You need to let the parent manage the object instead of unreffing the object directly.
14406                  */
14407
14408                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
14409                 //gst_object_unref( queue );
14410         }
14411
14412         if ( srccaps )
14413                 gst_caps_unref(GST_CAPS(srccaps));
14414
14415     return FALSE;
14416 }
14417
14418 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
14419 {
14420         const gchar *klass;
14421         //const gchar *name;
14422
14423         /* we only care about element factories */
14424         if (!GST_IS_ELEMENT_FACTORY(feature))
14425                 return FALSE;
14426
14427         /* only parsers, demuxers and decoders */
14428         klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
14429         //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
14430
14431         if( g_strrstr(klass, "Demux") == NULL &&
14432                 g_strrstr(klass, "Codec/Decoder") == NULL &&
14433                 g_strrstr(klass, "Depayloader") == NULL &&
14434                 g_strrstr(klass, "Parse") == NULL)
14435         {
14436                 return FALSE;
14437         }
14438     return TRUE;
14439 }
14440
14441
14442 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
14443 {
14444         mm_player_t* player = (mm_player_t*) data;
14445         GstCaps *caps = NULL;
14446         GstStructure *str = NULL;
14447         const char *name;
14448
14449         MMPLAYER_FENTER();
14450
14451         return_if_fail ( pad )
14452         return_if_fail ( unused )
14453         return_if_fail ( data )
14454
14455         caps = gst_pad_query_caps(pad, NULL);
14456         if ( !caps )
14457                 return;
14458
14459         str = gst_caps_get_structure(caps, 0);
14460         if ( !str )
14461                 return;
14462
14463         name = gst_structure_get_name(str);
14464         if ( !name )
14465                 return;
14466         debug_log("name=%s\n", name);
14467
14468         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
14469         {
14470                 debug_error("failed to autoplug for type (%s)\n", name);
14471                 gst_caps_unref(caps);
14472                 return;
14473         }
14474
14475         gst_caps_unref(caps);
14476
14477         __mmplayer_pipeline_complete( NULL, (gpointer)player );
14478
14479         MMPLAYER_FLEAVE();
14480
14481         return;
14482 }
14483
14484 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
14485 {
14486         GstStructure *str;
14487         gint version = 0;
14488         const char *stream_type;
14489         gchar *version_field = NULL;
14490
14491         MMPLAYER_FENTER();
14492
14493         return_if_fail ( player );
14494         return_if_fail ( caps );
14495
14496         str = gst_caps_get_structure(caps, 0);
14497         if ( !str )
14498                 return;
14499
14500         stream_type = gst_structure_get_name(str);
14501         if ( !stream_type )
14502                 return;
14503
14504
14505         /* set unlinked mime type for downloadable codec */
14506         if (g_str_has_prefix(stream_type, "video/"))
14507         {
14508                 if (g_str_has_prefix(stream_type, "video/mpeg"))
14509                 {
14510                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
14511                         version_field = MM_PLAYER_MPEG_VNAME;
14512                 }
14513                 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
14514                 {
14515                         gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
14516                         version_field = MM_PLAYER_WMV_VNAME;
14517
14518                 }
14519                 else if (g_str_has_prefix(stream_type, "video/x-divx"))
14520                 {
14521                         gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
14522                         version_field = MM_PLAYER_DIVX_VNAME;
14523                 }
14524
14525                 if (version)
14526                 {
14527                         player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
14528                 }
14529                 else
14530                 {
14531                         player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
14532                 }
14533         }
14534         else if (g_str_has_prefix(stream_type, "audio/"))
14535         {
14536                 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
14537                 {
14538                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
14539                         version_field = MM_PLAYER_MPEG_VNAME;
14540                 }
14541                 else if (g_str_has_prefix(stream_type, "audio/x-wma"))
14542                 {
14543                         gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
14544                         version_field = MM_PLAYER_WMA_VNAME;
14545                 }
14546
14547                 if (version)
14548                 {
14549                         player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
14550                 }
14551                 else
14552                 {
14553                         player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
14554                 }
14555         }
14556
14557         MMPLAYER_FLEAVE();
14558 }
14559
14560 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
14561 {
14562         mm_player_t* player = (mm_player_t*) data;
14563         GstCaps *caps = NULL;
14564         GstStructure *str = NULL;
14565         const char *name;
14566
14567         MMPLAYER_FENTER();
14568         return_if_fail ( player );
14569         return_if_fail ( pad );
14570
14571         GST_OBJECT_LOCK (pad);
14572         if ((caps = gst_pad_get_current_caps(pad)))
14573                 gst_caps_ref(caps);
14574         GST_OBJECT_UNLOCK (pad);
14575
14576         if ( NULL == caps )
14577         {
14578                 caps = gst_pad_query_caps(pad, NULL);
14579                 if ( !caps ) return;
14580         }
14581
14582         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
14583
14584         str = gst_caps_get_structure(caps, 0);
14585         if ( !str )
14586                 return;
14587
14588         name = gst_structure_get_name(str);
14589         if ( !name )
14590                 return;
14591
14592         player->num_dynamic_pad++;
14593         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
14594
14595         /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
14596           *     If want to play it, remove this code.
14597           */
14598         if (g_strrstr(name, "application"))
14599         {
14600                 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
14601                 {
14602                         /* If id3/ape tag comes, keep going */
14603                         debug_log("application mime exception : id3/ape tag");
14604                 }
14605                 else
14606                 {
14607                         /* Otherwise, we assume that this stream is subtile. */
14608                         debug_log(" application mime type pad is closed.");
14609                         return;
14610                 }
14611         }
14612         else if (g_strrstr(name, "audio"))
14613         {
14614                 gint samplerate = 0, channels = 0;
14615
14616                 if (player->audiodec_linked)
14617                 {
14618                         gst_caps_unref(caps);
14619                         debug_log("multi tracks. skip to plug");
14620                         return;
14621                 }
14622
14623                 /* set stream information */
14624                 /* if possible, set it here because the caps is not distrubed by resampler. */
14625                 gst_structure_get_int (str, "rate", &samplerate);
14626                 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
14627
14628                 gst_structure_get_int (str, "channels", &channels);
14629                 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
14630
14631                 debug_log("audio samplerate : %d        channels : %d", samplerate, channels);
14632         }
14633         else if (g_strrstr(name, "video"))
14634         {
14635                 gint stype;
14636                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
14637
14638                 /* don't make video because of not required */
14639                 if (stype == MM_DISPLAY_SURFACE_NULL)
14640                 {
14641                         debug_log("no video because it's not required");
14642                         return;
14643                 }
14644
14645                 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
14646         }
14647
14648         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
14649         {
14650                 debug_error("failed to autoplug for type (%s)", name);
14651
14652                 __mmplayer_set_unlinked_mime_type(player, caps);
14653         }
14654
14655         gst_caps_unref(caps);
14656
14657         MMPLAYER_FLEAVE();
14658         return;
14659 }
14660
14661 /* test API for tuning audio gain. this API should be
14662  * deprecated before the day of final release
14663  */
14664 int
14665 _mmplayer_set_volume_tune(MMHandleType hplayer, MMPlayerVolumeType volume)
14666 {
14667         mm_player_t* player = (mm_player_t*) hplayer;
14668         gint error = MM_ERROR_NONE;
14669         gint vol_max = 0;
14670         gboolean isMidi = FALSE;
14671         gint i = 0;
14672
14673         MMPLAYER_FENTER();
14674
14675         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14676         return_val_if_fail( player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED )
14677
14678         debug_log("clip type=%d(1-midi, 0-others), volume [L]=%d:[R]=%d\n",
14679                 player->profile.play_mode, volume.level[0], volume.level[1]);
14680
14681         isMidi = ( player->profile.play_mode == MM_PLAYER_MODE_MIDI ) ? TRUE : FALSE;
14682
14683         if ( isMidi )
14684                 vol_max = 1000;
14685         else
14686                 vol_max = 100;
14687
14688         /* is it proper volume level? */
14689         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; ++i)
14690         {
14691                 if (volume.level[i] < 0 || volume.level[i] > vol_max) {
14692                         debug_log("Invalid Volume level!!!! \n");
14693                         return MM_ERROR_INVALID_ARGUMENT;
14694                 }
14695         }
14696
14697         if ( isMidi )
14698         {
14699                 if ( player->pipeline->mainbin )
14700                 {
14701                         GstElement *midi_element = player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst;
14702
14703                         if ( midi_element && ( strstr(GST_ELEMENT_NAME(midi_element), "midiparse")) )
14704                         {
14705                                 debug_log("setting volume (%d) level to midi plugin\n", volume.level[0]);
14706
14707                                 g_object_set(midi_element, "volume", volume.level[0], NULL);
14708                         }
14709                 }
14710         }
14711         else
14712         {
14713                 if ( player->pipeline->audiobin )
14714                 {
14715                         GstElement *sink_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
14716
14717                         /* Set to Avsysaudiosink element */
14718                         if ( sink_element )
14719                         {
14720                                 gint vol_value = 0;
14721                                 gboolean mute = FALSE;
14722                                 vol_value = volume.level[0];
14723
14724                                 g_object_set(G_OBJECT(sink_element), "tuningvolume", vol_value, NULL);
14725
14726                                 mute = (vol_value == 0)? TRUE:FALSE;
14727
14728                                 g_object_set(G_OBJECT(sink_element), "mute", mute, NULL);
14729                         }
14730
14731                 }
14732         }
14733
14734         MMPLAYER_FLEAVE();
14735
14736         return error;
14737 }
14738
14739 gboolean
14740 __mmplayer_dump_pipeline_state( mm_player_t* player )
14741 {
14742         GstIterator*iter = NULL;
14743         gboolean done = FALSE;
14744
14745         GValue item = {0, };
14746         GstElement *element = NULL;
14747         GstElementFactory *factory = NULL;
14748
14749         GstState state = GST_STATE_VOID_PENDING;
14750         GstState pending = GST_STATE_VOID_PENDING;
14751         GstClockTime time = 200*GST_MSECOND;
14752
14753         MMPLAYER_FENTER();
14754
14755         return_val_if_fail ( player &&
14756                 player->pipeline &&
14757                 player->pipeline->mainbin,
14758                 FALSE );
14759
14760         iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) );
14761
14762         if ( iter != NULL )
14763         {
14764                 while (!done) {
14765                          switch ( gst_iterator_next (iter, &item) )
14766                          {
14767                            case GST_ITERATOR_OK:
14768                                 element = g_value_get_object(&item);
14769                                 gst_element_get_state(element,&state, &pending,time);
14770
14771                                 factory = gst_element_get_factory (element) ;
14772                                 if (factory)
14773                                 {
14774                                         debug_error("%s:%s : From:%s To:%s   refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(element) ,
14775                                                 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(element));
14776                                 }
14777                                  g_value_reset (&item);
14778                                  break;
14779                            case GST_ITERATOR_RESYNC:
14780                                  gst_iterator_resync (iter);
14781                                  break;
14782                            case GST_ITERATOR_ERROR:
14783                                  done = TRUE;
14784                                  break;
14785                            case GST_ITERATOR_DONE:
14786                                  done = TRUE;
14787                                  break;
14788                          }
14789                 }
14790         }
14791
14792         element = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
14793
14794         gst_element_get_state(element,&state, &pending,time);
14795
14796         factory = gst_element_get_factory (element) ;
14797
14798         if (factory)
14799         {
14800                 debug_error("%s:%s : From:%s To:%s  refcount : %d\n",
14801                         GST_OBJECT_NAME(factory),
14802                         GST_ELEMENT_NAME(element),
14803                         gst_element_state_get_name(state),
14804                         gst_element_state_get_name(pending),
14805                         GST_OBJECT_REFCOUNT_VALUE(element) );
14806         }
14807
14808         g_value_unset(&item);
14809
14810         if ( iter )
14811                 gst_iterator_free (iter);
14812
14813         MMPLAYER_FLEAVE();
14814
14815         return FALSE;
14816 }
14817
14818
14819 gboolean
14820 __mmplayer_check_subtitle( mm_player_t* player )
14821 {
14822         MMHandleType attrs = 0;
14823         char *subtitle_uri = NULL;
14824
14825         MMPLAYER_FENTER();
14826
14827         return_val_if_fail( player, FALSE );
14828
14829         /* get subtitle attribute */
14830         attrs = MMPLAYER_GET_ATTRS(player);
14831         if ( !attrs )
14832                 return FALSE;
14833
14834         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
14835         if ( !subtitle_uri || !strlen(subtitle_uri))
14836                 return FALSE;
14837
14838         debug_log ("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
14839         player->is_external_subtitle_present = TRUE;
14840
14841         MMPLAYER_FLEAVE();
14842
14843         return TRUE;
14844 }
14845
14846 static gboolean
14847 __mmplayer_can_extract_pcm( mm_player_t* player )
14848 {
14849         MMHandleType attrs = 0;
14850         gboolean is_drm = FALSE;
14851         gboolean sound_extraction = FALSE;
14852
14853         return_val_if_fail ( player, FALSE );
14854
14855         attrs = MMPLAYER_GET_ATTRS(player);
14856         if ( !attrs )
14857         {
14858                 debug_error("fail to get attributes.");
14859                 return FALSE;
14860         }
14861
14862         /* check file is drm or not */
14863         if (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm"))
14864                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
14865
14866         /* get sound_extraction property */
14867         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
14868
14869         if ( ! sound_extraction || is_drm )
14870         {
14871                 debug_log("checking pcm extraction mode : %d, drm : %d", sound_extraction, is_drm);
14872                 return FALSE;
14873         }
14874
14875         return TRUE;
14876 }
14877
14878 static gboolean
14879 __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error )
14880 {
14881         MMMessageParamType msg_param;
14882         gchar *msg_src_element;
14883
14884         MMPLAYER_FENTER();
14885
14886         return_val_if_fail( player, FALSE );
14887         return_val_if_fail( error, FALSE );
14888
14889         /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
14890
14891         memset (&msg_param, 0, sizeof(MMMessageParamType));
14892
14893         if ( error->domain == GST_CORE_ERROR )
14894         {
14895                 msg_param.code = __gst_handle_core_error( player, error->code );
14896         }
14897         else if ( error->domain == GST_LIBRARY_ERROR )
14898         {
14899                 msg_param.code = __gst_handle_library_error( player, error->code );
14900         }
14901         else if ( error->domain == GST_RESOURCE_ERROR )
14902         {
14903                 msg_param.code = __gst_handle_resource_error( player, error->code );
14904         }
14905         else if ( error->domain == GST_STREAM_ERROR )
14906         {
14907                 msg_param.code = __gst_handle_stream_error( player, error, message );
14908         }
14909         else
14910         {
14911                 debug_warning("This error domain is not defined.\n");
14912
14913                 /* we treat system error as an internal error */
14914                 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
14915         }
14916
14917         if ( message->src )
14918         {
14919                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
14920
14921                 msg_param.data = (void *) error->message;
14922
14923                 debug_error("-Msg src : [%s]    Domain : [%s]   Error : [%s]  Code : [%d] is tranlated to error code : [0x%x]\n",
14924                         msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg_param.code);
14925         }
14926
14927         /* no error */
14928         if (msg_param.code == MM_ERROR_NONE)
14929                 return TRUE;
14930
14931         /* post error to application */
14932         if ( ! player->msg_posted )
14933         {
14934                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
14935                 /* don't post more if one was sent already */
14936                 player->msg_posted = TRUE;
14937         }
14938         else
14939         {
14940                 debug_log("skip error post because it's sent already.\n");
14941         }
14942
14943         MMPLAYER_FLEAVE();
14944
14945         return TRUE;
14946 }
14947
14948 static gboolean
14949 __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message )
14950 {
14951         debug_log("\n");
14952         MMMessageParamType msg_param;
14953         gchar *msg_src_element = NULL;
14954         GstStructure *s = NULL;
14955         guint error_id = 0;
14956         gchar *error_string = NULL;
14957
14958         MMPLAYER_FENTER();
14959
14960         return_val_if_fail ( player, FALSE );
14961         return_val_if_fail ( message, FALSE );
14962
14963         s = malloc( sizeof(GstStructure) );
14964         memcpy ( s, gst_message_get_structure ( message ), sizeof(GstStructure));
14965
14966         if ( !gst_structure_get_uint (s, "error_id", &error_id) )
14967                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
14968
14969         switch ( error_id )
14970         {
14971                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
14972                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
14973                         break;
14974                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
14975                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
14976                         break;
14977                 case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
14978                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
14979                         break;
14980                 case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
14981                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
14982                         break;
14983                 case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
14984                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
14985                         break;
14986                 case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
14987                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
14988                         break;
14989                 case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
14990                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
14991                         break;
14992                 case MMPLAYER_STREAMING_ERROR_INVALID_URL:
14993                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
14994                         break;
14995                 case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
14996                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
14997                         break;
14998                 case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
14999                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
15000                         break;
15001                 case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
15002                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
15003                         break;
15004                 case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
15005                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
15006                         break;
15007                 case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
15008                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
15009                         break;
15010                 case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
15011                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
15012                         break;
15013                 case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
15014                         msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
15015                         break;
15016                 case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
15017                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
15018                         break;
15019                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
15020                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
15021                         break;
15022                 case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
15023                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
15024                         break;
15025                 case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
15026                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
15027                         break;
15028                 case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
15029                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
15030                         break;
15031                 case MMPLAYER_STREAMING_ERROR_GONE:
15032                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
15033                         break;
15034                 case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
15035                         msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
15036                         break;
15037                 case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
15038                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
15039                         break;
15040                 case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
15041                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
15042                         break;
15043                 case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
15044                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
15045                         break;
15046                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
15047                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
15048                         break;
15049                 case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
15050                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
15051                         break;
15052                 case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
15053                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
15054                         break;
15055                 case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
15056                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
15057                         break;
15058                 case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
15059                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
15060                         break;
15061                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
15062                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
15063                         break;
15064                 case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
15065                         msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
15066                         break;
15067                 case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
15068                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
15069                         break;
15070                 case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
15071                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
15072                         break;
15073                 case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
15074                         msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
15075                         break;
15076                 case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
15077                         msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
15078                         break;
15079                 case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
15080                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
15081                         break;
15082                 case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
15083                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
15084                         break;
15085                 case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
15086                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
15087                         break;
15088                 case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
15089                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
15090                         break;
15091                 case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
15092                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
15093                         break;
15094                 case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
15095                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
15096                         break;
15097                 case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
15098                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
15099                         break;
15100                 case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
15101                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
15102                         break;
15103                 case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
15104                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
15105                         break;
15106                 default:
15107                         {
15108                                 MMPLAYER_FREEIF(s);
15109                                 return MM_ERROR_PLAYER_STREAMING_FAIL;
15110                         }
15111         }
15112
15113         error_string = g_strdup(gst_structure_get_string (s, "error_string"));
15114         if ( error_string )
15115                 msg_param.data = (void *) error_string;
15116
15117         if ( message->src )
15118         {
15119                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
15120
15121                 debug_error("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
15122                         msg_src_element, msg_param.code, (char*)msg_param.data );
15123         }
15124
15125         /* post error to application */
15126         if ( ! player->msg_posted )
15127         {
15128                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
15129
15130                 /* don't post more if one was sent already */
15131                 player->msg_posted = TRUE;
15132         }
15133         else
15134         {
15135                 debug_log("skip error post because it's sent already.\n");
15136         }
15137
15138         MMPLAYER_FREEIF(s);
15139         MMPLAYER_FLEAVE();
15140         g_free(error_string);
15141
15142         return TRUE;
15143
15144 }
15145
15146 static gint
15147 __gst_handle_core_error( mm_player_t* player, int code )
15148 {
15149         gint trans_err = MM_ERROR_NONE;
15150
15151         MMPLAYER_FENTER();
15152
15153         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15154
15155         switch ( code )
15156         {
15157                 case GST_CORE_ERROR_MISSING_PLUGIN:
15158                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15159                 case GST_CORE_ERROR_STATE_CHANGE:
15160                 case GST_CORE_ERROR_SEEK:
15161                 case GST_CORE_ERROR_NOT_IMPLEMENTED:
15162                 case GST_CORE_ERROR_FAILED:
15163                 case GST_CORE_ERROR_TOO_LAZY:
15164                 case GST_CORE_ERROR_PAD:
15165                 case GST_CORE_ERROR_THREAD:
15166                 case GST_CORE_ERROR_NEGOTIATION:
15167                 case GST_CORE_ERROR_EVENT:
15168                 case GST_CORE_ERROR_CAPS:
15169                 case GST_CORE_ERROR_TAG:
15170                 case GST_CORE_ERROR_CLOCK:
15171                 case GST_CORE_ERROR_DISABLED:
15172                 default:
15173                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
15174                 break;
15175         }
15176
15177         MMPLAYER_FLEAVE();
15178
15179         return trans_err;
15180 }
15181
15182 static gint
15183 __gst_handle_library_error( mm_player_t* player, int code )
15184 {
15185         gint trans_err = MM_ERROR_NONE;
15186
15187         MMPLAYER_FENTER();
15188
15189         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15190
15191         switch ( code )
15192         {
15193                 case GST_LIBRARY_ERROR_FAILED:
15194                 case GST_LIBRARY_ERROR_TOO_LAZY:
15195                 case GST_LIBRARY_ERROR_INIT:
15196                 case GST_LIBRARY_ERROR_SHUTDOWN:
15197                 case GST_LIBRARY_ERROR_SETTINGS:
15198                 case GST_LIBRARY_ERROR_ENCODE:
15199                 default:
15200                         trans_err =  MM_ERROR_PLAYER_INVALID_STREAM;
15201                 break;
15202         }
15203
15204         MMPLAYER_FLEAVE();
15205
15206         return trans_err;
15207 }
15208
15209
15210 static gint
15211 __gst_handle_resource_error( mm_player_t* player, int code )
15212 {
15213         gint trans_err = MM_ERROR_NONE;
15214
15215         MMPLAYER_FENTER();
15216
15217         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15218
15219         switch ( code )
15220         {
15221                 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
15222                         trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
15223                         break;
15224                 case GST_RESOURCE_ERROR_NOT_FOUND:
15225                 case GST_RESOURCE_ERROR_OPEN_READ:
15226                         if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
15227                                 || MMPLAYER_IS_RTSP_STREAMING(player))
15228                         {
15229                                 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
15230                                 break;
15231                         }
15232                 case GST_RESOURCE_ERROR_READ:
15233                         if ( MMPLAYER_IS_HTTP_STREAMING(player) ||  MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
15234                                 || MMPLAYER_IS_RTSP_STREAMING(player))
15235                         {
15236                                 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
15237                                 break;
15238                         }
15239                 case GST_RESOURCE_ERROR_WRITE:
15240                 case GST_RESOURCE_ERROR_FAILED:
15241                 case GST_RESOURCE_ERROR_SEEK:
15242                 case GST_RESOURCE_ERROR_TOO_LAZY:
15243                 case GST_RESOURCE_ERROR_BUSY:
15244                 case GST_RESOURCE_ERROR_OPEN_WRITE:
15245                 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
15246                 case GST_RESOURCE_ERROR_CLOSE:
15247                 case GST_RESOURCE_ERROR_SYNC:
15248                 case GST_RESOURCE_ERROR_SETTINGS:
15249                 default:
15250                         trans_err = MM_ERROR_PLAYER_INTERNAL;
15251                 break;
15252         }
15253
15254         MMPLAYER_FLEAVE();
15255
15256         return trans_err;
15257 }
15258
15259
15260 static gint
15261 __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message )
15262 {
15263         gint trans_err = MM_ERROR_NONE;
15264
15265         MMPLAYER_FENTER();
15266
15267         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15268         return_val_if_fail( error, MM_ERROR_INVALID_ARGUMENT );
15269         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
15270
15271         switch ( error->code )
15272         {
15273                 case GST_STREAM_ERROR_FAILED:
15274                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
15275                 case GST_STREAM_ERROR_DECODE:
15276                 case GST_STREAM_ERROR_WRONG_TYPE:
15277                 case GST_STREAM_ERROR_DECRYPT:
15278                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
15279                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
15280                          trans_err = __gst_transform_gsterror( player, message, error );
15281                 break;
15282
15283                 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
15284                 case GST_STREAM_ERROR_TOO_LAZY:
15285                 case GST_STREAM_ERROR_ENCODE:
15286                 case GST_STREAM_ERROR_DEMUX:
15287                 case GST_STREAM_ERROR_MUX:
15288                 case GST_STREAM_ERROR_FORMAT:
15289                 default:
15290                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
15291                 break;
15292         }
15293
15294         MMPLAYER_FLEAVE();
15295
15296         return trans_err;
15297 }
15298
15299 /* NOTE : decide gstreamer state whether there is some playable track or not. */
15300 static gint
15301 __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error )
15302 {
15303         gchar *src_element_name = NULL;
15304         GstElement *src_element = NULL;
15305         GstElementFactory *factory = NULL;
15306         const gchar* klass = NULL;
15307
15308         MMPLAYER_FENTER();
15309
15310         /* FIXIT */
15311         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
15312         return_val_if_fail ( message->src, MM_ERROR_INVALID_ARGUMENT );
15313         return_val_if_fail ( error, MM_ERROR_INVALID_ARGUMENT );
15314
15315         src_element = GST_ELEMENT_CAST(message->src);
15316         if ( !src_element )
15317                 goto INTERNAL_ERROR;
15318
15319         src_element_name = GST_ELEMENT_NAME(src_element);
15320         if ( !src_element_name )
15321                 goto INTERNAL_ERROR;
15322
15323         factory = gst_element_get_factory(src_element);
15324         if ( !factory )
15325                 goto INTERNAL_ERROR;
15326
15327         klass = gst_element_factory_get_klass(factory);
15328         if ( !klass )
15329                 goto INTERNAL_ERROR;
15330
15331         debug_log("error code=%d, msg=%s, src element=%s, class=%s\n",
15332                         error->code, error->message, src_element_name, klass);
15333
15334         //<-
15335         {
15336                 if (player->selector) {
15337                         int msg_src_pos = 0;
15338                         gint active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
15339                         debug_log ("current  active pad index  -%d", active_pad_index);
15340
15341                         if  (src_element_name) {
15342                                 int idx = 0;
15343
15344                                 if (player->audio_decoders) {
15345                                         GList *adec = player->audio_decoders;
15346                                         for ( ;adec ; adec = g_list_next(adec)) {
15347                                                 gchar *name = adec->data;
15348
15349                                                 debug_log("found audio decoder name  = %s", name);
15350                                                 if (g_strrstr(name, src_element_name)) {
15351                                                         msg_src_pos = idx;
15352                                                         break;
15353                                                 }
15354                                                 idx++;
15355                                         }
15356                                 }
15357                                 debug_log("active pad = %d, error src index = %d", active_pad_index,  msg_src_pos);
15358                         }
15359
15360                         if (active_pad_index != msg_src_pos) {
15361                                 debug_log("skip error because error is posted from no activated track");
15362                                 return MM_ERROR_NONE;
15363                         }
15364                 }
15365         }
15366         //-> temp code
15367
15368         switch ( error->code )
15369         {
15370                 case GST_STREAM_ERROR_DECODE:
15371                 {
15372                         /* Demuxer can't parse one track because it's corrupted.
15373                          * So, the decoder for it is not linked.
15374                          * But, it has one playable track.
15375                          */
15376                         if ( g_strrstr(klass, "Demux") )
15377                         {
15378                                 if ( player->can_support_codec == FOUND_PLUGIN_VIDEO )
15379                                 {
15380                                         return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
15381                                 }
15382                                 else if ( player->can_support_codec == FOUND_PLUGIN_AUDIO )
15383                                 {
15384                                         return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15385                                 }
15386                                 else
15387                                 {
15388                                         if ( player->pipeline->audiobin ) // PCM
15389                                         {
15390                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15391                                         }
15392                                         else
15393                                         {
15394                                                 goto CODEC_NOT_FOUND;
15395                                         }
15396                                 }
15397                         }
15398                         return MM_ERROR_PLAYER_INVALID_STREAM;
15399                 }
15400                 break;
15401
15402                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
15403                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
15404                 case GST_STREAM_ERROR_WRONG_TYPE:
15405                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15406
15407                 case GST_STREAM_ERROR_FAILED:
15408                 {
15409                         /* Decoder Custom Message */
15410                         if ( strstr(error->message, "ongoing") )
15411                         {
15412                                 if ( strncasecmp(klass, "audio", 5) )
15413                                 {
15414                                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) )
15415                                         {
15416                                                 debug_log("Video can keep playing.\n");
15417                                                 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
15418                                         }
15419                                         else
15420                                         {
15421                                                 goto CODEC_NOT_FOUND;
15422                                         }
15423
15424                                 }
15425                                 else if ( strncasecmp(klass, "video", 5) )
15426                                 {
15427                                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) )
15428                                         {
15429                                                 debug_log("Audio can keep playing.\n");
15430                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15431                                         }
15432                                         else
15433                                         {
15434                                                 goto CODEC_NOT_FOUND;
15435                                         }
15436                                 }
15437                         }
15438                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15439                 }
15440                 break;
15441
15442                 case GST_STREAM_ERROR_DECRYPT:
15443                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
15444                 {
15445                         debug_error("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
15446
15447                         if ( strstr(error->message, "rights expired") )
15448                         {
15449                                 return MM_ERROR_PLAYER_DRM_EXPIRED;
15450                         }
15451                         else if ( strstr(error->message, "no rights") )
15452                         {
15453                                 return MM_ERROR_PLAYER_DRM_NO_LICENSE;
15454                         }
15455                         else if ( strstr(error->message, "has future rights") )
15456                         {
15457                                 return MM_ERROR_PLAYER_DRM_FUTURE_USE;
15458                         }
15459                         else if ( strstr(error->message, "opl violation") )
15460                         {
15461                                 return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
15462                         }
15463                         return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
15464                 }
15465                 break;
15466
15467                 default:
15468                 break;
15469         }
15470
15471         MMPLAYER_FLEAVE();
15472
15473         return MM_ERROR_PLAYER_INVALID_STREAM;
15474
15475 INTERNAL_ERROR:
15476         return MM_ERROR_PLAYER_INTERNAL;
15477
15478 CODEC_NOT_FOUND:
15479         debug_log("not found any available codec. Player should be destroyed.\n");
15480         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
15481 }
15482
15483 static void
15484 __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms )
15485 {
15486         return_if_fail( player );
15487
15488
15489         /* post now if delay is zero */
15490         if ( delay_in_ms == 0 || player->set_mode.pcm_extraction)
15491         {
15492                 debug_log("eos delay is zero. posting EOS now\n");
15493                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15494
15495                 if ( player->set_mode.pcm_extraction )
15496                         __mmplayer_cancel_eos_timer(player);
15497
15498                 return;
15499         }
15500
15501         /* cancel if existing */
15502         __mmplayer_cancel_eos_timer( player );
15503
15504         /* init new timeout */
15505         /* NOTE : consider give high priority to this timer */
15506         debug_log("posting EOS message after [%d] msec\n", delay_in_ms);
15507
15508         player->eos_timer = g_timeout_add( delay_in_ms,
15509                 __mmplayer_eos_timer_cb, player );
15510
15511         player->context.global_default = g_main_context_default ();
15512         debug_log("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
15513
15514         /* check timer is valid. if not, send EOS now */
15515         if ( player->eos_timer == 0 )
15516         {
15517                 debug_warning("creating timer for delayed EOS has failed. sending EOS now\n");
15518                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15519         }
15520 }
15521
15522 static void
15523 __mmplayer_cancel_eos_timer( mm_player_t* player )
15524 {
15525         return_if_fail( player );
15526
15527         if ( player->eos_timer )
15528         {
15529                 debug_log("cancel eos timer");
15530                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
15531                 player->eos_timer = 0;
15532         }
15533
15534         return;
15535 }
15536
15537 static gboolean
15538 __mmplayer_eos_timer_cb(gpointer u_data)
15539 {
15540         mm_player_t* player = NULL;
15541         player = (mm_player_t*) u_data;
15542
15543         return_val_if_fail( player, FALSE );
15544
15545         if ( player->play_count > 1 )
15546         {
15547                 gint ret_value = 0;
15548                 ret_value = __gst_set_position( player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
15549                 if (ret_value == MM_ERROR_NONE)
15550                 {
15551                         MMHandleType attrs = 0;
15552                         attrs = MMPLAYER_GET_ATTRS(player);
15553
15554                         /* we successeded to rewind. update play count and then wait for next EOS */
15555                         player->play_count--;
15556
15557                         mm_attrs_set_int_by_name(attrs, "profile_play_count", player->play_count);
15558                         mmf_attrs_commit ( attrs );
15559                 }
15560                 else
15561                 {
15562                         debug_error("seeking to 0 failed in repeat play");
15563                 }
15564         }
15565         else
15566         {
15567                 /* posting eos */
15568                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15569         }
15570
15571         /* we are returning FALSE as we need only one posting */
15572         return FALSE;
15573 }
15574
15575 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force)
15576 {
15577         gint antishock = FALSE;
15578         MMHandleType attrs = 0;
15579
15580         MMPLAYER_FENTER();
15581
15582         return_if_fail ( player && player->pipeline );
15583
15584         /* It should be passed for video only clip */
15585         if ( ! player->pipeline->audiobin )
15586                 return;
15587
15588         if ( ( g_strrstr(player->ini.name_of_audiosink, "avsysaudiosink")) )
15589         {
15590                 attrs = MMPLAYER_GET_ATTRS(player);
15591                 if ( ! attrs )
15592                 {
15593                         debug_error("fail to get attributes.\n");
15594                         return;
15595                 }
15596
15597                 mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock);
15598
15599                 if (player->sm.antishock) {
15600                         antishock = TRUE;
15601                         player->sm.antishock = 0;
15602                 }
15603
15604                 debug_log("setting antishock as (%d)\n", antishock);
15605
15606                 if ( disable_by_force )
15607                 {
15608                         debug_log("but, antishock is disabled by force when is seeked\n");
15609
15610                         antishock = FALSE;
15611                 }
15612
15613                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "fadeup", antishock, NULL);
15614         }
15615
15616         MMPLAYER_FLEAVE();
15617
15618         return;
15619 }
15620
15621
15622 static gboolean
15623 __mmplayer_link_decoder( mm_player_t* player, GstPad *srcpad)
15624 {
15625         const gchar* name = NULL;
15626         GstStructure* str = NULL;
15627         GstCaps* srccaps = NULL;
15628
15629         MMPLAYER_FENTER();
15630
15631         return_val_if_fail( player, FALSE );
15632         return_val_if_fail ( srcpad, FALSE );
15633
15634         /* to check any of the decoder (video/audio) need to be linked  to parser*/
15635         srccaps = gst_pad_query_caps( srcpad, NULL);
15636         if ( !srccaps )
15637                 goto ERROR;
15638
15639         str = gst_caps_get_structure( srccaps, 0 );
15640         if ( ! str )
15641                 goto ERROR;
15642
15643         name = gst_structure_get_name(str);
15644         if ( ! name )
15645                 goto ERROR;
15646
15647         if (strstr(name, "video"))
15648         {
15649                 if(player->videodec_linked)
15650                 {
15651                     debug_msg("Video decoder already linked\n");
15652                         return FALSE;
15653                 }
15654         }
15655         if (strstr(name, "audio"))
15656         {
15657                 if(player->audiodec_linked)
15658                 {
15659                     debug_msg("Audio decoder already linked\n");
15660                         return FALSE;
15661                 }
15662         }
15663
15664         gst_caps_unref( srccaps );
15665
15666         MMPLAYER_FLEAVE();
15667
15668         return TRUE;
15669
15670 ERROR:
15671         if ( srccaps )
15672                 gst_caps_unref( srccaps );
15673
15674         return FALSE;
15675 }
15676
15677 static gboolean
15678 __mmplayer_link_sink( mm_player_t* player , GstPad *srcpad)
15679 {
15680         const gchar* name = NULL;
15681         GstStructure* str = NULL;
15682         GstCaps* srccaps = NULL;
15683
15684         MMPLAYER_FENTER();
15685
15686         return_val_if_fail ( player, FALSE );
15687         return_val_if_fail ( srcpad, FALSE );
15688
15689         /* to check any of the decoder (video/audio) need to be linked  to parser*/
15690         srccaps = gst_pad_query_caps( srcpad, NULL );
15691         if ( !srccaps )
15692                 goto ERROR;
15693
15694         str = gst_caps_get_structure( srccaps, 0 );
15695         if ( ! str )
15696                 goto ERROR;
15697
15698         name = gst_structure_get_name(str);
15699         if ( ! name )
15700                 goto ERROR;
15701
15702         if (strstr(name, "video"))
15703         {
15704                 if(player->videosink_linked)
15705                 {
15706                         debug_msg("Video Sink already linked\n");
15707                         return FALSE;
15708                 }
15709         }
15710         if (strstr(name, "audio"))
15711         {
15712                 if(player->audiosink_linked)
15713                 {
15714                         debug_msg("Audio Sink already linked\n");
15715                         return FALSE;
15716                 }
15717         }
15718         if (strstr(name, "text"))
15719         {
15720                 if(player->textsink_linked)
15721                 {
15722                         debug_msg("Text Sink already linked\n");
15723                         return FALSE;
15724                 }
15725         }
15726
15727         gst_caps_unref( srccaps );
15728
15729         MMPLAYER_FLEAVE();
15730
15731         return TRUE;
15732         //return (!player->videosink_linked || !player->audiosink_linked);
15733
15734 ERROR:
15735         if ( srccaps )
15736                 gst_caps_unref( srccaps );
15737
15738         return FALSE;
15739 }
15740
15741
15742 /* sending event to one of sinkelements */
15743 static gboolean
15744 __gst_send_event_to_sink( mm_player_t* player, GstEvent* event )
15745 {
15746         GstEvent * event2 = NULL;
15747         GList *sinks = NULL;
15748         gboolean res = FALSE;
15749         MMPLAYER_FENTER();
15750
15751         return_val_if_fail( player, FALSE );
15752         return_val_if_fail ( event, FALSE );
15753
15754         if ( player->play_subtitle && !player->use_textoverlay)
15755                 event2 = gst_event_copy((const GstEvent *)event);
15756
15757         sinks = player->sink_elements;
15758         while (sinks)
15759         {
15760                 GstElement *sink = GST_ELEMENT_CAST (sinks->data);
15761
15762                 if (GST_IS_ELEMENT(sink))
15763                 {
15764                         /* keep ref to the event */
15765                         gst_event_ref (event);
15766
15767                         if ( (res = gst_element_send_event (sink, event)) )
15768                         {
15769                                 debug_log("sending event[%s] to sink element [%s] success!\n",
15770                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
15771
15772                                 /* rtsp case, asyn_done is not called after seek during pause state */
15773                                 if (MMPLAYER_IS_RTSP_STREAMING(player))
15774                                 {
15775                                         if (strstr(GST_EVENT_TYPE_NAME(event), "seek"))
15776                                         {
15777                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
15778                                                 {
15779                                                         debug_log("RTSP seek completed, after pause state..\n");
15780                                                         player->doing_seek = FALSE;
15781                                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
15782                                                 }
15783
15784                                         }
15785                                 }
15786
15787 #ifdef TEST_ES
15788                                 if( MMPLAYER_IS_ES_BUFF_SRC(player))
15789                                 {
15790                                         sinks = g_list_next (sinks);
15791                                         continue;
15792                                 }
15793                                 else
15794 #endif
15795                                         break;
15796                         }
15797
15798                         debug_log("sending event[%s] to sink element [%s] failed. try with next one.\n",
15799                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
15800                 }
15801
15802                 sinks = g_list_next (sinks);
15803         }
15804
15805 #if 0
15806         if (internal_sub)
15807           request pad name = sink0;
15808         else
15809           request pad name = sink1; // external
15810 #endif
15811
15812         /* Note : Textbin is not linked to the video or audio bin.
15813          * It needs to send the event to the text sink seperatelly.
15814          */
15815          if ( player->play_subtitle && !player->use_textoverlay)
15816          {
15817                 GstElement *text_sink = GST_ELEMENT_CAST (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
15818
15819                 if (GST_IS_ELEMENT(text_sink))
15820                 {
15821                         /* keep ref to the event */
15822                         gst_event_ref (event2);
15823
15824                         if ( (res != gst_element_send_event (text_sink, event2)) )
15825                         {
15826                                 debug_error("sending event[%s] to subtitle sink element [%s] failed!\n",
15827                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
15828                         }
15829                         else
15830                         {
15831                                 debug_log("sending event[%s] to subtitle sink element [%s] success!\n",
15832                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
15833                         }
15834
15835                         gst_event_unref (event2);
15836                 }
15837          }
15838
15839         gst_event_unref (event);
15840
15841         MMPLAYER_FLEAVE();
15842
15843         return res;
15844 }
15845
15846 static void
15847 __mmplayer_add_sink( mm_player_t* player, GstElement* sink )
15848 {
15849         MMPLAYER_FENTER();
15850
15851         return_if_fail ( player );
15852         return_if_fail ( sink );
15853
15854         player->sink_elements =
15855                 g_list_append(player->sink_elements, sink);
15856
15857         MMPLAYER_FLEAVE();
15858 }
15859
15860 static void
15861 __mmplayer_del_sink( mm_player_t* player, GstElement* sink )
15862 {
15863         MMPLAYER_FENTER();
15864
15865         return_if_fail ( player );
15866         return_if_fail ( sink );
15867
15868         player->sink_elements =
15869                         g_list_remove(player->sink_elements, sink);
15870
15871         MMPLAYER_FLEAVE();
15872 }
15873
15874 static gboolean
15875 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
15876                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
15877                         gint64 cur, GstSeekType stop_type, gint64 stop )
15878 {
15879         GstEvent* event = NULL;
15880         gboolean result = FALSE;
15881
15882         MMPLAYER_FENTER();
15883
15884         return_val_if_fail( player, FALSE );
15885
15886         __mmplayer_drop_subtitle(player, FALSE);
15887
15888         event = gst_event_new_seek (rate, format, flags, cur_type,
15889                 cur, stop_type, stop);
15890
15891         result = __gst_send_event_to_sink( player, event );
15892
15893         MMPLAYER_FLEAVE();
15894
15895         return result;
15896 }
15897
15898 /* NOTE : be careful with calling this api. please refer to below glib comment
15899  * glib comment : Note that there is a bug in GObject that makes this function much
15900  * less useful than it might seem otherwise. Once gobject is disposed, the callback
15901  * will no longer be called, but, the signal handler is not currently disconnected.
15902  * If the instance is itself being freed at the same time than this doesn't matter,
15903  * since the signal will automatically be removed, but if instance persists,
15904  * then the signal handler will leak. You should not remove the signal yourself
15905  * because in a future versions of GObject, the handler will automatically be
15906  * disconnected.
15907  *
15908  * It's possible to work around this problem in a way that will continue to work
15909  * with future versions of GObject by checking that the signal handler is still
15910  * connected before disconnected it:
15911  *
15912  *  if (g_signal_handler_is_connected (instance, id))
15913  *    g_signal_handler_disconnect (instance, id);
15914  */
15915 static void
15916 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
15917 {
15918         GList* sig_list = NULL;
15919         MMPlayerSignalItem* item = NULL;
15920
15921         MMPLAYER_FENTER();
15922
15923         return_if_fail( player );
15924
15925         debug_log("release signals type : %d", type);
15926
15927         if ((type < MM_PLAYER_SIGNAL_TYPE_AUTOPLUG) || (type >= MM_PLAYER_SIGNAL_TYPE_ALL))
15928         {
15929                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
15930                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
15931                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
15932                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
15933                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
15934                 return;
15935         }
15936
15937         sig_list = player->signals[type];
15938
15939         for ( ; sig_list; sig_list = sig_list->next )
15940         {
15941                 item = sig_list->data;
15942
15943                 if ( item && item->obj && GST_IS_ELEMENT(item->obj) )
15944                 {
15945                         if ( g_signal_handler_is_connected ( item->obj, item->sig ) )
15946                         {
15947                                 g_signal_handler_disconnect ( item->obj, item->sig );
15948                         }
15949                 }
15950
15951                 MMPLAYER_FREEIF( item );
15952         }
15953
15954         g_list_free ( player->signals[type] );
15955         player->signals[type] = NULL;
15956
15957         MMPLAYER_FLEAVE();
15958
15959         return;
15960 }
15961
15962 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
15963 {
15964         mm_player_t* player = 0;
15965         int prev_display_surface_type = 0;
15966         void *prev_display_overlay = NULL;
15967         const gchar *klass = NULL;
15968         gchar *cur_videosink_name = NULL;
15969         int ret = 0;
15970         int i = 0;
15971         int num_of_dec = 2; /* DEC1, DEC2 */
15972
15973         MMPLAYER_FENTER();
15974
15975         return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
15976         return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
15977
15978         player = MM_PLAYER_CAST(handle);
15979
15980         if (surface_type < MM_DISPLAY_SURFACE_X && surface_type > MM_DISPLAY_SURFACE_EVAS)
15981         {
15982                 debug_error("Not support this surface type(%d) for changing vidoesink", surface_type);
15983                 MMPLAYER_FLEAVE();
15984                 return MM_ERROR_INVALID_ARGUMENT;
15985         }
15986
15987         /* load previous attributes */
15988         if (player->attrs)
15989         {
15990                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &prev_display_surface_type);
15991                 mm_attrs_get_data_by_name (player->attrs, "display_overlay", &prev_display_overlay);
15992                 debug_log("[0: X surface, 1: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
15993                 if (prev_display_surface_type == surface_type)
15994                 {
15995                         debug_log("incoming display surface type is same as previous one, do nothing..");
15996                         MMPLAYER_FLEAVE();
15997                         return MM_ERROR_NONE;
15998                 }
15999         }
16000         else
16001         {
16002                 debug_error("failed to load attributes");
16003                 MMPLAYER_FLEAVE();
16004                 return MM_ERROR_PLAYER_INTERNAL;
16005         }
16006
16007         /* check videosink element is created */
16008         if (!player->pipeline || !player->pipeline->videobin ||
16009                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
16010         {
16011                 debug_log("videosink element is not yet ready");
16012
16013                 /* videobin is not created yet, so we just set attributes related to display surface */
16014                 debug_log("store display attribute for given surface type(%d)", surface_type);
16015                 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
16016                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
16017                 if ( mmf_attrs_commit ( player->attrs ) )
16018                 {
16019                         debug_error("failed to commit attribute");
16020                         MMPLAYER_FLEAVE();
16021                         return MM_ERROR_PLAYER_INTERNAL;
16022                 }
16023                 MMPLAYER_FLEAVE();
16024                 return MM_ERROR_NONE;
16025         }
16026         else
16027         {
16028                 /* get player command status */
16029                 if ( !(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE) )
16030                 {
16031                         debug_error("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command",player->cmd);
16032                         MMPLAYER_FLEAVE();
16033                         return MM_ERROR_PLAYER_INVALID_STATE;
16034                 }
16035
16036                 /* get a current videosink name */
16037                 cur_videosink_name = GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
16038
16039                 /* surface change */
16040                 for ( i = 0 ; i < num_of_dec ; i++)
16041                 {
16042                         if ( player->pipeline->mainbin &&
16043                                 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst )
16044                         {
16045                                 klass = gst_element_factory_get_klass( gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) );
16046                                 if ((g_strrstr(klass, "Codec/Decoder/Video")))
16047                                 {
16048                                         if ( !strncmp(cur_videosink_name, "x", 1) && (surface_type == MM_DISPLAY_SURFACE_EVAS) )
16049                                         {
16050                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_evas, surface_type, display_overlay);
16051                                                 if (ret)
16052                                                 {
16053                                                         goto ERROR_CASE;
16054                                                 }
16055                                                 else
16056                                                 {
16057                                                         debug_warning("success to changing display surface(%d)",surface_type);
16058                                                         MMPLAYER_FLEAVE();
16059                                                         return MM_ERROR_NONE;
16060                                                 }
16061                                         }
16062                                         else if (!strncmp(cur_videosink_name, "evas", 4) && (surface_type == MM_DISPLAY_SURFACE_X) )
16063                                         {
16064                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_x, surface_type, display_overlay);
16065                                                 if (ret)
16066                                                 {
16067                                                         goto ERROR_CASE;
16068                                                 }
16069                                                 else
16070                                                 {
16071                                                         debug_warning("success to changing display surface(%d)",surface_type);
16072                                                         MMPLAYER_FLEAVE();
16073                                                         return MM_ERROR_NONE;
16074                                                 }
16075                                         }
16076                                         else
16077                                         {
16078                                                 debug_error("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface",surface_type, cur_videosink_name);
16079                                                 ret = MM_ERROR_PLAYER_INTERNAL;
16080                                                 goto ERROR_CASE;
16081                                         }
16082                                 }
16083                         }
16084                 }
16085         }
16086
16087 ERROR_CASE:
16088         /* rollback to previous attributes */
16089         mm_attrs_set_int_by_name (player->attrs, "display_surface_type", prev_display_surface_type);
16090         mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(prev_display_overlay));
16091         if ( mmf_attrs_commit ( player->attrs ) )
16092         {
16093                 debug_error("failed to commit attributes to rollback");
16094                 MMPLAYER_FLEAVE();
16095                 return MM_ERROR_PLAYER_INTERNAL;
16096         }
16097         MMPLAYER_FLEAVE();
16098         return ret;
16099 }
16100
16101 /* NOTE : It does not support some use cases, eg using colorspace converter */
16102 int
16103 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
16104 {
16105         GstPad *src_pad_dec = NULL;
16106         GstPad *sink_pad_videosink = NULL;
16107         GstPad *sink_pad_videobin = NULL;
16108         GstClock *clock = NULL;
16109         MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
16110         int ret = MM_ERROR_NONE;
16111         gboolean is_audiobin_created = TRUE;
16112
16113         MMPLAYER_FENTER();
16114
16115         return_val_if_fail(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
16116         return_val_if_fail(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
16117         return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
16118
16119         debug_log("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
16120         debug_log("surface type(%d), display overlay(%x)", surface_type, display_overlay);
16121
16122         /* get information whether if audiobin is created */
16123         if ( !player->pipeline->audiobin ||
16124                      !player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
16125         {
16126                 debug_warning("audiobin is null, this video content may not have audio data");
16127                 is_audiobin_created = FALSE;
16128         }
16129
16130         /* get current state of player */
16131         previous_state = MMPLAYER_CURRENT_STATE(player);
16132         debug_log("previous state(%d)", previous_state);
16133
16134
16135         /* get src pad of decoder and block it */
16136         src_pad_dec = gst_element_get_static_pad (GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
16137         if (!src_pad_dec)
16138         {
16139                 debug_error("failed to get src pad from decode in mainbin");
16140                 return MM_ERROR_PLAYER_INTERNAL;
16141         }
16142
16143         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
16144         {
16145                 debug_warning("trying to block pad(video)");
16146 //              if (!gst_pad_set_blocked (src_pad_dec, TRUE))
16147                 gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
16148                         NULL, NULL, NULL);
16149
16150                 {
16151                         debug_error("failed to set block pad(video)");
16152                         return MM_ERROR_PLAYER_INTERNAL;
16153                 }
16154                 debug_warning("pad is blocked(video)");
16155         }
16156         else
16157         {
16158                 /* no data flows, so no need to do pad_block */
16159                 if (player->doing_seek) {
16160                         debug_warning("not completed seek(%d), do nothing", player->doing_seek);
16161                 }
16162                 debug_log("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
16163         }
16164
16165         /* remove pad */
16166         if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
16167                 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin))))
16168         {
16169                 debug_error("failed to remove previous ghost_pad for videobin");
16170                 return MM_ERROR_PLAYER_INTERNAL;
16171         }
16172
16173         /* change state of videobin to NULL */
16174         debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
16175         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
16176         if (ret != GST_STATE_CHANGE_SUCCESS)
16177         {
16178                 debug_error("failed to change state of videobin to NULL");
16179                 return MM_ERROR_PLAYER_INTERNAL;
16180         }
16181
16182         /* unlink between decoder and videobin and remove previous videosink from videobin */
16183         GST_ELEMENT_UNLINK(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst),GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
16184         if ( !gst_bin_remove (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst)) )
16185         {
16186                 debug_error("failed to remove former videosink from videobin");
16187                 return MM_ERROR_PLAYER_INTERNAL;
16188         }
16189
16190         __mmplayer_del_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
16191
16192         /* create a new videosink and add it to videobin */
16193         player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, videosink_element);
16194         gst_bin_add (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
16195         __mmplayer_add_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
16196         g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
16197
16198         /* save attributes */
16199         if (player->attrs)
16200         {
16201                 /* set a new display surface type */
16202                 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
16203                 /* set a new diplay overlay */
16204                 switch (surface_type)
16205                 {
16206                         case MM_DISPLAY_SURFACE_X:
16207                                 debug_log("save attributes related to display surface to X : xid = %d", *(int*)display_overlay);
16208                                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
16209                                 break;
16210                         case MM_DISPLAY_SURFACE_EVAS:
16211                                 debug_log("save attributes related to display surface to EVAS : evas image object = %x", display_overlay);
16212                                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
16213                                 break;
16214                         default:
16215                                 debug_error("invalid type(%d) for changing display surface",surface_type);
16216                                 MMPLAYER_FLEAVE();
16217                                 return MM_ERROR_INVALID_ARGUMENT;
16218                 }
16219                 if ( mmf_attrs_commit ( player->attrs ) )
16220                 {
16221                         debug_error("failed to commit");
16222                         MMPLAYER_FLEAVE();
16223                         return MM_ERROR_PLAYER_INTERNAL;
16224                 }
16225         }
16226         else
16227         {
16228                 debug_error("player->attrs is null, failed to save attributes");
16229                 MMPLAYER_FLEAVE();
16230                 return MM_ERROR_PLAYER_INTERNAL;
16231         }
16232
16233         /* update video param */
16234         if ( MM_ERROR_NONE != _mmplayer_update_video_param( player ) )
16235         {
16236                 debug_error("failed to update video param");
16237                 return MM_ERROR_PLAYER_INTERNAL;
16238         }
16239
16240         /* change state of videobin to READY */
16241         debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
16242         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
16243         if (ret != GST_STATE_CHANGE_SUCCESS)
16244         {
16245                 debug_error("failed to change state of videobin to READY");
16246                 return MM_ERROR_PLAYER_INTERNAL;
16247         }
16248
16249         /* change ghostpad */
16250         sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
16251         if ( !sink_pad_videosink )
16252         {
16253                 debug_error("failed to get sink pad from videosink element");
16254                 return MM_ERROR_PLAYER_INTERNAL;
16255         }
16256         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
16257         if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE))
16258         {
16259                 debug_error("failed to set active to ghost_pad");
16260                 return MM_ERROR_PLAYER_INTERNAL;
16261         }
16262         if ( FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
16263         {
16264                 debug_error("failed to change ghostpad for videobin");
16265                 return MM_ERROR_PLAYER_INTERNAL;
16266         }
16267         gst_object_unref(sink_pad_videosink);
16268
16269         /* link decoder with videobin */
16270         sink_pad_videobin = gst_element_get_static_pad( GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
16271         if ( !sink_pad_videobin )
16272         {
16273                 debug_error("failed to get sink pad from videobin");
16274                 return MM_ERROR_PLAYER_INTERNAL;
16275         }
16276         if ( GST_PAD_LINK_OK != GST_PAD_LINK(src_pad_dec, sink_pad_videobin) )
16277         {
16278                 debug_error("failed to link");
16279                 return MM_ERROR_PLAYER_INTERNAL;
16280         }
16281         gst_object_unref(sink_pad_videobin);
16282
16283         /* clock setting for a new videosink plugin */
16284         /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
16285                         so we set it from audiosink plugin or pipeline(system clock) */
16286         if (!is_audiobin_created)
16287         {
16288                 debug_warning("audiobin is not created, get clock from pipeline..");
16289                 clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
16290         }
16291         else
16292         {
16293                 clock = GST_ELEMENT_CLOCK (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
16294         }
16295         if (clock)
16296         {
16297                 GstClockTime now;
16298                 GstClockTime base_time;
16299                 debug_log("set the clock to videosink");
16300                 gst_element_set_clock (GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
16301                 clock = GST_ELEMENT_CLOCK (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
16302                 if (clock)
16303                 {
16304                         debug_log("got clock of videosink");
16305                         now = gst_clock_get_time ( clock );
16306                         base_time = GST_ELEMENT_CAST (player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
16307                         debug_log ("at time %" GST_TIME_FORMAT ", base %"
16308                                         GST_TIME_FORMAT, GST_TIME_ARGS (now), GST_TIME_ARGS (base_time));
16309                 }
16310                 else
16311                 {
16312                         debug_error("failed to get clock of videosink after setting clock");
16313                         return MM_ERROR_PLAYER_INTERNAL;
16314                 }
16315         }
16316         else
16317         {
16318                 debug_warning("failed to get clock, maybe it is the time before first playing");
16319         }
16320
16321         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
16322         {
16323                 /* change state of videobin to PAUSED */
16324                 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
16325                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
16326                 if (ret != GST_STATE_CHANGE_FAILURE)
16327                 {
16328                         debug_warning("change state of videobin to PLAYING, ret(%d)", ret);
16329                 }
16330                 else
16331                 {
16332                         debug_error("failed to change state of videobin to PLAYING");
16333                         return MM_ERROR_PLAYER_INTERNAL;
16334                 }
16335
16336                 /* release blocked and unref src pad of video decoder */
16337                 #if 0
16338                 if (!gst_pad_set_blocked (src_pad_dec, FALSE))
16339                 {
16340                         debug_error("failed to set pad blocked FALSE(video)");
16341                         return MM_ERROR_PLAYER_INTERNAL;
16342                 }
16343                 #endif
16344                 debug_warning("pad is unblocked(video)");
16345         }
16346         else
16347         {
16348                 if (player->doing_seek) {
16349                         debug_warning("not completed seek(%d)", player->doing_seek);
16350                 }
16351                 /* change state of videobin to PAUSED */
16352                 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
16353                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
16354                 if (ret != GST_STATE_CHANGE_FAILURE)
16355                 {
16356                         debug_warning("change state of videobin to PAUSED, ret(%d)", ret);
16357                 }
16358                 else
16359                 {
16360                         debug_error("failed to change state of videobin to PLAYING");
16361                         return MM_ERROR_PLAYER_INTERNAL;
16362                 }
16363
16364                 /* already skipped pad block */
16365                 debug_log("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
16366         }
16367
16368         /* do get/set position for new videosink plugin */
16369         {
16370                 unsigned long position = 0;
16371                 gint64 pos_msec = 0;
16372
16373                 debug_log("do get/set position for new videosink plugin");
16374                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
16375                 {
16376                         debug_error("failed to get position");
16377                         return MM_ERROR_PLAYER_INTERNAL;
16378                 }
16379 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
16380                 /* accurate seek */
16381                 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE ))
16382                 {
16383                         debug_error("failed to set position");
16384                         return MM_ERROR_PLAYER_INTERNAL;
16385                 }
16386 #else
16387                 /* key unit seek */
16388                 pos_msec = position * G_GINT64_CONSTANT(1000000);
16389                 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
16390                                 GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT ),
16391                                                         GST_SEEK_TYPE_SET, pos_msec,
16392                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
16393                 if ( !ret  )
16394                 {
16395                         debug_error("failed to set position");
16396                         return MM_ERROR_PLAYER_INTERNAL;
16397                 }
16398 #endif
16399         }
16400
16401         if (src_pad_dec)
16402         {
16403                 gst_object_unref (src_pad_dec);
16404         }
16405         debug_log("success to change sink");
16406
16407         MMPLAYER_FLEAVE();
16408
16409         return MM_ERROR_NONE;
16410 }
16411
16412
16413 /* Note : if silent is true, then subtitle would not be displayed. :*/
16414 int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent)
16415 {
16416         mm_player_t* player = (mm_player_t*) hplayer;
16417
16418         MMPLAYER_FENTER();
16419
16420         /* check player handle */
16421         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16422
16423         player->set_mode.subtitle_off = silent;
16424
16425         debug_log("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
16426
16427         MMPLAYER_FLEAVE();
16428
16429         return MM_ERROR_NONE;
16430 }
16431
16432 int _mmplayer_remove_audio_parser_decoder(mm_player_t* player,GstPad *inpad)
16433 {
16434         int result = MM_ERROR_NONE;
16435         GstPad *peer = NULL,*pad = NULL;
16436         GstElement *Element = NULL;
16437         MMPlayerGstElement* mainbin = NULL;
16438         mainbin = player->pipeline->mainbin;
16439
16440         #if 0
16441         if(!gst_pad_set_blocked(inpad,TRUE))
16442         {
16443                 result = MM_ERROR_PLAYER_INTERNAL;
16444                 goto EXIT;
16445         }
16446         #endif
16447         gst_pad_add_probe(inpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
16448                         NULL, NULL, NULL);
16449
16450         /*Getting pad connected to demuxer audio pad */
16451         peer = gst_pad_get_peer(inpad);
16452         /* Disconnecting Demuxer and its peer plugin [audio] */
16453         if(peer)
16454         {
16455                 if(!gst_pad_unlink(inpad,peer))
16456                 {
16457                         result = MM_ERROR_PLAYER_INTERNAL;
16458                         goto EXIT;
16459                 }
16460         }
16461         else
16462         {
16463                 result = MM_ERROR_PLAYER_INTERNAL;
16464                 goto EXIT;
16465         }
16466         /*Removing elements between Demuxer and audiobin*/
16467         while(peer != NULL)
16468         {
16469                 gchar *Element_name = NULL;
16470                 gchar *factory_name = NULL;
16471                 GList *elements = NULL;
16472                 GstElementFactory *factory = NULL;
16473                 /*Getting peer element*/
16474                 Element = gst_pad_get_parent_element(peer);
16475                 if(Element == NULL)
16476                 {
16477                         gst_object_unref(peer);
16478                         result = MM_ERROR_PLAYER_INTERNAL;
16479                         break;
16480                 }
16481
16482                 Element_name = gst_element_get_name(Element);
16483                 factory = gst_element_get_factory(Element);
16484                 /*checking the element is audio bin*/
16485                 if(!strcmp(Element_name,"audiobin"))
16486                 {
16487                         gst_object_unref(peer);
16488                         result = MM_ERROR_NONE;
16489             g_free(Element_name);
16490                         break;
16491                 }
16492                 factory_name = GST_OBJECT_NAME(factory);
16493                 pad = gst_element_get_static_pad(Element,"src");
16494                 if(pad == NULL)
16495                 {
16496                         result = MM_ERROR_PLAYER_INTERNAL;
16497             g_free(Element_name);
16498                         break;
16499                 }
16500                 gst_object_unref(peer);
16501                 peer = gst_pad_get_peer(pad);
16502                 if(peer)
16503                 {
16504                         if(!gst_pad_unlink(pad,peer))
16505                         {
16506                                 gst_object_unref(peer);
16507                                 gst_object_unref(pad);
16508                                 result = MM_ERROR_PLAYER_INTERNAL;
16509                 g_free(Element_name);
16510                                 break;
16511                         }
16512                 }
16513                 elements = player->parsers;
16514                 /* Removing the element form the list*/
16515                 for ( ; elements; elements = g_list_next(elements))
16516                 {
16517                         Element_name = elements->data;
16518                         if(g_strrstr(Element_name,factory_name))
16519                         {
16520                                 player->parsers = g_list_remove(player->parsers,elements->data);
16521                         }
16522                 }
16523                 gst_element_set_state(Element,GST_STATE_NULL);
16524                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),Element);
16525                 gst_object_unref(pad);
16526                 if(Element == mainbin[MMPLAYER_M_Q1].gst)
16527                 {
16528                         mainbin[MMPLAYER_M_Q1].gst = NULL;
16529                 }
16530                 else if(Element == mainbin[MMPLAYER_M_Q2].gst)
16531                 {
16532                         mainbin[MMPLAYER_M_Q2].gst = NULL;
16533                 }
16534                 else if(Element == mainbin[MMPLAYER_M_DEC1].gst)
16535                 {
16536                         mainbin[MMPLAYER_M_DEC1].gst = NULL;
16537                 }
16538                 else if(Element == mainbin[MMPLAYER_M_DEC2].gst)
16539                 {
16540                         mainbin[MMPLAYER_M_DEC2].gst = NULL;
16541                 }
16542                 gst_object_unref(Element);
16543         }
16544 EXIT:
16545         return result;
16546 }
16547
16548 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
16549 {
16550         MMPlayerGstElement* mainbin = NULL;
16551         MMPlayerGstElement* textbin = NULL;
16552         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
16553         GstState current_state = GST_STATE_VOID_PENDING;
16554         GstState element_state = GST_STATE_VOID_PENDING;
16555         GstState element_pending_state = GST_STATE_VOID_PENDING;
16556         gint64 time = 0;
16557         GstEvent *event = NULL;
16558         int result = MM_ERROR_NONE;
16559
16560         GstClock *curr_clock = NULL;
16561         GstClockTime base_time, start_time, curr_time;
16562
16563
16564         MMPLAYER_FENTER();
16565
16566         /* check player handle */
16567         return_val_if_fail ( player && player->pipeline , MM_ERROR_PLAYER_NOT_INITIALIZED);
16568
16569         if (!(player->pipeline->mainbin) || !(player->pipeline->textbin))
16570         {
16571                 debug_error("Pipeline is not in proper state\n");
16572                 result = MM_ERROR_PLAYER_NOT_INITIALIZED;
16573                 goto EXIT;
16574         }
16575
16576         mainbin = player->pipeline->mainbin;
16577         textbin = player->pipeline->textbin;
16578
16579         current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
16580
16581         // sync clock with current pipeline
16582         curr_clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
16583         curr_time = gst_clock_get_time (curr_clock);
16584
16585         base_time = gst_element_get_base_time (GST_ELEMENT_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
16586         start_time = gst_element_get_start_time (GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
16587
16588         debug_log ("base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
16589                 GST_TIME_ARGS (base_time), GST_TIME_ARGS (start_time), GST_TIME_ARGS (curr_time));
16590
16591         if (current_state > GST_STATE_READY)
16592         {
16593                 // sync state with current pipeline
16594                 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
16595                 gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_PAUSED);
16596                 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
16597
16598                 ret = gst_element_get_state (mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
16599                 if ( GST_STATE_CHANGE_FAILURE == ret )
16600                 {
16601                         debug_error("fail to state change.\n");
16602                 }
16603         }
16604
16605         gst_element_set_base_time (textbin[MMPLAYER_T_BIN].gst, base_time);
16606         gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
16607
16608         if (curr_clock)
16609         {
16610                 gst_element_set_clock (textbin[MMPLAYER_T_BIN].gst, curr_clock);
16611                 gst_object_unref (curr_clock);
16612         }
16613
16614         // seek to current position
16615         if (!gst_element_query_position (mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time))
16616         {
16617                 result = MM_ERROR_PLAYER_INVALID_STATE;
16618                 debug_error("gst_element_query_position failed, invalid state\n");
16619                 goto EXIT;
16620         }
16621
16622         debug_log("seek time = %lld\n", time);
16623
16624         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);
16625         if (event)
16626         {
16627                 __gst_send_event_to_sink(player, event);
16628         }
16629         else
16630         {
16631                 result = MM_ERROR_PLAYER_INTERNAL;
16632                 debug_error("gst_event_new_seek failed\n");
16633                 goto EXIT;
16634         }
16635
16636         // sync state with current pipeline
16637         gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
16638         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
16639         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
16640
16641 EXIT:
16642         return result;
16643 }
16644
16645 static int
16646 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
16647 {
16648         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
16649         GstState current_state = GST_STATE_VOID_PENDING;
16650
16651         MMHandleType attrs = 0;
16652         MMPlayerGstElement* mainbin = NULL;
16653         MMPlayerGstElement* textbin = NULL;
16654
16655         gchar* subtitle_uri = NULL;
16656         int result = MM_ERROR_NONE;
16657         const gchar *charset = NULL;
16658
16659         MMPLAYER_FENTER();
16660
16661         /* check player handle */
16662         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16663         return_val_if_fail( filepath, MM_ERROR_COMMON_INVALID_ARGUMENT );
16664
16665         if (!(player->pipeline) || !(player->pipeline->mainbin))
16666         {
16667                 result = MM_ERROR_PLAYER_INVALID_STATE;
16668                 debug_error("Pipeline is not in proper state\n");
16669                 goto EXIT;
16670         }
16671
16672         mainbin = player->pipeline->mainbin;
16673         textbin = player->pipeline->textbin;
16674
16675         current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
16676         if (current_state < GST_STATE_READY)
16677         {
16678                 result = MM_ERROR_PLAYER_INVALID_STATE;
16679                 debug_error("Pipeline is not in proper state\n");
16680                 goto EXIT;
16681         }
16682
16683         attrs = MMPLAYER_GET_ATTRS(player);
16684         if (!attrs)
16685         {
16686                 debug_error("cannot get content attribute\n");
16687                 result = MM_ERROR_PLAYER_INTERNAL;
16688                 goto EXIT;
16689         }
16690
16691         mm_attrs_get_string_by_name (attrs, "subtitle_uri", &subtitle_uri);
16692         if (!subtitle_uri || strlen(subtitle_uri) < 1)
16693         {
16694                 debug_error("subtitle uri is not proper filepath\n");
16695                 result = MM_ERROR_PLAYER_INVALID_URI;
16696                 goto EXIT;
16697         }
16698
16699         debug_log("old subtitle file path is [%s]\n", subtitle_uri);
16700         debug_log("new subtitle file path is [%s]\n", filepath);
16701
16702         if (!strcmp (filepath, subtitle_uri))
16703         {
16704                 debug_log("No need to swtich subtitle, as input filepath is same as current filepath\n");
16705                 goto EXIT;
16706         }
16707         else
16708         {
16709                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16710                 if (mmf_attrs_commit(player->attrs))
16711                 {
16712                         debug_error("failed to commit.\n");
16713                         goto EXIT;
16714                 }
16715         }
16716
16717         //gst_pad_set_blocked_async(src-srcpad, TRUE)
16718
16719         ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
16720         if (ret != GST_STATE_CHANGE_SUCCESS)
16721         {
16722                 debug_error("failed to change state of textbin to READY");
16723                 result = MM_ERROR_PLAYER_INTERNAL;
16724                 goto EXIT;
16725         }
16726
16727         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_READY);
16728         if (ret != GST_STATE_CHANGE_SUCCESS)
16729         {
16730                 debug_error("failed to change state of subparse to READY");
16731                 result = MM_ERROR_PLAYER_INTERNAL;
16732                 goto EXIT;
16733         }
16734
16735         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
16736         if (ret != GST_STATE_CHANGE_SUCCESS)
16737         {
16738                 debug_error("failed to change state of filesrc to READY");
16739                 result = MM_ERROR_PLAYER_INTERNAL;
16740                 goto EXIT;
16741         }
16742
16743         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
16744
16745         charset = util_get_charset(filepath);
16746         if (charset)
16747         {
16748                 debug_log ("detected charset is %s\n", charset );
16749                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
16750         }
16751
16752         result = _mmplayer_sync_subtitle_pipeline(player);
16753
16754 EXIT:
16755         MMPLAYER_FLEAVE();
16756         return result;
16757 }
16758
16759 /* API to switch between external subtitles */
16760 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
16761 {
16762         int result = MM_ERROR_NONE;
16763         mm_player_t* player = (mm_player_t*)hplayer;
16764
16765         MMPLAYER_FENTER();
16766
16767         /* check player handle */
16768         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16769
16770         if (!player->pipeline)  // IDLE state
16771         {
16772                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16773                 if (mmf_attrs_commit(player->attrs))
16774                 {
16775                         debug_error("failed to commit.\n");
16776                         result= MM_ERROR_PLAYER_INTERNAL;
16777                 }
16778         }
16779         else    // curr state <> IDLE (READY, PAUSE, PLAYING..)
16780         {
16781                 if ( filepath == NULL )
16782                         return MM_ERROR_COMMON_INVALID_ARGUMENT;
16783
16784                 if (!__mmplayer_check_subtitle(player))
16785                 {
16786                         mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16787                         if (mmf_attrs_commit(player->attrs))
16788                         {
16789                                 debug_error("failed to commit.\n");
16790                                 result = MM_ERROR_PLAYER_INTERNAL;
16791                         }
16792
16793                         if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
16794                                 debug_error("fail to create subtitle src\n");
16795
16796                         result = _mmplayer_sync_subtitle_pipeline(player);
16797                 }
16798                 else
16799                 {
16800                         result = __mmplayer_change_external_subtitle_language(player, filepath);
16801                 }
16802         }
16803
16804         MMPLAYER_FLEAVE();
16805         return result;
16806 }
16807
16808 static int
16809 __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index)
16810 {
16811         int result = MM_ERROR_NONE;
16812         gchar* change_pad_name = NULL;
16813         GstPad* sinkpad = NULL;
16814         MMPlayerGstElement* mainbin = NULL;
16815         enum MainElementID elemId = MMPLAYER_M_NUM;
16816         GstCaps* caps = NULL;
16817         gint total_track_num = 0;
16818
16819         MMPLAYER_FENTER();
16820
16821         return_val_if_fail (player && player->pipeline && player->pipeline->mainbin,
16822                                                                                                         MM_ERROR_PLAYER_NOT_INITIALIZED);
16823
16824         debug_log ("Change Track(%d) to %d\n", type, index);
16825
16826         mainbin = player->pipeline->mainbin;
16827
16828         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
16829         {
16830                 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
16831         }
16832         else if (type == MM_PLAYER_TRACK_TYPE_TEXT)
16833         {
16834                 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
16835         }
16836         else
16837         {
16838                 debug_error ("Track Type Error\n");
16839                 goto EXIT;
16840         }
16841
16842         if (mainbin[elemId].gst == NULL)
16843         {
16844                 result = MM_ERROR_PLAYER_NO_OP;
16845                 debug_log ("Req track doesn't exist\n");
16846                 goto EXIT;
16847         }
16848
16849         total_track_num = player->selector[type].total_track_num;
16850         if (total_track_num <= 0)
16851         {
16852                 result = MM_ERROR_PLAYER_NO_OP;
16853                 debug_log ("Language list is not available \n");
16854                 goto EXIT;
16855         }
16856
16857         if ((index < 0) || (index >= total_track_num))
16858         {
16859                 result = MM_ERROR_INVALID_ARGUMENT;
16860                 debug_log ("Not a proper index : %d \n", index);
16861                 goto EXIT;
16862         }
16863
16864         /*To get the new pad from the selector*/
16865         change_pad_name = g_strdup_printf ("sink_%u", index);
16866         if (change_pad_name == NULL)
16867         {
16868                 result = MM_ERROR_PLAYER_INTERNAL;
16869                 debug_log ("Pad does not exists\n");
16870                 goto EXIT;
16871         }
16872
16873         debug_log ("new active pad name: %s\n", change_pad_name);
16874
16875         sinkpad = gst_element_get_static_pad (mainbin[elemId].gst, change_pad_name);
16876         if (sinkpad == NULL)
16877         {
16878                 debug_log ("sinkpad is NULL");
16879                 result = MM_ERROR_PLAYER_INTERNAL;
16880                 goto EXIT;
16881         }
16882
16883         debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
16884         g_object_set (mainbin[elemId].gst, "active-pad", sinkpad, NULL);
16885
16886         caps = gst_pad_get_current_caps(sinkpad);
16887         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
16888
16889         if (sinkpad)
16890                 gst_object_unref (sinkpad);
16891
16892         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
16893         {
16894                 __mmplayer_set_audio_attrs (player, caps);
16895         }
16896
16897 EXIT:
16898
16899         MMPLAYER_FREEIF(change_pad_name);
16900         return result;
16901 }
16902
16903 int _mmplayer_change_track_language (MMHandleType hplayer, MMPlayerTrackType type, int index)
16904 {
16905         int result = MM_ERROR_NONE;
16906         mm_player_t* player = NULL;
16907         MMPlayerGstElement* mainbin = NULL;
16908
16909         gint current_active_index = 0;
16910
16911         GstState current_state = GST_STATE_VOID_PENDING;
16912         GstEvent* event = NULL;
16913         gint64 time = 0;
16914
16915         MMPLAYER_FENTER();
16916
16917         player = (mm_player_t*)hplayer;
16918         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
16919
16920         if (!player->pipeline)
16921         {
16922                 debug_error ("Track %d pre setting -> %d\n", type, index);
16923
16924                 player->selector[type].active_pad_index = index;
16925                 goto EXIT;
16926         }
16927
16928         mainbin = player->pipeline->mainbin;
16929
16930         current_active_index = player->selector[type].active_pad_index;
16931
16932         /*If index is same as running index no need to change the pad*/
16933         if (current_active_index == index)
16934         {
16935                 goto EXIT;
16936         }
16937
16938         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time))
16939         {
16940                 result = MM_ERROR_PLAYER_INVALID_STATE;
16941                 goto EXIT;
16942         }
16943
16944         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
16945         if (current_state < GST_STATE_PAUSED)
16946         {
16947                 result = MM_ERROR_PLAYER_INVALID_STATE;
16948                 debug_warning ("Pipeline not in porper state\n");
16949                 goto EXIT;
16950         }
16951
16952         result = __mmplayer_change_selector_pad(player, type, index);
16953         if (result != MM_ERROR_NONE)
16954         {
16955                 debug_error ("change selector pad error\n");
16956                 goto EXIT;
16957         }
16958
16959         player->selector[type].active_pad_index = index;
16960
16961         if (current_state == GST_STATE_PLAYING)
16962         {
16963                 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);
16964                 if (event)
16965                 {
16966                         __gst_send_event_to_sink (player, event);
16967                 }
16968                 else
16969                 {
16970                         result = MM_ERROR_PLAYER_INTERNAL;
16971                         goto EXIT;
16972                 }
16973         }
16974
16975 EXIT:
16976         return result;
16977 }
16978
16979 int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent)
16980 {
16981         mm_player_t* player = (mm_player_t*) hplayer;
16982
16983         MMPLAYER_FENTER();
16984
16985         /* check player handle */
16986         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16987
16988         *silent = player->set_mode.subtitle_off;
16989
16990         debug_log("subtitle is %s.\n", silent ? "ON" : "OFF");
16991
16992         MMPLAYER_FLEAVE();
16993
16994         return MM_ERROR_NONE;
16995 }
16996
16997 const gchar *
16998 __get_state_name ( int state )
16999 {
17000         switch ( state )
17001         {
17002                 case MM_PLAYER_STATE_NULL:
17003                         return "NULL";
17004                 case MM_PLAYER_STATE_READY:
17005                         return "READY";
17006                 case MM_PLAYER_STATE_PAUSED:
17007                         return "PAUSED";
17008                 case MM_PLAYER_STATE_PLAYING:
17009                         return "PLAYING";
17010                 case MM_PLAYER_STATE_NONE:
17011                         return "NONE";
17012                 default:
17013                         return "INVAID";
17014         }
17015 }
17016
17017 gboolean
17018 __is_rtsp_streaming ( mm_player_t* player )
17019 {
17020         return_val_if_fail ( player, FALSE );
17021
17022         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP ) ? TRUE : FALSE;
17023 }
17024
17025 gboolean
17026 __is_wfd_streaming ( mm_player_t* player )
17027 {
17028   return_val_if_fail ( player, FALSE );
17029
17030   return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_WFD ) ? TRUE : FALSE;
17031 }
17032
17033 static gboolean
17034 __is_http_streaming ( mm_player_t* player )
17035 {
17036         return_val_if_fail ( player, FALSE );
17037
17038         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP ) ? TRUE : FALSE;
17039 }
17040
17041 static gboolean
17042 __is_streaming ( mm_player_t* player )
17043 {
17044         return_val_if_fail ( player, FALSE );
17045
17046   return ( __is_http_progressive_down( player ) || __is_rtsp_streaming ( player ) || __is_wfd_streaming ( player ) || __is_http_streaming ( player )
17047           || __is_http_live_streaming ( player ) || __is_dash_streaming ( player ) || __is_smooth_streaming(player) ) ? TRUE : FALSE;
17048 }
17049
17050 gboolean
17051 __is_live_streaming ( mm_player_t* player )
17052 {
17053         return_val_if_fail ( player, FALSE );
17054
17055         return ( __is_rtsp_streaming ( player ) && player->streaming_type == STREAMING_SERVICE_LIVE ) ? TRUE : FALSE;
17056 }
17057
17058 static gboolean
17059 __is_http_live_streaming( mm_player_t* player )
17060 {
17061         return_val_if_fail( player, FALSE );
17062
17063         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS ) ? TRUE : FALSE;
17064 }
17065
17066 static gboolean
17067 __is_dash_streaming ( mm_player_t* player )
17068 {
17069         return_val_if_fail ( player, FALSE );
17070
17071         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH ) ? TRUE : FALSE;
17072 }
17073
17074 static gboolean
17075 __is_smooth_streaming ( mm_player_t* player )
17076 {
17077         return_val_if_fail ( player, FALSE );
17078
17079         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_SS ) ? TRUE : FALSE;
17080 }
17081
17082
17083 static gboolean
17084 __is_http_progressive_down(mm_player_t* player)
17085 {
17086         return_val_if_fail( player, FALSE );
17087
17088         return ((player->pd_mode) ? TRUE:FALSE);
17089 }
17090
17091 #ifdef TEST_ES
17092 gboolean
17093 __is_es_buff_src( mm_player_t* player )
17094 {
17095         return_val_if_fail ( player, FALSE );
17096
17097         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF) ? TRUE : FALSE;
17098 }
17099 #endif
17100
17101 gboolean
17102 __has_suffix(mm_player_t* player, const gchar* suffix)
17103 {
17104         return_val_if_fail( player, FALSE );
17105         return_val_if_fail( suffix, FALSE );
17106
17107         gboolean ret = FALSE;
17108         gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
17109         gchar* t_suffix = g_ascii_strdown(suffix, -1);
17110
17111         if ( g_str_has_suffix(player->profile.uri, suffix) )
17112         {
17113                 ret = TRUE;
17114         }
17115
17116         MMPLAYER_FREEIF(t_url);
17117         MMPLAYER_FREEIF(t_suffix);
17118
17119         return ret;
17120 }
17121
17122 int
17123 _mmplayer_set_display_zoom(MMHandleType hplayer, float level, int x, int y)
17124 {
17125         mm_player_t* player = (mm_player_t*) hplayer;
17126
17127         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17128
17129         MMPLAYER_VIDEO_SINK_CHECK(player);
17130
17131         debug_log("setting display zoom level = %f, offset = %d, %d", level, x, y);
17132
17133         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", level, "zoom-pos-x", x, "zoom-pos-y", y, NULL);
17134
17135         return MM_ERROR_NONE;
17136 }
17137 int
17138 _mmplayer_get_display_zoom(MMHandleType hplayer, float *level, int *x, int *y)
17139 {
17140
17141         mm_player_t* player = (mm_player_t*) hplayer;
17142         float _level = 0.0;
17143         int _x = 0;
17144         int _y = 0;
17145
17146         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17147
17148         MMPLAYER_VIDEO_SINK_CHECK(player);
17149
17150         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", &_level, "zoom-pos-x", &_x, "zoom-pos-y", &_y, NULL);
17151
17152         debug_log("display zoom level = %f, start off x = %d, y = %d", _level, _x, _y);
17153
17154         *level = _level;
17155         *x = _x;
17156         *y = _y;
17157
17158         return MM_ERROR_NONE;
17159 }
17160
17161 int
17162 _mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
17163 {
17164         mm_player_t* player = (mm_player_t*) hplayer;
17165
17166         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
17167
17168         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL)
17169         {
17170                 MMPLAYER_PRINT_STATE(player);
17171                 debug_error("wrong-state : can't set the download mode to parse");
17172                 return MM_ERROR_PLAYER_INVALID_STATE;
17173         }
17174
17175         debug_log("set video hub download mode to %s", (mode)?"ON":"OFF");
17176         player->video_hub_download_mode = mode;
17177
17178         return MM_ERROR_NONE;
17179 }
17180
17181 int
17182 _mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
17183 {
17184         mm_player_t* player = (mm_player_t*) hplayer;
17185
17186         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
17187
17188         debug_log("enable sync handler : %s", (enable)?"ON":"OFF");
17189         player->sync_handler = enable;
17190
17191         return MM_ERROR_NONE;
17192 }
17193
17194 int
17195 _mmplayer_use_system_clock (MMHandleType hplayer)
17196 {
17197         mm_player_t* player = (mm_player_t*) hplayer;
17198
17199         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
17200
17201         debug_log("change clock provider to system");
17202
17203         // to use system clock
17204         player->ini.provide_clock_for_movie = FALSE;
17205         player->ini.provide_clock_for_music = FALSE;
17206
17207         return MM_ERROR_NONE;
17208 }
17209
17210 int
17211 _mmplayer_set_video_share_master_clock( MMHandleType hplayer,
17212                                         long long clock,
17213                                         long long clock_delta,
17214                                         long long video_time,
17215                                         long long media_clock,
17216                                         long long audio_time)
17217 {
17218         mm_player_t* player = (mm_player_t*) hplayer;
17219         MMPlayerGstElement* mainbin = NULL;
17220         GstClockTime start_time_audio = 0, start_time_video = 0;
17221         GstClockTimeDiff base_time = 0, new_base_time = 0;
17222         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
17223         gint64 api_delta = 0;
17224         gint64 position = 0, position_delta = 0;
17225         gint64 adj_base_time = 0;
17226         GstClock *curr_clock = NULL;
17227         GstClockTime curr_time = 0;
17228         gboolean query_ret = TRUE;
17229         int result = MM_ERROR_NONE;
17230
17231         MMPLAYER_FENTER();
17232
17233         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
17234         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
17235         return_val_if_fail ( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
17236
17237         // debug_log("in(us) : %lld, %lld, %lld, %lld, %lld", clock, clock_delta, video_time, media_clock, audio_time);
17238
17239         if ((video_time < 0) || (player->doing_seek))
17240         {
17241                 debug_log("skip setting master clock.  %lld", video_time);
17242                 goto EXIT;
17243         }
17244
17245         mainbin = player->pipeline->mainbin;
17246
17247         curr_clock = gst_pipeline_get_clock (GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
17248         curr_time = gst_clock_get_time (curr_clock);
17249
17250         current_state = MMPLAYER_CURRENT_STATE(player);
17251
17252         if ( current_state == MM_PLAYER_STATE_PLAYING )
17253                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
17254
17255         if ( ( current_state != MM_PLAYER_STATE_PLAYING ) ||
17256                  ( !query_ret ))
17257         {
17258                 position = player->last_position;
17259                 debug_log ("query fail. %lld", position);
17260         }
17261
17262         clock*= GST_USECOND;
17263         clock_delta *= GST_USECOND;
17264
17265         api_delta = clock - curr_time;
17266         if ((player->video_share_api_delta == 0 ) || (player->video_share_api_delta > api_delta))
17267         {
17268                 player->video_share_api_delta = api_delta;
17269         }
17270         else
17271         {
17272                 clock_delta += (api_delta - player->video_share_api_delta);
17273         }
17274
17275         if ((player->video_share_clock_delta == 0 ) || (player->video_share_clock_delta > clock_delta))
17276         {
17277                 player->video_share_clock_delta = (gint64)clock_delta;
17278
17279                 position_delta = (position/GST_USECOND) - video_time;
17280                 position_delta *= GST_USECOND;
17281
17282                 adj_base_time = position_delta;
17283                 debug_log ("video_share_clock_delta = %lld, adj = %lld", player->video_share_clock_delta, adj_base_time);
17284
17285         }
17286         else
17287         {
17288                 gint64 new_play_time = 0;
17289                 gint64 network_delay =0;
17290
17291                 video_time *= GST_USECOND;
17292
17293                 network_delay = clock_delta - player->video_share_clock_delta;
17294                 new_play_time = video_time + network_delay;
17295
17296                 adj_base_time = position - new_play_time;
17297
17298                 debug_log ("%lld(delay) = %lld - %lld / %lld(adj) = %lld(slave_pos) - %lld(master_pos) - %lld(delay)",
17299                         network_delay, clock_delta, player->video_share_clock_delta, adj_base_time, position, video_time, network_delay);
17300         }
17301
17302         /* Adjust Current Stream Time with base_time of sink
17303          * 1. Set Start time to CLOCK NONE, to control the base time by MSL
17304          * 2. Set new base time
17305          *    if adj_base_time is positive value, the stream time will be decreased.
17306          * 3. If seek event is occurred, the start time will be reset. */
17307         if ((player->pipeline->audiobin) &&
17308                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
17309         {
17310                 start_time_audio = gst_element_get_start_time (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
17311
17312                 if (start_time_audio != GST_CLOCK_TIME_NONE)
17313                 {
17314                         debug_log ("audio sink : gst_element_set_start_time -> NONE");
17315                         gst_element_set_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, GST_CLOCK_TIME_NONE);
17316                 }
17317
17318                 base_time = gst_element_get_base_time (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
17319         }
17320
17321         if ((player->pipeline->videobin) &&
17322                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
17323         {
17324                 start_time_video = gst_element_get_start_time (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
17325
17326                 if (start_time_video != GST_CLOCK_TIME_NONE)
17327                 {
17328                         debug_log ("video sink : gst_element_set_start_time -> NONE");
17329                         gst_element_set_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst, GST_CLOCK_TIME_NONE);
17330                 }
17331
17332                 // if videobin exist, get base_time from videobin.
17333                 base_time = gst_element_get_base_time (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
17334         }
17335
17336         new_base_time = base_time + adj_base_time;
17337
17338         if ((player->pipeline->audiobin) &&
17339                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
17340                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), (GstClockTime)new_base_time);
17341
17342         if ((player->pipeline->videobin) &&
17343                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
17344                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), (GstClockTime)new_base_time);
17345
17346 EXIT:
17347         MMPLAYER_FLEAVE();
17348
17349         return result;
17350 }
17351
17352 int
17353 _mmplayer_get_video_share_master_clock( MMHandleType hplayer,
17354                                         long long *video_time,
17355                                         long long *media_clock,
17356                                         long long *audio_time)
17357 {
17358         mm_player_t* player = (mm_player_t*) hplayer;
17359         MMPlayerGstElement* mainbin = NULL;
17360         GstClock *curr_clock = NULL;
17361         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
17362         gint64 position = 0;
17363         gboolean query_ret = TRUE;
17364
17365         MMPLAYER_FENTER();
17366
17367         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
17368         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
17369         return_val_if_fail ( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
17370
17371         return_val_if_fail ( video_time, MM_ERROR_COMMON_INVALID_ARGUMENT );
17372         return_val_if_fail ( media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT );
17373         return_val_if_fail ( audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT );
17374
17375         mainbin = player->pipeline->mainbin;
17376
17377         curr_clock = gst_pipeline_get_clock (GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
17378
17379         current_state = MMPLAYER_CURRENT_STATE(player);
17380
17381         if ( current_state != MM_PLAYER_STATE_PAUSED )
17382                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
17383
17384         if ( ( current_state == MM_PLAYER_STATE_PAUSED ) ||
17385                  ( !query_ret ))
17386         {
17387                 position = player->last_position;
17388         }
17389
17390         *media_clock = *video_time = *audio_time = (position/GST_USECOND);
17391
17392         debug_log("media_clock: %lld, video_time: %lld (us)", *media_clock, *video_time);
17393
17394         if (curr_clock)
17395                 gst_object_unref (curr_clock);
17396
17397         MMPLAYER_FLEAVE();
17398
17399         return MM_ERROR_NONE;
17400 }
17401
17402 int
17403 _mmplayer_get_video_rotate_angle(MMHandleType hplayer, int *angle)
17404 {
17405         mm_player_t* player = (mm_player_t*) hplayer;
17406         int org_angle = 0;
17407
17408         MMPLAYER_FENTER();
17409
17410         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17411         return_val_if_fail ( angle, MM_ERROR_COMMON_INVALID_ARGUMENT );
17412
17413         if (player->v_stream_caps)
17414         {
17415                 GstStructure *str = NULL;
17416
17417                 str = gst_caps_get_structure (player->v_stream_caps, 0);
17418                 if ( !gst_structure_get_int (str, "orientation", &org_angle))
17419                 {
17420                         debug_log ("missing 'orientation' field in video caps");
17421                 }
17422         }
17423
17424         debug_log("orientation: %d", org_angle);
17425         *angle = org_angle;
17426
17427         MMPLAYER_FLEAVE();
17428         return MM_ERROR_NONE;
17429 }
17430
17431 gboolean
17432 __mmplayer_is_streaming(mm_player_t* player)
17433 {
17434         gboolean result = FALSE;
17435
17436         MMPLAYER_FENTER();
17437
17438         return_val_if_fail (player, FALSE);
17439         result = __is_streaming (player) ;
17440
17441         MMPLAYER_FLEAVE();
17442         return result;
17443 }
17444
17445 static gboolean
17446 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
17447 {
17448         return_val_if_fail (player, FALSE);
17449         return_val_if_fail (element, FALSE);
17450
17451         gchar *factory_name = GST_OBJECT_NAME (gst_element_get_factory(element));
17452         gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
17453
17454         int idx = 0;
17455
17456         for ( idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++ )
17457         {
17458                 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx]))
17459                 {
17460                         debug_log("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
17461                         mm_player_dump_t *dump_s;
17462                         dump_s = g_malloc (sizeof(mm_player_dump_t));
17463
17464                         if (dump_s == NULL)
17465                         {
17466                                 debug_error ("malloc fail");
17467                                 return FALSE;
17468                         }
17469
17470                         dump_s->dump_element_file = NULL;
17471                         dump_s->dump_pad = NULL;
17472                         dump_s->dump_pad = gst_element_get_static_pad (element, "sink");
17473
17474                         if (dump_s->dump_pad)
17475                         {
17476                                 memset (dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
17477                                 sprintf (dump_file_name, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
17478                                 dump_s->dump_element_file = fopen(dump_file_name,"w+");
17479 //                              dump_s->probe_handle_id = gst_pad_add_buffer_probe (dump_s->dump_pad, G_CALLBACK(__mmplayer_dump_buffer_probe_cb), dump_s->dump_element_file);
17480                                 /* add list for removed buffer probe and close FILE */
17481                                 player->dump_list = g_list_append (player->dump_list, dump_s);
17482                                 debug_log ("%s sink pad added buffer probe for dump", factory_name);
17483                                 return TRUE;
17484                         }
17485                         else
17486                         {
17487                                 g_free(dump_s);
17488                                 dump_s = NULL;
17489                                 debug_error ("failed to get %s sink pad added", factory_name);
17490                         }
17491
17492
17493                 }
17494         }
17495         return FALSE;
17496 }
17497
17498
17499 #if 0
17500 static gboolean
17501 __mmplayer_dump_buffer_probe_cb(GstPad *pad, GstBuffer *buffer, gpointer u_data)
17502 {
17503         FILE *dump_data = (FILE *) u_data;
17504 //      int written = 0;
17505
17506         return_val_if_fail ( dump_data, FALSE );
17507
17508 //      debug_log ("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS( GST_BUFFER_TIMESTAMP(buffer)));
17509
17510         fwrite ( GST_BUFFER_DATA(buffer), 1, GST_BUFFER_SIZE(buffer), dump_data);
17511
17512         return TRUE;
17513 }
17514 #endif
17515
17516 static void
17517 __mmplayer_release_dump_list (GList *dump_list)
17518 {
17519         if (dump_list)
17520         {
17521                 GList *d_list = dump_list;
17522                 for ( ;d_list ; d_list = g_list_next(d_list))
17523                 {
17524                         mm_player_dump_t *dump_s = d_list->data;
17525                         if (dump_s->dump_pad)
17526                         {
17527                                 if (dump_s->probe_handle_id)
17528                                 {
17529                                         gst_pad_remove_probe (dump_s->dump_pad, dump_s->probe_handle_id);
17530                                 }
17531
17532                         }
17533                         if (dump_s->dump_element_file)
17534                         {
17535                                 fclose(dump_s->dump_element_file);
17536                                 dump_s->dump_element_file = NULL;
17537                         }
17538                         MMPLAYER_FREEIF(dump_s);
17539                 }
17540                 g_list_free(dump_list);
17541                 dump_list = NULL;
17542         }
17543 }
17544
17545 int
17546 _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
17547 {
17548         mm_player_t* player = (mm_player_t*) hplayer;
17549
17550         MMPLAYER_FENTER();
17551
17552         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17553         return_val_if_fail ( exist, MM_ERROR_INVALID_ARGUMENT );
17554
17555         *exist = player->has_closed_caption;
17556
17557         MMPLAYER_FLEAVE();
17558
17559         return MM_ERROR_NONE;
17560 }
17561
17562 int
17563 _mmplayer_enable_media_packet_video_stream(MMHandleType hplayer, bool enable)
17564 {
17565         mm_player_t* player = (mm_player_t*) hplayer;
17566
17567         MMPLAYER_FENTER();
17568
17569         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
17570         return_val_if_fail (enable == TRUE || enable == FALSE, MM_ERROR_INVALID_ARGUMENT);
17571
17572         player->set_mode.media_packet_video_stream = enable;
17573
17574         MMPLAYER_FLEAVE();
17575
17576         return MM_ERROR_NONE;
17577 }
17578
17579 void * _mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer)
17580 {
17581         void * ret = NULL
17582         MMPLAYER_FENTER();
17583         /* increase ref count of gst buffer */
17584         if (buffer)
17585                 ret = gst_buffer_ref((GstBuffer *)buffer);
17586
17587         MMPLAYER_FLEAVE();
17588         return ret;
17589 }
17590
17591 void _mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer)
17592 {
17593         MMPLAYER_FENTER();
17594         if (buffer) {
17595                 gst_buffer_unref((GstBuffer *)buffer);
17596                 buffer = NULL;
17597         }
17598         MMPLAYER_FLEAVE();
17599 }
17600
17601 void
17602 __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data)
17603 {
17604         mm_player_t *player  = (mm_player_t*)user_data;
17605         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
17606
17607         return_if_fail ( player );
17608
17609         debug_msg("app-src: feed audio\n");
17610
17611         if (player->media_stream_buffer_status_cb[type])
17612         {
17613                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
17614         }
17615 }
17616
17617 void
17618 __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data)
17619 {
17620         mm_player_t *player  = (mm_player_t*)user_data;
17621         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
17622
17623         return_if_fail ( player );
17624
17625         debug_msg("app-src: feed video\n");
17626
17627         if (player->media_stream_buffer_status_cb[type])
17628         {
17629                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
17630         }
17631 }
17632
17633 void
17634 __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data)
17635 {
17636         mm_player_t *player  = (mm_player_t*)user_data;
17637         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
17638
17639         return_if_fail ( player );
17640
17641         debug_msg("app-src: feed subtitle\n");
17642
17643         if (player->media_stream_buffer_status_cb[type])
17644         {
17645                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
17646         }
17647 }
17648
17649 void
17650 __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data)
17651 {
17652         mm_player_t *player  = (mm_player_t*)user_data;
17653         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
17654
17655         return_if_fail ( player );
17656
17657         debug_msg("app-src: audio buffer is full.\n");
17658
17659         if (player->media_stream_buffer_status_cb[type])
17660         {
17661                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
17662         }
17663 }
17664
17665 void
17666 __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data)
17667 {
17668         mm_player_t *player  = (mm_player_t*)user_data;
17669         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
17670
17671         return_if_fail ( player );
17672
17673         debug_msg("app-src: video buffer is full.\n");
17674
17675         if (player->media_stream_buffer_status_cb[type])
17676         {
17677                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
17678         }
17679 }
17680
17681 gboolean
17682 __gst_seek_audio_data (GstElement * appsrc, guint64 position, gpointer user_data)
17683 {
17684         mm_player_t *player  = (mm_player_t*)user_data;
17685         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
17686
17687         return_val_if_fail( player, FALSE );
17688
17689         debug_log("app-src: seek audio data\n");
17690
17691         if (player->media_stream_seek_data_cb[type])
17692         {
17693                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
17694         }
17695
17696         return TRUE;
17697 }
17698
17699 gboolean
17700 __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data)
17701 {
17702         mm_player_t *player  = (mm_player_t*)user_data;
17703         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
17704
17705         return_val_if_fail( player, FALSE );
17706
17707         debug_log("app-src: seek video data\n");
17708
17709         if (player->media_stream_seek_data_cb[type])
17710         {
17711                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
17712         }
17713
17714         return TRUE;
17715 }
17716
17717 gboolean
17718 __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data)
17719 {
17720         mm_player_t *player  = (mm_player_t*)user_data;
17721         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
17722
17723         return_val_if_fail( player, FALSE );
17724
17725         debug_log("app-src: seek subtitle data\n");
17726
17727         if (player->media_stream_seek_data_cb[type])
17728         {
17729                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
17730         }
17731
17732         return TRUE;
17733 }
17734