fix prevent issue #453398
[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 void __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad, gpointer data);
157 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
158 static void     __mmplayer_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
159 static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
160 static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
161
162 static void     __mmplayer_typefind_have_type(  GstElement *tf, guint probability, GstCaps *caps, gpointer data);
163 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
164 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
165 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
166 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
167 static void     __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
168 //static void   __mmplayer_check_video_zero_cpoy(mm_player_t* player, GstElementFactory* factory);
169
170 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
171 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
172 static void     __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
173
174 static void             __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data);
175 //static void    __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
176 static void             __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
177 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player );
178 static gboolean __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
179
180
181 static void     __mmplayer_init_factories(mm_player_t* player);
182 static void     __mmplayer_release_factories(mm_player_t* player);
183 static void             __mmplayer_release_misc(mm_player_t* player);
184 static void             __mmplayer_release_misc_post(mm_player_t* player);
185 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
186
187 static int              __mmplayer_gst_set_state (mm_player_t* player, GstElement * pipeline,  GstState state, gboolean async, gint timeout );
188 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
189 static gboolean      __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
190
191 int             __mmplayer_switch_audio_sink (mm_player_t* player);
192 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
193 static int              __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
194 static GstPadProbeReturn __mmplayer_audio_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
195 static GstPadProbeReturn __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
196 static GstPadProbeReturn __mmplayer_subtitle_adjust_position_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
197 static int __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index);
198
199 static gboolean __mmplayer_dump_pipeline_state( mm_player_t* player );
200 static gboolean __mmplayer_check_subtitle( mm_player_t* player );
201 static gboolean __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error );
202 static gboolean __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message );
203 static void             __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms );
204 static void     __mmplayer_cancel_eos_timer( mm_player_t* player );
205 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
206 static gboolean __mmplayer_link_decoder( mm_player_t* player,GstPad *srcpad);
207 static gboolean __mmplayer_link_sink( mm_player_t* player,GstPad *srcpad);
208 static int      __mmplayer_handle_missed_plugin(mm_player_t* player);
209 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
210 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
211 static void     __mmplayer_add_sink( mm_player_t* player, GstElement* sink);
212 static void     __mmplayer_del_sink( mm_player_t* player, GstElement* sink);
213 static void     __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
214 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force);
215 static gpointer __mmplayer_next_play_thread(gpointer data);
216 static gpointer __mmplayer_repeat_thread(gpointer data);
217 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
218
219
220 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
221 static GstPadProbeReturn __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data);
222 static void __mmplayer_release_dump_list (GList *dump_list);
223
224 static int              __gst_realize(mm_player_t* player);
225 static int              __gst_unrealize(mm_player_t* player);
226 static int              __gst_start(mm_player_t* player);
227 static int              __gst_stop(mm_player_t* player);
228 static int              __gst_pause(mm_player_t* player, gboolean async);
229 static int              __gst_resume(mm_player_t* player, gboolean async);
230 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
231                                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
232                                         gint64 cur, GstSeekType stop_type, gint64 stop );
233 static int __gst_pending_seek ( mm_player_t* player );
234
235 static int              __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called);
236 static int              __gst_get_position(mm_player_t* player, int format, unsigned long *position);
237 static int              __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
238 static int              __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
239 static int              __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
240
241 static gint     __gst_handle_core_error( mm_player_t* player, int code );
242 static gint     __gst_handle_library_error( mm_player_t* player, int code );
243 static gint     __gst_handle_resource_error( mm_player_t* player, int code );
244 static gint     __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message );
245 static gint             __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error);
246 static gboolean __gst_send_event_to_sink( mm_player_t* player, GstEvent* event );
247
248 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
249 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
250
251 /*fadeout */
252 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
253 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
254
255 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
256 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
257
258 /* util */
259 const gchar * __get_state_name ( int state );
260 static gboolean __is_streaming( mm_player_t* player );
261 static gboolean __is_rtsp_streaming( mm_player_t* player );
262 static gboolean __is_wfd_streaming( mm_player_t* player );
263 static gboolean __is_live_streaming ( mm_player_t* player );
264 static gboolean __is_http_streaming( mm_player_t* player );
265 static gboolean __is_http_live_streaming( mm_player_t* player );
266 static gboolean __is_dash_streaming( mm_player_t* player );
267 static gboolean __is_smooth_streaming( mm_player_t* player );
268 static gboolean __is_http_progressive_down(mm_player_t* player);
269 static gboolean __is_es_buff_src(mm_player_t* player);
270 static gboolean __has_suffix(mm_player_t * player, const gchar * suffix);
271
272 static GstBusSyncReply __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data);
273
274 static int  __mmplayer_realize_streaming_ext(mm_player_t* player);
275 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
276 static int __mmplayer_start_streaming_ext(mm_player_t *player);
277 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
278 static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
279 static void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id);
280
281 static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
282 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
283 static void __mmplayer_check_pipeline(mm_player_t* player);
284 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
285 static void __mmplayer_deactivate_old_path(mm_player_t *player);
286 #if 0 // We'll need this in future.
287 static int __mmplayer_gst_switching_element(mm_player_t *player, GstElement *search_from, const gchar *removal_name, const gchar *new_element_name);
288 #endif
289
290 static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg);
291 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
292 static gboolean __mmplayer_can_do_interrupt(mm_player_t *player);
293
294 /* device change post proc */
295 void __mmplayer_device_change_post_process(gpointer user);
296 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score);
297 void __mmplayer_inc_cb_score(mm_player_t* player);
298 void __mmplayer_post_proc_reset(mm_player_t* player);
299 void __mmplayer_device_change_trigger_post_process(mm_player_t* player);
300 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
301 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name);
302 static void             __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data);
303 static void             __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data);
304 static void     __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data);
305 static void             __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data);
306 static void             __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data);
307 static gboolean __gst_seek_audio_data (GstElement * appsrc, guint64 position, gpointer user_data);
308 static gboolean __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data);
309 static gboolean __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data);
310 /*===========================================================================================
311 |                                                                                                                                                                                       |
312 |  FUNCTION DEFINITIONS                                                                                                                                         |
313 |                                                                                                                                                                                       |
314 ========================================================================================== */
315
316 #if 0 //debug
317 static void
318 print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
319 {
320   gint i, count;
321
322   count = gst_tag_list_get_tag_size (list, tag);
323
324   debug_log("count = %d", count);
325
326   for (i = 0; i < count; i++) {
327     gchar *str;
328
329     if (gst_tag_get_type (tag) == G_TYPE_STRING) {
330       if (!gst_tag_list_get_string_index (list, tag, i, &str))
331         g_assert_not_reached ();
332     } else {
333       str =
334           g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
335     }
336
337     if (i == 0) {
338       g_print ("  %15s: %s\n", gst_tag_get_nick (tag), str);
339     } else {
340       g_print ("                 : %s\n", str);
341     }
342
343     g_free (str);
344   }
345 }
346 #endif
347
348 /* implementing player FSM */
349 /* FIXIT : We need to handle state transition also at here since start api is no more sync */
350 static int
351 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
352 {
353         MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
354         MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
355 //      MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
356 //      MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
357
358         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
359
360         //debug_log("incomming command : %d \n", command );
361
362         current_state = MMPLAYER_CURRENT_STATE(player);
363         pending_state = MMPLAYER_PENDING_STATE(player);
364 //      target_state = MMPLAYER_TARGET_STATE(player);
365 //      prev_state = MMPLAYER_PREV_STATE(player);
366
367         MMPLAYER_PRINT_STATE(player);
368
369         switch( command )
370         {
371                 case MMPLAYER_COMMAND_CREATE:
372                 {
373                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
374
375                         if ( current_state == MM_PLAYER_STATE_NULL ||
376                                 current_state == MM_PLAYER_STATE_READY ||
377                                 current_state == MM_PLAYER_STATE_PAUSED ||
378                                 current_state == MM_PLAYER_STATE_PLAYING )
379                                 goto NO_OP;
380                 }
381                 break;
382
383                 case MMPLAYER_COMMAND_DESTROY:
384                 {
385                         /* destroy can called anytime */
386
387                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
388                 }
389                 break;
390
391                 case MMPLAYER_COMMAND_REALIZE:
392                 {
393                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
394
395                         if ( pending_state != MM_PLAYER_STATE_NONE )
396                         {
397                                 goto INVALID_STATE;
398                         }
399                         else
400                         {
401                                 /* need ready state to realize */
402                                 if ( current_state == MM_PLAYER_STATE_READY )
403                                         goto NO_OP;
404
405                                 if ( current_state != MM_PLAYER_STATE_NULL )
406                                         goto INVALID_STATE;
407                         }
408                 }
409                 break;
410
411                 case MMPLAYER_COMMAND_UNREALIZE:
412                 {
413                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
414
415                         if ( current_state == MM_PLAYER_STATE_NULL )
416                                 goto NO_OP;
417                 }
418                 break;
419
420                 case MMPLAYER_COMMAND_START:
421                 {
422                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
423
424                         if ( pending_state == MM_PLAYER_STATE_NONE )
425                         {
426                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
427                                         goto NO_OP;
428                                 else if ( current_state  != MM_PLAYER_STATE_READY &&
429                                         current_state != MM_PLAYER_STATE_PAUSED )
430                                         goto INVALID_STATE;
431                         }
432                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
433                         {
434                                 goto ALREADY_GOING;
435                         }
436                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
437                         {
438                                 debug_log("player is going to paused state, just change the pending state as playing");
439                         }
440                         else
441                         {
442                                 goto INVALID_STATE;
443                         }
444                 }
445                 break;
446
447                 case MMPLAYER_COMMAND_STOP:
448                 {
449                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
450
451                         if ( current_state == MM_PLAYER_STATE_READY )
452                                 goto NO_OP;
453
454                         /* need playing/paused state to stop */
455                         if ( current_state != MM_PLAYER_STATE_PLAYING &&
456                                  current_state != MM_PLAYER_STATE_PAUSED )
457                                 goto INVALID_STATE;
458                 }
459                 break;
460
461                 case MMPLAYER_COMMAND_PAUSE:
462                 {
463                         if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
464                                 goto NO_OP;
465
466                         if (player->doing_seek)
467                                 goto NOT_COMPLETED_SEEK;
468
469                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
470
471                         if ( pending_state == MM_PLAYER_STATE_NONE )
472                         {
473                                 if ( current_state == MM_PLAYER_STATE_PAUSED )
474                                         goto NO_OP;
475                                 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
476                                         goto INVALID_STATE;
477                         }
478                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
479                         {
480                                 goto ALREADY_GOING;
481                         }
482                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
483                         {
484                                 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
485                                         debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
486                                 } else {
487                                         goto INVALID_STATE;
488                                 }
489                         }
490                 }
491                 break;
492
493                 case MMPLAYER_COMMAND_RESUME:
494                 {
495
496                         if (player->doing_seek)
497                                 goto NOT_COMPLETED_SEEK;
498
499                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
500
501                         if ( pending_state == MM_PLAYER_STATE_NONE )
502                         {
503                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
504                                         goto NO_OP;
505                                 else if (  current_state != MM_PLAYER_STATE_PAUSED )
506                                         goto INVALID_STATE;
507                         }
508                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
509                         {
510                                 goto ALREADY_GOING;
511                         }
512                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
513                         {
514                                 debug_log("player is going to paused state, just change the pending state as playing");
515                         }
516                         else
517                         {
518                                 goto INVALID_STATE;
519                         }
520                 }
521                 break;
522
523                 default:
524                 break;
525         }
526         player->cmd = command;
527
528         return MM_ERROR_NONE;
529
530 INVALID_STATE:
531         debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
532                 MMPLAYER_STATE_GET_NAME(current_state), command);
533         return MM_ERROR_PLAYER_INVALID_STATE;
534
535 NOT_COMPLETED_SEEK:
536         debug_warning("not completed seek");
537         return MM_ERROR_PLAYER_DOING_SEEK;
538
539 NO_OP:
540         debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
541         return MM_ERROR_PLAYER_NO_OP;
542
543 ALREADY_GOING:
544         debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
545         return MM_ERROR_PLAYER_NO_OP;
546 }
547
548 int
549 __mmplayer_gst_set_state (mm_player_t* player, GstElement * element,  GstState state, gboolean async, gint timeout) // @
550 {
551         GstState element_state = GST_STATE_VOID_PENDING;
552         GstState element_pending_state = GST_STATE_VOID_PENDING;
553         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
554
555         MMPLAYER_FENTER();
556
557         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
558         return_val_if_fail ( element, MM_ERROR_INVALID_ARGUMENT );
559
560         debug_log("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
561
562         /* set state */
563         ret = gst_element_set_state(element, state);
564
565         if ( ret == GST_STATE_CHANGE_FAILURE )
566         {
567                 debug_error("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
568
569                 /* dump state of all element */
570                 __mmplayer_dump_pipeline_state( player );
571
572                 return MM_ERROR_PLAYER_INTERNAL;
573         }
574
575         /* return here so state transition to be done in async mode */
576         if ( async )
577         {
578                 debug_log("async state transition. not waiting for state complete.\n");
579                 return MM_ERROR_NONE;
580         }
581
582         /* wait for state transition */
583         ret = gst_element_get_state( element, &element_state, &element_pending_state, timeout * GST_SECOND );
584
585         if ( ret == GST_STATE_CHANGE_FAILURE || ( state != element_state ) )
586         {
587                 debug_error("failed to change [%s] element state to [%s] within %d sec\n",
588                         GST_ELEMENT_NAME(element),
589                         gst_element_state_get_name(state), timeout );
590
591                 debug_error(" [%s] state : %s   pending : %s \n",
592                         GST_ELEMENT_NAME(element),
593                         gst_element_state_get_name(element_state),
594                         gst_element_state_get_name(element_pending_state) );
595
596                 /* dump state of all element */
597                 __mmplayer_dump_pipeline_state( player );
598
599                 return MM_ERROR_PLAYER_INTERNAL;
600         }
601
602         debug_log("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
603
604         MMPLAYER_FLEAVE();
605
606         return MM_ERROR_NONE;
607 }
608
609 static void
610 __mmplayer_videostream_cb(GstElement *element, void *data,
611 int width, int height, gpointer user_data) // @
612 {
613         mm_player_t* player = (mm_player_t*)user_data;
614
615         return_if_fail ( player );
616
617         MMPLAYER_FENTER();
618
619         if (player->is_drm_file)
620         {
621                 MMMessageParamType msg_param = { 0, };
622                 debug_warning("not supported in drm file");
623                 msg_param.code = MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
624                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
625         }
626         else if ( !player->set_mode.media_packet_video_stream && player->video_stream_cb)
627         {
628                 MMPlayerVideoStreamDataType stream;
629
630                 /* clear stream data structure */
631                 memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
632
633                 stream.data[0] = data;
634                 stream.length_total = width * height * 4; // for rgb 32bit
635                 stream.height = height;
636                 stream.width = width;
637                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
638         }
639
640         MMPLAYER_FLEAVE();
641 }
642
643 static void
644 __mmplayer_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer data)
645 {
646         mm_player_t* player = (mm_player_t*)data;
647
648         return_if_fail ( player );
649
650         MMPLAYER_FENTER();
651
652         if (player->video_frame_render_error_cb )
653         {
654                 if (player->attrs)
655                 {
656                         int surface_type = 0;
657                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
658                         switch (surface_type)
659                         {
660                         case MM_DISPLAY_SURFACE_X_EXT:
661                                 player->video_frame_render_error_cb((unsigned int*)error_id, player->video_frame_render_error_cb_user_param);
662                                 debug_log("display surface type(X_EXT) : render error callback(%p) is finished", player->video_frame_render_error_cb);
663                                 break;
664                         default:
665                                 debug_error("video_frame_render_error_cb was set, but this surface type(%d) is not supported", surface_type);
666                                 break;
667                         }
668                 }
669                 else
670                 {
671                         debug_error("could not get surface type");
672                 }
673         }
674         else
675         {
676                 debug_warning("video_frame_render_error_cb was not set");
677         }
678
679         MMPLAYER_FLEAVE();
680 }
681
682 void
683 __mmplayer_device_change_post_process(gpointer user)
684 {
685         mm_player_t* player = (mm_player_t*)user;
686         unsigned long position = 0;
687         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
688         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
689
690         MMPLAYER_FENTER();
691
692         if (! player ||
693                 ! player->pipeline ||
694                 ! player->pipeline->mainbin ||
695                 ! player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
696         {
697                 goto EXIT;
698         }
699
700         current_state = MMPLAYER_CURRENT_STATE(player);
701         pending_state = MMPLAYER_PENDING_STATE(player);
702
703         if (player->post_proc.need_pause_and_resume)
704         {
705                 debug_log("pausing");
706                 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
707                         ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
708                         gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED);
709         }
710
711         /* seek should be done within pause and resume */
712         if (player->post_proc.need_seek)
713         {
714                 debug_log("seeking");
715                 __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position);
716                 debug_log(">> seek to current position = %ld ms", position);
717                 __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE);
718         }
719
720         if (player->post_proc.need_pause_and_resume)
721         {
722                 debug_log("resuming");
723                 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
724                         ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
725                         gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING);
726         }
727
728         /* async */
729         if (player->post_proc.need_async)
730         {
731                 debug_log("setting async");
732
733                 /* TODO : need some comment here */
734                 if (player->pipeline->textbin && player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst)
735                         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
736         }
737
738 EXIT:
739         /* reset all */
740         __mmplayer_post_proc_reset(player);
741         return;
742 }
743
744 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score)
745 {
746         return_if_fail(player);
747         player->post_proc.required_cb_score = score;
748         debug_log("set required score to : %d", score);
749 }
750
751 void __mmplayer_inc_cb_score(mm_player_t* player)
752 {
753         return_if_fail(player);
754         player->post_proc.cb_score++;
755         debug_log("post proc cb score increased to %d", player->post_proc.cb_score);
756 }
757
758 void __mmplayer_post_proc_reset(mm_player_t* player)
759 {
760         return_if_fail(player);
761
762         /* check if already triggered */
763         if (player->post_proc.id)
764         {
765                 /* TODO : need to consider multiple main context. !!!! */
766                 if (FALSE == g_source_remove(player->post_proc.id) )
767                 {
768                         debug_error("failed to remove exist post_proc item");
769                 }
770                 player->post_proc.id = 0;
771         }
772
773         memset(&player->post_proc, 0, sizeof(mm_player_post_proc_t));
774
775         /* set default required cb score 1 as only audio device has changed in this case.
776            if display status is changed with audio device, required cb score is set 2 in display status callback.
777            this logic bases on the assumption which audio device callback is called after calling display status callback. */
778         player->post_proc.required_cb_score = 1;
779 }
780
781 void
782 __mmplayer_device_change_trigger_post_process(mm_player_t* player)
783 {
784         return_if_fail(player);
785
786         /* check score */
787         if ( player->post_proc.cb_score < player->post_proc.required_cb_score )
788         {
789                 /* wait for next turn */
790                 debug_log("wait for next turn. required cb score : %d   current score : %d\n",
791                         player->post_proc.required_cb_score, player->post_proc.cb_score);
792                 return;
793         }
794
795         /* check if already triggered */
796         if (player->post_proc.id)
797         {
798                 /* TODO : need to consider multiple main context. !!!! */
799                 if (FALSE == g_source_remove(player->post_proc.id) )
800                 {
801                         debug_error("failed to remove exist post_proc item");
802                 }
803                 player->post_proc.id = 0;
804         }
805
806         player->post_proc.id = g_idle_add((GSourceFunc)__mmplayer_device_change_post_process, (gpointer)player);
807 }
808
809 /* NOTE : Sound module has different latency according to output device So,
810  * synchronization problem can be happened whenever device is changed.
811  * To avoid this issue, we do reset avsystem or seek as workaroud.
812  */
813 static void
814 __mmplayer_sound_device_info_changed_cb_func (MMSoundDevice_t device_h, int changed_info_type, void *user_data)
815 {
816     int ret;
817     mm_sound_device_type_e device_type;
818         mm_player_t* player = (mm_player_t*) user_data;
819
820         return_if_fail( player );
821
822         debug_warning("device_info_changed_cb is called, device_h[0x%x], changed_info_type[%d]\n", device_h, changed_info_type);
823
824         __mmplayer_inc_cb_score(player);
825
826         /* get device type with device_h*/
827         ret = mm_sound_get_device_type(device_h, &device_type);
828         if (ret) {
829                 debug_error("failed to mm_sound_get_device_type()\n");
830         }
831
832         /* do pause and resume only if video is playing  */
833         if ( player->videodec_linked && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING )
834         {
835                 switch (device_type)
836                 {
837                         case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
838                         case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
839                         case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
840                         case MM_SOUND_DEVICE_TYPE_HDMI:
841                         case MM_SOUND_DEVICE_TYPE_MIRRORING:
842                         {
843                                 player->post_proc.need_pause_and_resume = TRUE;
844                         }
845                         break;
846
847                         default:
848                                 debug_log("do nothing");
849                 }
850         }
851         debug_warning("dispatched");
852
853         __mmplayer_device_change_trigger_post_process(player);
854 }
855
856 /* This function should be called after the pipeline goes PAUSED or higher
857 state. */
858 gboolean
859 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
860 {
861         static gboolean has_duration = FALSE;
862         static gboolean has_video_attrs = FALSE;
863         static gboolean has_audio_attrs = FALSE;
864         static gboolean has_bitrate = FALSE;
865         gboolean missing_only = FALSE;
866         gboolean all = FALSE;
867         gint64 dur_nsec = 0;
868         GstStructure* p = NULL;
869         MMHandleType attrs = 0;
870         gchar *path = NULL;
871         gint stream_service_type = STREAMING_SERVICE_NONE;
872         struct stat sb;
873
874         MMPLAYER_FENTER();
875
876         return_val_if_fail ( player, FALSE );
877
878         /* check player state here */
879         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
880                 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING )
881         {
882                 /* give warning now only */
883                 debug_warning("be careful. content attributes may not available in this state ");
884         }
885
886         /* get content attribute first */
887         attrs = MMPLAYER_GET_ATTRS(player);
888         if ( !attrs )
889         {
890                 debug_error("cannot get content attribute");
891                 return FALSE;
892         }
893
894         /* get update flag */
895
896         if ( flag & ATTR_MISSING_ONLY )
897         {
898                 missing_only = TRUE;
899                 debug_log("updating missed attr only");
900         }
901
902         if ( flag & ATTR_ALL )
903         {
904                 all = TRUE;
905                 has_duration = FALSE;
906                 has_video_attrs = FALSE;
907                 has_audio_attrs = FALSE;
908                 has_bitrate = FALSE;
909
910                 debug_log("updating all attrs");
911         }
912
913         if ( missing_only && all )
914         {
915                 debug_warning("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
916                 missing_only = FALSE;
917         }
918
919         if (  (flag & ATTR_DURATION) || (!has_duration && missing_only) || all )
920         {
921                 debug_log("try to update duration");
922                 has_duration = FALSE;
923
924                 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
925                 {
926                         player->duration = dur_nsec;
927                         debug_warning("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
928                 }
929
930                 /* try to get streaming service type */
931                 stream_service_type = __mmplayer_get_stream_service_type( player );
932                 mm_attrs_set_int_by_name ( attrs, "streaming_type", stream_service_type );
933
934                 /* check duration is OK */
935                 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
936                 {
937                         /* FIXIT : find another way to get duration here. */
938                         debug_error("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
939                 }
940                 else
941                 {
942                         /*update duration */
943                         mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
944                         has_duration = TRUE;
945                 }
946         }
947
948         if (  (flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all )
949         {
950                 /* update audio params
951                 NOTE : We need original audio params and it can be only obtained from src pad of audio
952                 decoder. Below code only valid when we are not using 'resampler' just before
953                 'audioconverter'. */
954
955                 debug_log("try to update audio attrs");
956                 has_audio_attrs = FALSE;
957
958                 if ( player->pipeline->audiobin &&
959                          player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
960                 {
961                         GstCaps *caps_a = NULL;
962                         GstPad* pad = NULL;
963                         gint samplerate = 0, channels = 0;
964
965                         pad = gst_element_get_static_pad(
966                                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
967
968                         if ( pad )
969                         {
970                                 caps_a = gst_pad_get_current_caps( pad );
971
972                                 if ( caps_a )
973                                 {
974                                         p = gst_caps_get_structure (caps_a, 0);
975
976                                         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
977
978                                         gst_structure_get_int (p, "rate", &samplerate);
979                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
980
981                                         gst_structure_get_int (p, "channels", &channels);
982                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
983
984                                         secure_debug_log("samplerate : %d       channels : %d", samplerate, channels);
985
986                                         gst_caps_unref( caps_a );
987                                         caps_a = NULL;
988
989                                         has_audio_attrs = TRUE;
990                                 }
991                                 else
992                                 {
993                                         debug_warning("not ready to get audio caps");
994                                 }
995
996                                 gst_object_unref( pad );
997                         }
998                         else
999                         {
1000                                 debug_warning("failed to get pad from audiosink");
1001                         }
1002                 }
1003         }
1004
1005         if ( (flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all )
1006         {
1007                 debug_log("try to update video attrs");
1008                 has_video_attrs = FALSE;
1009
1010                 if ( player->pipeline->videobin &&
1011                          player->pipeline->videobin[MMPLAYER_V_SINK].gst )
1012                 {
1013                         GstCaps *caps_v = NULL;
1014                         GstPad* pad = NULL;
1015                         gint tmpNu, tmpDe;
1016                         gint width, height;
1017
1018                         pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
1019                         if ( pad )
1020                         {
1021                                 caps_v = gst_pad_get_current_caps( pad );
1022
1023                                 /* Use v_stream_caps, if fail to get video_sink sink pad*/
1024                                 if (!caps_v && player->v_stream_caps)
1025                                 {
1026                                         caps_v = player->v_stream_caps;
1027                                         gst_caps_ref(caps_v);
1028                                 }
1029
1030                                 if (caps_v)
1031                                 {
1032                                         p = gst_caps_get_structure (caps_v, 0);
1033                                         gst_structure_get_int (p, "width", &width);
1034                                         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
1035
1036                                         gst_structure_get_int (p, "height", &height);
1037                                         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
1038
1039                                         gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
1040
1041                                         secure_debug_log("width : %d     height : %d", width, height );
1042
1043                                         gst_caps_unref( caps_v );
1044                                         caps_v = NULL;
1045
1046                                         if (tmpDe > 0)
1047                                         {
1048                                                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
1049                                                 secure_debug_log("fps : %d", tmpNu / tmpDe);
1050                                         }
1051
1052                                         has_video_attrs = TRUE;
1053                                 }
1054                                 else
1055                                 {
1056                                         debug_log("no negitiated caps from videosink");
1057                                 }
1058                                 gst_object_unref( pad );
1059                                 pad = NULL;
1060                         }
1061                         else
1062                         {
1063                                 debug_log("no videosink sink pad");
1064                         }
1065                 }
1066         }
1067
1068
1069         if ( (flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all )
1070         {
1071                 has_bitrate = FALSE;
1072
1073                 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
1074                 if (player->duration)
1075                 {
1076                         guint64 data_size = 0;
1077
1078                         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1079                         {
1080                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1081
1082                                 if (stat(path, &sb) == 0)
1083                                 {
1084                                         data_size = (guint64)sb.st_size;
1085                                 }
1086                         }
1087                         else if (MMPLAYER_IS_HTTP_STREAMING(player))
1088                         {
1089                                 data_size = player->http_content_size;
1090                         }
1091                         debug_log("try to update bitrate : data_size = %lld", data_size);
1092
1093                         if (data_size)
1094                         {
1095                                 guint64 bitrate = 0;
1096                                 guint64 msec_dur = 0;
1097
1098                                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
1099                                 bitrate = data_size * 8 * 1000 / msec_dur;
1100                                 secure_debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
1101                                 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
1102
1103                                 has_bitrate = TRUE;
1104                         }
1105
1106                         if (MMPLAYER_IS_RTSP_STREAMING(player))
1107                         {
1108                                 if(player->total_bitrate)
1109                                 {
1110                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
1111                                         has_bitrate = TRUE;
1112                                 }
1113                         }
1114                 }
1115         }
1116
1117         /* validate all */
1118         if (  mmf_attrs_commit ( attrs ) )
1119         {
1120                 debug_error("failed to update attributes\n");
1121                 return FALSE;
1122         }
1123
1124         MMPLAYER_FLEAVE();
1125
1126         return TRUE;
1127 }
1128
1129 gint __mmplayer_get_stream_service_type( mm_player_t* player )
1130 {
1131         gint streaming_type = STREAMING_SERVICE_NONE;
1132
1133         MMPLAYER_FENTER();
1134
1135         return_val_if_fail ( player &&
1136                         player->pipeline &&
1137                         player->pipeline->mainbin &&
1138                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
1139                         FALSE );
1140
1141         /* streaming service type if streaming */
1142         if ( ! MMPLAYER_IS_STREAMING(player) )
1143                 return STREAMING_SERVICE_NONE;
1144
1145         if (MMPLAYER_IS_HTTP_STREAMING(player))
1146         {
1147                 streaming_type = (player->duration == 0) ?
1148                         STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
1149         }
1150
1151         switch ( streaming_type )
1152         {
1153                 case STREAMING_SERVICE_LIVE:
1154                         debug_log("it's live streaming");
1155                 break;
1156                 case STREAMING_SERVICE_VOD:
1157                         debug_log("it's vod streaming");
1158                 break;
1159                 case STREAMING_SERVICE_NONE:
1160                         debug_error("should not get here");
1161                 break;
1162                 default:
1163                         debug_error("should not get here");
1164         }
1165
1166         player->streaming_type = streaming_type;
1167         MMPLAYER_FLEAVE();
1168
1169         return streaming_type;
1170 }
1171
1172
1173 /* this function sets the player state and also report
1174  * it to applicaton by calling callback function
1175  */
1176 static int
1177 __mmplayer_set_state(mm_player_t* player, int state) // @
1178 {
1179         MMMessageParamType msg = {0, };
1180         int asm_result = MM_ERROR_NONE;
1181         gboolean post_bos = FALSE;
1182         gboolean interrupted_by_asm = FALSE;
1183         int ret = MM_ERROR_NONE;
1184
1185         return_val_if_fail ( player, FALSE );
1186
1187         if ( MMPLAYER_CURRENT_STATE(player) == state )
1188         {
1189                 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
1190                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1191                 return ret;
1192         }
1193
1194         /* update player states */
1195         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
1196         MMPLAYER_CURRENT_STATE(player) = state;
1197
1198         /* FIXIT : it's better to do like below code
1199         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player) )
1200                         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1201         and add more code to handling PENDING_STATE.
1202         */
1203         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
1204                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1205
1206         /* print state */
1207         MMPLAYER_PRINT_STATE(player);
1208
1209         /* do some FSM stuffs before posting new state to application  */
1210         interrupted_by_asm = player->sm.by_asm_cb;
1211
1212         switch ( MMPLAYER_CURRENT_STATE(player) )
1213         {
1214                 case MM_PLAYER_STATE_NULL:
1215                 case MM_PLAYER_STATE_READY:
1216                 {
1217                         if (player->cmd == MMPLAYER_COMMAND_STOP)
1218                         {
1219                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP, FALSE);
1220                                 if ( asm_result != MM_ERROR_NONE )
1221                                 {
1222                                         debug_error("failed to set asm state to stop\n");
1223                                         return MM_ERROR_POLICY_INTERNAL;
1224                                 }
1225                         }
1226                 }
1227                 break;
1228
1229                 case MM_PLAYER_STATE_PAUSED:
1230                 {
1231                          if ( ! player->sent_bos )
1232                          {
1233                                 int found = 0;
1234                                 #define MMPLAYER_MAX_SOUND_PRIORITY     3
1235
1236                                 /* it's first time to update all content attrs. */
1237                                 _mmplayer_update_content_attrs( player, ATTR_ALL );
1238                                 /* set max sound priority to keep own sound and not to mute other's one */
1239                                 mm_attrs_get_int_by_name(player->attrs, "content_video_found", &found);
1240                                 if (found)
1241                                 {
1242                                         mm_attrs_get_int_by_name(player->attrs, "content_audio_found", &found);
1243                                         if (found)
1244                                         {
1245                                                 debug_log("set max audio priority");
1246                                                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "priority", MMPLAYER_MAX_SOUND_PRIORITY, NULL);
1247                                         }
1248                                 }
1249
1250                          }
1251
1252                         /* add audio callback probe if condition is satisfied */
1253                         if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
1254                         {
1255                                 __mmplayer_configure_audio_callback(player);
1256                                 /* FIXIT : handle return value */
1257                         }
1258
1259                         if (!MMPLAYER_IS_STREAMING(player) || (player->streamer && !player->streamer->is_buffering))
1260                         {
1261                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE, FALSE);
1262                                 if ( asm_result )
1263                                 {
1264                                         debug_error("failed to set asm state to PAUSE\n");
1265                                         return MM_ERROR_POLICY_INTERNAL;
1266                                 }
1267                         }
1268                 }
1269                 break;
1270
1271                 case MM_PLAYER_STATE_PLAYING:
1272                 {
1273                         /* try to get content metadata */
1274                         if ( ! player->sent_bos )
1275                         {
1276                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
1277                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
1278                                  * legacy mmfw-player api */
1279                                 _mmplayer_update_content_attrs( player, ATTR_MISSING_ONLY);
1280                         }
1281
1282                         if ( (player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME) )
1283                         {
1284                                 if (!player->sent_bos)
1285                                 {
1286                                         __mmplayer_handle_missed_plugin ( player );
1287                                 }
1288
1289                                 /* update ASM state for video and streaming buffering */
1290                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING, TRUE);
1291                                 if (asm_result != MM_ERROR_NONE)
1292                                 {
1293                                         if (player->pipeline->videobin)
1294                                         {
1295                                                 MMMessageParamType msg = {0, };
1296
1297                                                 debug_error("failed to go ahead because of video conflict\n");
1298
1299                                                 msg.union_type = MM_MSG_UNION_CODE;
1300                                                 msg.code = MM_ERROR_POLICY_INTERRUPTED;
1301                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
1302
1303                                                 _mmplayer_unrealize((MMHandleType)player);
1304                                         }
1305                                         else
1306                                         {
1307                                                 debug_error("failed to play by ASM error : 0x%X\n", asm_result);
1308                                                 _mmplayer_pause((MMHandleType)player);
1309                                                 return asm_result;
1310                                         }
1311
1312                                         return MM_ERROR_POLICY_INTERNAL;
1313                                 }
1314                         }
1315
1316                         if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
1317                         {
1318                                 /* initialize because auto resume is done well. */
1319                                 player->resumed_by_rewind = FALSE;
1320                                 player->playback_rate = 1.0;
1321                         }
1322
1323                         if ( !player->sent_bos )
1324                         {
1325                                 /* check audio codec field is set or not
1326                                  * we can get it from typefinder or codec's caps.
1327                                  */
1328                                 gchar *audio_codec = NULL;
1329                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
1330
1331                                 /* The codec format can't be sent for audio only case like amr, mid etc.
1332                                  * Because, parser don't make related TAG.
1333                                  * So, if it's not set yet, fill it with found data.
1334                                  */
1335                                 if ( ! audio_codec )
1336                                 {
1337                                         if ( g_strrstr(player->type, "audio/midi"))
1338                                         {
1339                                                 audio_codec = g_strdup("MIDI");
1340
1341                                         }
1342                                         else if ( g_strrstr(player->type, "audio/x-amr"))
1343                                         {
1344                                                 audio_codec = g_strdup("AMR");
1345                                         }
1346                                         else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
1347                                         {
1348                                                 audio_codec = g_strdup("AAC");
1349                                         }
1350                                         else
1351                                         {
1352                                                 audio_codec = g_strdup("unknown");
1353                                         }
1354                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1355
1356                                         MMPLAYER_FREEIF(audio_codec);
1357                                         mmf_attrs_commit(player->attrs);
1358                                         debug_log("set audio codec type with caps\n");
1359                                 }
1360
1361                                 post_bos = TRUE;
1362                         }
1363                 }
1364                 break;
1365
1366                 case MM_PLAYER_STATE_NONE:
1367                 default:
1368                         debug_warning("invalid target state, there is nothing to do.\n");
1369                         break;
1370         }
1371
1372
1373         /* post message to application */
1374         if (MMPLAYER_TARGET_STATE(player) == state)
1375         {
1376                 /* fill the message with state of player */
1377                 msg.state.previous = MMPLAYER_PREV_STATE(player);
1378                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
1379
1380                 debug_log ("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
1381
1382                 /* state changed by asm callback */
1383                 if ( interrupted_by_asm )
1384                 {
1385                         msg.union_type = MM_MSG_UNION_CODE;
1386                         msg.code = player->sm.event_src;
1387                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
1388                 }
1389                 /* state changed by usecase */
1390                 else
1391                 {
1392                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
1393                 }
1394         }
1395         else
1396         {
1397                 debug_log ("intermediate state, do nothing.\n");
1398                 MMPLAYER_PRINT_STATE(player);
1399                 return ret;
1400         }
1401
1402         if ( post_bos )
1403         {
1404                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
1405                 player->sent_bos = TRUE;
1406         }
1407
1408         return ret;
1409 }
1410
1411 gboolean
1412 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
1413 {
1414         return_val_if_fail( player, FALSE );
1415
1416         if ( !player->msg_cb )
1417         {
1418                 return FALSE;
1419         }
1420
1421         //debug_log("Message (type : %d)  will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
1422
1423         player->msg_cb(msgtype, param, player->msg_cb_param);
1424
1425         return TRUE;
1426 }
1427
1428 static gpointer __mmplayer_next_play_thread(gpointer data)
1429 {
1430         mm_player_t* player = (mm_player_t*) data;
1431         MMPlayerGstElement *mainbin = NULL;
1432
1433         return_val_if_fail ( player, NULL );
1434
1435         g_mutex_lock(&player->next_play_thread_mutex);
1436         while ( ! player->next_play_thread_exit )
1437         {
1438                 debug_log("next play thread started. waiting for signal.\n");
1439                 g_cond_wait(&player->next_play_thread_cond, &player->next_play_thread_mutex );
1440
1441                 debug_log("reconfigure pipeline for gapless play.\n");
1442
1443                 if ( player->next_play_thread_exit )
1444                 {
1445                         if(player->gapless.reconfigure)
1446                         {
1447                                 player->gapless.reconfigure = false;
1448                                 MMPLAYER_PLAYBACK_UNLOCK(player);
1449                         }
1450                         debug_log("exiting gapless play thread\n");
1451                         break;
1452                 }
1453
1454                 mainbin = player->pipeline->mainbin;
1455
1456                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
1457                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
1458                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
1459                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
1460                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
1461
1462                 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
1463         }
1464         g_mutex_unlock(&player->next_play_thread_mutex);
1465
1466         return NULL;
1467 }
1468
1469 static gpointer __mmplayer_repeat_thread(gpointer data)
1470 {
1471         mm_player_t* player = (mm_player_t*) data;
1472         gboolean ret_value = FALSE;
1473         MMHandleType attrs = 0;
1474         gint count = 0;
1475
1476         return_val_if_fail ( player, NULL );
1477
1478         g_mutex_lock(&player->repeat_thread_mutex);
1479         while ( ! player->repeat_thread_exit )
1480         {
1481                 debug_log("repeat thread started. waiting for signal.\n");
1482                 g_cond_wait(&player->repeat_thread_cond, &player->repeat_thread_mutex );
1483
1484                 if ( player->repeat_thread_exit )
1485                 {
1486                         debug_log("exiting repeat thread\n");
1487                         break;
1488                 }
1489
1490
1491                 /* lock */
1492                 g_mutex_lock(&player->cmd_lock);
1493
1494                 attrs = MMPLAYER_GET_ATTRS(player);
1495
1496                 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1497                 {
1498                         debug_error("can not get play count\n");
1499                         break;
1500                 }
1501
1502                 if ( player->section_repeat )
1503                 {
1504                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1505                 }
1506                 else
1507                 {
1508                         if ( player->playback_rate < 0.0 )
1509                         {
1510                                 player->resumed_by_rewind = TRUE;
1511                                 _mmplayer_set_mute((MMHandleType)player, 0);
1512                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1513                         }
1514
1515                         ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
1516                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1517                                 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1518
1519                         /* initialize */
1520                         player->sent_bos = FALSE;
1521                 }
1522
1523                 if ( ! ret_value )
1524                 {
1525                         debug_error("failed to set position to zero for rewind\n");
1526                         continue;
1527                 }
1528
1529                 /* decrease play count */
1530                 if ( count > 1 )
1531                 {
1532                         /* we successeded to rewind. update play count and then wait for next EOS */
1533                         count--;
1534
1535                         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1536
1537                         /* commit attribute */
1538                         if ( mmf_attrs_commit ( attrs ) )
1539                         {
1540                                 debug_error("failed to commit attribute\n");
1541                         }
1542                 }
1543
1544                 /* unlock */
1545                 g_mutex_unlock(&player->cmd_lock);
1546         }
1547
1548         g_mutex_unlock(&player->repeat_thread_mutex);
1549         return NULL;
1550 }
1551
1552 static void
1553 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
1554 {
1555         MMHandleType attrs = 0;
1556         guint64 data_size = 0;
1557         gchar* path = NULL;
1558         unsigned long pos_msec = 0;
1559         struct stat sb;
1560
1561         return_if_fail( player && player->pipeline && player->pipeline->mainbin);
1562
1563         __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_msec);       // update last_position
1564
1565         attrs = MMPLAYER_GET_ATTRS(player);
1566         if ( !attrs )
1567         {
1568                 debug_error("fail to get attributes.\n");
1569                 return;
1570         }
1571
1572         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1573         {
1574                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1575
1576                 if (stat(path, &sb) == 0)
1577                 {
1578                         data_size = (guint64)sb.st_size;
1579                 }
1580         }
1581         else if (MMPLAYER_IS_HTTP_STREAMING(player))
1582         {
1583                 data_size = player->http_content_size;
1584         }
1585
1586         __mm_player_streaming_buffering(        player->streamer,
1587                                                                                 buffering_msg,
1588                                                                                 data_size,
1589                                                                                 player->last_position,
1590                                                                                 player->duration);
1591
1592         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
1593
1594         return;
1595 }
1596
1597
1598 static void
1599 __mmplayer_handle_buffering_message ( mm_player_t* player )
1600 {
1601         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1602         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1603         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1604         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1605
1606         return_if_fail ( player );
1607
1608         prev_state = MMPLAYER_PREV_STATE(player);
1609         current_state = MMPLAYER_CURRENT_STATE(player);
1610         target_state = MMPLAYER_TARGET_STATE(player);
1611         pending_state = MMPLAYER_PENDING_STATE(player);
1612
1613         if (MMPLAYER_IS_LIVE_STREAMING(player))
1614                 return;
1615
1616         if ( !player->streamer->is_buffering )
1617         {
1618                 debug_log( "player state : prev %s, current %s, pending %s, target %s \n",
1619                         MMPLAYER_STATE_GET_NAME(prev_state),
1620                         MMPLAYER_STATE_GET_NAME(current_state),
1621                         MMPLAYER_STATE_GET_NAME(pending_state),
1622                         MMPLAYER_STATE_GET_NAME(target_state));
1623
1624                 /* NOTE : if buffering has done, player has to go to target state. */
1625                 switch ( target_state )
1626                 {
1627                         case MM_PLAYER_STATE_PAUSED :
1628                         {
1629                                 switch ( pending_state )
1630                                 {
1631                                         case MM_PLAYER_STATE_PLAYING:
1632                                         {
1633                                                 __gst_pause ( player, TRUE );
1634                                         }
1635                                         break;
1636
1637                                         case MM_PLAYER_STATE_PAUSED:
1638                                         {
1639                                                  debug_log("player is already going to paused state, there is nothing to do.\n");
1640                                         }
1641                                         break;
1642
1643                                         case MM_PLAYER_STATE_NONE:
1644                                         case MM_PLAYER_STATE_NULL:
1645                                         case MM_PLAYER_STATE_READY:
1646                                         default :
1647                                         {
1648                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1649                                         }
1650                                                 break;
1651                                 }
1652                         }
1653                         break;
1654
1655                         case MM_PLAYER_STATE_PLAYING :
1656                         {
1657                                 switch ( pending_state )
1658                                 {
1659                                         case MM_PLAYER_STATE_NONE:
1660                                         {
1661                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
1662                                                         __gst_resume ( player, TRUE );
1663                                         }
1664                                         break;
1665
1666                                         case MM_PLAYER_STATE_PAUSED:
1667                                         {
1668                                                 /* NOTE: It should be worked as asynchronously.
1669                                                  * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1670                                                  */
1671                                                 __gst_resume ( player, TRUE );
1672                                         }
1673                                         break;
1674
1675                                         case MM_PLAYER_STATE_PLAYING:
1676                                         {
1677                                                  debug_log("player is already going to playing state, there is nothing to do.\n");
1678                                         }
1679                                         break;
1680
1681                                         case MM_PLAYER_STATE_NULL:
1682                                         case MM_PLAYER_STATE_READY:
1683                                         default :
1684                                         {
1685                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1686                                         }
1687                                                 break;
1688                                 }
1689                         }
1690                         break;
1691
1692                         case MM_PLAYER_STATE_NULL :
1693                         case MM_PLAYER_STATE_READY :
1694                         case MM_PLAYER_STATE_NONE :
1695                         default:
1696                         {
1697                                 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1698                         }
1699                                 break;
1700                 }
1701         }
1702         else
1703         {
1704                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1705                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
1706                  */
1707                 switch ( pending_state )
1708                 {
1709                         case MM_PLAYER_STATE_NONE:
1710                         {
1711                                 if (current_state != MM_PLAYER_STATE_PAUSED)
1712                                 {
1713                                         debug_log("set pause state during buffering\n");
1714                                         __gst_pause ( player, TRUE );
1715
1716                                         // to cover the weak-signal environment.
1717                                         if (MMPLAYER_IS_RTSP_STREAMING(player))
1718                                         {
1719                                                 unsigned long position = 0;
1720                                                 gint64 pos_msec = 0;
1721
1722                                                 debug_log("[RTSP] seek to the buffering start point\n");
1723
1724                                                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
1725                                                 {
1726                                                         debug_error("failed to get position\n");
1727                                                         break;
1728                                                 }
1729
1730                                                 /* key unit seek */
1731                                                 pos_msec = position * G_GINT64_CONSTANT(1000000);
1732
1733                                                 __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
1734                                                                         GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1735                                                                         pos_msec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1736                                         }
1737                                 }
1738                         }
1739                         break;
1740
1741                         case MM_PLAYER_STATE_PLAYING:
1742                         {
1743                                 __gst_pause ( player, TRUE );
1744                         }
1745                         break;
1746
1747                         case MM_PLAYER_STATE_PAUSED:
1748                         {
1749                         }
1750                         break;
1751
1752                         case MM_PLAYER_STATE_NULL:
1753                         case MM_PLAYER_STATE_READY:
1754                         default :
1755                         {
1756                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1757                         }
1758                                 break;
1759                 }
1760         }
1761 }
1762
1763 static void
1764 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
1765 {
1766         MMPlayerGstElement *textbin;
1767         MMPLAYER_FENTER();
1768
1769         return_if_fail ( player &&
1770                                         player->pipeline &&
1771                                         player->pipeline->textbin);
1772
1773         return_if_fail (player->pipeline->textbin[MMPLAYER_T_IDENTITY].gst);
1774
1775         textbin = player->pipeline->textbin;
1776
1777         if (is_drop)
1778         {
1779                 debug_log("Drop subtitle text after getting EOS\n");
1780
1781                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
1782                 g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1783
1784                 player->is_subtitle_force_drop = TRUE;
1785         }
1786         else
1787         {
1788                 if (player->is_subtitle_force_drop == TRUE)
1789                 {
1790                         debug_log("Enable subtitle data path without drop\n");
1791
1792                         g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1793                         g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
1794
1795                         debug_log ("non-connected with external display");
1796
1797                         player->is_subtitle_force_drop = FALSE;
1798                 }
1799         }
1800 }
1801
1802 static gboolean
1803 __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
1804 {
1805         mm_player_t* player = (mm_player_t*) data;
1806         gboolean ret = TRUE;
1807         static gboolean async_done = FALSE;
1808
1809         return_val_if_fail ( player, FALSE );
1810         return_val_if_fail ( msg && GST_IS_MESSAGE(msg), FALSE );
1811
1812         switch ( GST_MESSAGE_TYPE( msg ) )
1813         {
1814                 case GST_MESSAGE_UNKNOWN:
1815                         debug_log("unknown message received\n");
1816                 break;
1817
1818                 case GST_MESSAGE_EOS:
1819                 {
1820                         MMHandleType attrs = 0;
1821                         gint count = 0;
1822
1823                         debug_log("GST_MESSAGE_EOS received\n");
1824
1825                         /* NOTE : EOS event is comming multiple time. watch out it */
1826                         /* check state. we only process EOS when pipeline state goes to PLAYING */
1827                         if ( ! (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) )
1828                         {
1829                                 debug_log("EOS received on non-playing state. ignoring it\n");
1830                                 break;
1831                         }
1832
1833                         __mmplayer_drop_subtitle(player, TRUE);
1834
1835                         if ( (player->audio_stream_cb) && (player->set_mode.pcm_extraction) && (!player->audio_stream_render_cb_ex))
1836                         {
1837                                 GstPad *pad = NULL;
1838
1839                                 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1840
1841                                 debug_log("release audio callback\n");
1842
1843                                 /* release audio callback */
1844                                 gst_pad_remove_probe (pad, player->audio_cb_probe_id);
1845                                 player->audio_cb_probe_id = 0;
1846                                 /* audio callback should be free because it can be called even though probe remove.*/
1847                                 player->audio_stream_cb = NULL;
1848                                 player->audio_stream_cb_user_param = NULL;
1849
1850                         }
1851
1852                         /* rewind if repeat count is greater then zero */
1853                         /* get play count */
1854                         attrs = MMPLAYER_GET_ATTRS(player);
1855
1856                         if ( attrs )
1857                         {
1858                                 gboolean smooth_repeat = FALSE;
1859
1860                                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1861                                 mm_attrs_get_int_by_name(attrs, "profile_smooth_repeat", &smooth_repeat);
1862
1863                                 player->play_count = count;
1864
1865                                 debug_log("remaining play count: %d, playback rate: %f\n", count, player->playback_rate);
1866
1867                                 if ( count > 1 || count == -1 || player->playback_rate < 0.0 ) /* default value is 1 */
1868                                 {
1869                                         if ( smooth_repeat )
1870                                         {
1871                                                 debug_log("smooth repeat enabled. seeking operation will be excuted in new thread\n");
1872
1873                                                 g_cond_signal( &player->repeat_thread_cond );
1874
1875                                                 break;
1876                                         }
1877                                         else
1878                                         {
1879                                                 gint ret_value = 0;
1880
1881                                                 if ( player->section_repeat )
1882                                                 {
1883                                                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1884                                                 }
1885                                                 else
1886                                                 {
1887                                                         if ( player->playback_rate < 0.0 )
1888                                                         {
1889                                                                 player->resumed_by_rewind = TRUE;
1890                                                                 _mmplayer_set_mute((MMHandleType)player, 0);
1891                                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1892                                                         }
1893
1894                                                         __mmplayer_handle_eos_delay( player, player->ini.delay_before_repeat );
1895
1896                                                         /* initialize */
1897                                                         player->sent_bos = FALSE;
1898                                                 }
1899
1900                                                 if ( MM_ERROR_NONE != ret_value )
1901                                                 {
1902                                                         debug_error("failed to set position to zero for rewind\n");
1903                                                 }
1904
1905                                                 /* not posting eos when repeating */
1906                                                 break;
1907                                         }
1908                                 }
1909                         }
1910
1911                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-eos" );
1912
1913                         /* post eos message to application */
1914                         __mmplayer_handle_eos_delay( player, player->ini.eos_delay );
1915
1916                         /* reset last position */
1917                         player->last_position = 0;
1918                 }
1919                 break;
1920
1921                 case GST_MESSAGE_ERROR:
1922                 {
1923                         GError *error = NULL;
1924                         gchar* debug = NULL;
1925
1926                         /* generating debug info before returning error */
1927                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-error" );
1928
1929                         /* get error code */
1930                         gst_message_parse_error( msg, &error, &debug );
1931
1932                         if ( gst_structure_has_name ( gst_message_get_structure(msg), "streaming_error" ) )
1933                         {
1934                                 /* Note : the streaming error from the streaming source is handled
1935                                  *   using __mmplayer_handle_streaming_error.
1936                                  */
1937                                 __mmplayer_handle_streaming_error ( player, msg );
1938
1939                                 /* dump state of all element */
1940                                 __mmplayer_dump_pipeline_state( player );
1941                         }
1942                         else
1943                         {
1944                                 /* traslate gst error code to msl error code. then post it
1945                                  * to application if needed
1946                                  */
1947                                 __mmplayer_handle_gst_error( player, msg, error );
1948
1949                                 if (debug)
1950                                 {
1951                                         debug_error ("error debug : %s", debug);
1952                                 }
1953
1954                         }
1955
1956                         if (MMPLAYER_IS_HTTP_PD(player))
1957                         {
1958                                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
1959                         }
1960
1961                         MMPLAYER_FREEIF( debug );
1962                         g_error_free( error );
1963                 }
1964                 break;
1965
1966                 case GST_MESSAGE_WARNING:
1967                 {
1968                         char* debug = NULL;
1969                         GError* error = NULL;
1970
1971                         gst_message_parse_warning(msg, &error, &debug);
1972
1973                         debug_log("warning : %s\n", error->message);
1974                         debug_log("debug : %s\n", debug);
1975
1976                         MMPLAYER_POST_MSG( player, MM_MESSAGE_WARNING, NULL );
1977
1978                         MMPLAYER_FREEIF( debug );
1979                         g_error_free( error );
1980                 }
1981                 break;
1982
1983                 case GST_MESSAGE_TAG:
1984                 {
1985                         debug_log("GST_MESSAGE_TAG\n");
1986                         if ( ! __mmplayer_gst_extract_tag_from_msg( player, msg ) )
1987                         {
1988                                 debug_warning("failed to extract tags from gstmessage\n");
1989                         }
1990                 }
1991                 break;
1992
1993                 case GST_MESSAGE_BUFFERING:
1994                 {
1995                         MMMessageParamType msg_param = {0, };
1996                         int asm_result = MM_ERROR_NONE;
1997
1998                         if (!MMPLAYER_IS_STREAMING(player))
1999                                 break;
2000
2001                         /* ignore the prev buffering message */
2002                         if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (player->streamer->is_buffering_done == TRUE))
2003                         {
2004                                 gint buffer_percent = 0;
2005
2006                                 gst_message_parse_buffering (msg, &buffer_percent);
2007
2008                                 if (buffer_percent == MAX_BUFFER_PERCENT)
2009                                 {
2010                                         debug_log ("Ignored all the previous buffering msg! (got %d%%)\n", buffer_percent);
2011                                         player->streamer->is_buffering_done = FALSE;
2012                                 }
2013
2014                                 break;
2015                         }
2016
2017                         /* update ASM state to ASM_STATE_PLAYING */
2018                         /* fixed ASM_STATE_WAITING -> ASM_STATE_PLAYING for Samsunlink issue*/
2019                         if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED))
2020                         {
2021                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_WAITING, TRUE);
2022                                 if ( asm_result != MM_ERROR_NONE )
2023                                 {
2024                                         debug_warning("failed to set asm state to waiting, but keep going...\n");
2025                                 }
2026                         }
2027
2028                         __mmplayer_update_buffer_setting(player, msg);
2029
2030                         __mmplayer_handle_buffering_message ( player );
2031
2032                         msg_param.connection.buffering = player->streamer->buffering_percent;
2033                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param );
2034                         if (MMPLAYER_IS_RTSP_STREAMING(player) && (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT))
2035                         {
2036                                 if (player->doing_seek)
2037                                 {
2038                                         if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2039                                         {
2040                                                 player->doing_seek = FALSE;
2041                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2042                                         }
2043                                         else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2044                                         {
2045                                                 async_done = TRUE;
2046                                         }
2047                                 }
2048                         }
2049                 }
2050                 break;
2051
2052                 case GST_MESSAGE_STATE_CHANGED:
2053                 {
2054                         MMPlayerGstElement *mainbin;
2055                         const GValue *voldstate, *vnewstate, *vpending;
2056                         GstState oldstate, newstate, pending;
2057
2058                         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
2059                         {
2060                                 debug_error("player pipeline handle is null");
2061                                 break;
2062                         }
2063
2064                         mainbin = player->pipeline->mainbin;
2065
2066                         /* we only handle messages from pipeline */
2067                         if( msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst )
2068                                 break;
2069
2070                         /* get state info from msg */
2071                         voldstate = gst_structure_get_value (gst_message_get_structure(msg), "old-state");
2072                         vnewstate = gst_structure_get_value (gst_message_get_structure(msg), "new-state");
2073                         vpending = gst_structure_get_value (gst_message_get_structure(msg), "pending-state");
2074
2075                         oldstate = (GstState)voldstate->data[0].v_int;
2076                         newstate = (GstState)vnewstate->data[0].v_int;
2077                         pending = (GstState)vpending->data[0].v_int;
2078
2079                         debug_log("state changed [%s] : %s ---> %s     final : %s\n",
2080                                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
2081                                 gst_element_state_get_name( (GstState)oldstate ),
2082                                 gst_element_state_get_name( (GstState)newstate ),
2083                                 gst_element_state_get_name( (GstState)pending ) );
2084
2085                         if (oldstate == newstate)
2086                         {
2087                                 debug_log("pipeline reports state transition to old state");
2088                                 break;
2089                         }
2090
2091                         switch(newstate)
2092                         {
2093                                 case GST_STATE_VOID_PENDING:
2094                                 break;
2095
2096                                 case GST_STATE_NULL:
2097                                 break;
2098
2099                                 case GST_STATE_READY:
2100                                 break;
2101
2102                                 case GST_STATE_PAUSED:
2103                                 {
2104                                         gboolean prepare_async = FALSE;
2105                                         gboolean is_drm = FALSE;
2106
2107                                         if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
2108                                                 __mmplayer_configure_audio_callback(player);
2109
2110                                         if ( ! player->sent_bos && oldstate == GST_STATE_READY) // managed prepare async case
2111                                         {
2112                                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
2113                                                 debug_log("checking prepare mode for async transition - %d", prepare_async);
2114                                         }
2115
2116                                         if ( MMPLAYER_IS_STREAMING(player) || prepare_async )
2117                                         {
2118                                                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
2119
2120                                                 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
2121                                                 {
2122                                                         __mm_player_streaming_set_content_bitrate(player->streamer,
2123                                                                 player->total_maximum_bitrate, player->total_bitrate);
2124                                                 }
2125                                         }
2126
2127                                         /* NOTE : should consider streaming case */
2128                                         /* check if drm file */
2129                                         if ((player->pipeline->mainbin[MMPLAYER_M_SRC].gst) &&
2130                                                 (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm")))
2131                                         {
2132                                                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
2133
2134                                                 if (is_drm)
2135                                                 {
2136                                                         player->is_drm_file = TRUE;
2137                                                 }
2138                                         }
2139                                 }
2140                                 break;
2141
2142                                 case GST_STATE_PLAYING:
2143                                 {
2144 /* for audio tunning */
2145 #ifndef IS_SDK
2146                                         if (player->can_support_codec == 0x03) {
2147                                                 gint volume_type;
2148                                                 mm_attrs_get_int_by_name(player->attrs, "sound_volume_type", &volume_type);
2149                                                 volume_type |= MM_SOUND_VOLUME_GAIN_VIDEO;
2150                                                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "volumetype", volume_type, NULL);
2151                                         }
2152 #endif
2153                                         if ( MMPLAYER_IS_STREAMING(player) ) // managed prepare async case when buffering is completed
2154                                         {
2155                                                 // pending state should be reset oyherwise, it's still playing even though it's resumed after bufferging.
2156                                                 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
2157                                                         (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
2158                                                 {
2159                                                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING);
2160                                                 }
2161                                         }
2162
2163                                         if (player->gapless.stream_changed)
2164                                         {
2165                                                 _mmplayer_update_content_attrs(player, ATTR_ALL);
2166                                         }
2167
2168                                         if (player->doing_seek && async_done)
2169                                         {
2170                                                 player->doing_seek = FALSE;
2171                                                 async_done = FALSE;
2172                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2173                                         }
2174                                 }
2175                                 break;
2176
2177                                 default:
2178                                 break;
2179                         }
2180                 }
2181                 break;
2182
2183                 case GST_MESSAGE_CLOCK_LOST:
2184                         {
2185                                 GstClock *clock = NULL;
2186                                 gst_message_parse_clock_lost (msg, &clock);
2187                                 debug_log("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2188                                 g_print ("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2189
2190                                 if (((player->ini.provide_clock_for_music) && (!player->videodec_linked)) ||
2191                                         ((player->ini.provide_clock_for_movie) && (player->videodec_linked)))
2192                                 {
2193                                         debug_log ("Provide clock is TRUE, do pause->resume\n");
2194                                         __gst_pause(player, FALSE);
2195                                         __gst_resume(player, FALSE);
2196                                 }
2197                         }
2198                         break;
2199
2200                 case GST_MESSAGE_NEW_CLOCK:
2201                         {
2202                                 GstClock *clock = NULL;
2203                                 gst_message_parse_new_clock (msg, &clock);
2204                                 debug_log("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2205                         }
2206                         break;
2207
2208                 case GST_MESSAGE_ELEMENT:
2209                         {
2210                                 const gchar *structure_name;
2211                                 gint count = 0;
2212                                 MMHandleType attrs = 0;
2213
2214                                 attrs = MMPLAYER_GET_ATTRS(player);
2215                                 if ( !attrs )
2216                                 {
2217                                         debug_error("cannot get content attribute");
2218                                         ret = FALSE;
2219                                         break;
2220                                 }
2221
2222                                 if(gst_message_get_structure(msg) == NULL)
2223                                         break;
2224
2225                                 structure_name = gst_structure_get_name(gst_message_get_structure(msg));
2226                                 if(!strcmp(structure_name, "Language_list"))
2227                                 {
2228                                         const GValue *lang_list = NULL;
2229                                         lang_list = gst_structure_get_value (gst_message_get_structure(msg), "lang_list");
2230                                         if(lang_list != NULL)
2231                                         {
2232                                                 count = g_list_length((GList *)g_value_get_pointer (lang_list));
2233                                                 if (count > 1)
2234                                                         debug_log("Total audio tracks (from parser) = %d \n",count);
2235                                         }
2236                                 }
2237
2238                                 if (!strcmp (structure_name, "Ext_Sub_Language_List"))
2239                                 {
2240                                         const GValue *lang_list = NULL;
2241                                         MMPlayerLangStruct *temp = NULL;
2242
2243                                         lang_list = gst_structure_get_value (gst_message_get_structure(msg), "lang_list");
2244                                         if (lang_list != NULL)
2245                                         {
2246                                                 count = g_list_length ((GList *)g_value_get_pointer (lang_list));
2247                                                 if (count)
2248                                                 {
2249                                                         player->subtitle_language_list = (GList *)g_value_get_pointer (lang_list);
2250                                                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
2251                                                         if (mmf_attrs_commit (attrs))
2252                                                           debug_error("failed to commit.\n");
2253                                                         debug_log("Total subtitle tracks = %d \n", count);
2254                                                 }
2255                                                 while (count)
2256                                                 {
2257                                                         temp = g_list_nth_data (player->subtitle_language_list, count - 1);
2258                                                         debug_log ("value of lang_key is %s and lang_code is %s",
2259                                                                                 temp->language_key, temp->language_code);
2260                                                         count--;
2261                                                 }
2262                                         }
2263                                 }
2264
2265                                 /* custom message */
2266                                 if (!strcmp (structure_name, "audio_codec_not_supported")) {
2267                                         MMMessageParamType msg_param = {0,};
2268                                         msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
2269                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
2270                                 }
2271                         }
2272                         break;
2273
2274                 case GST_MESSAGE_DURATION_CHANGED:
2275                 {
2276                         debug_log("GST_MESSAGE_DURATION_CHANGED\n");
2277                         ret = __mmplayer_gst_handle_duration(player, msg);
2278                         if (!ret)
2279                         {
2280                                 debug_warning("failed to update duration");
2281                         }
2282                 }
2283
2284                 break;
2285
2286                 case GST_MESSAGE_ASYNC_START:
2287                 {
2288                         debug_log("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2289                 }
2290                 break;
2291
2292                 case GST_MESSAGE_ASYNC_DONE:
2293                 {
2294                         debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2295
2296                         /* we only handle messages from pipeline */
2297                         if( msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
2298                                 break;
2299
2300                         if (player->doing_seek)
2301                         {
2302                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2303                                 {
2304                                         player->doing_seek = FALSE;
2305                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2306                                 }
2307                                 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2308                                 {
2309                                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2310                                                 (player->streamer) &&
2311                                                 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
2312                                                 (player->streamer->is_buffering == FALSE))
2313                                         {
2314                                                 GstQuery *query = NULL;
2315                                                 gboolean busy = FALSE;
2316                                                 gint percent = 0;
2317
2318                                                 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer)
2319                                                 {
2320                                                         query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
2321                                                         if ( gst_element_query (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query ) )
2322                                                         {
2323                                                                 gst_query_parse_buffering_percent ( query, &busy, &percent);
2324                                                         }
2325                                                         gst_query_unref (query);
2326
2327                                                         debug_log("buffered percent(%s): %d\n",
2328                                                                 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
2329                                                 }
2330
2331                                                 if (percent >= 100)
2332                                                 {
2333                                                         player->streamer->is_buffering = FALSE;
2334                                                         __mmplayer_handle_buffering_message(player);
2335                                                 }
2336                                         }
2337
2338                                         async_done = TRUE;
2339                                 }
2340                         }
2341                 }
2342                 break;
2343
2344                 #if 0 /* delete unnecessary logs */
2345                 case GST_MESSAGE_REQUEST_STATE:         debug_log("GST_MESSAGE_REQUEST_STATE\n"); break;
2346                 case GST_MESSAGE_STEP_START:            debug_log("GST_MESSAGE_STEP_START\n"); break;
2347                 case GST_MESSAGE_QOS:                           debug_log("GST_MESSAGE_QOS\n"); break;
2348                 case GST_MESSAGE_PROGRESS:                      debug_log("GST_MESSAGE_PROGRESS\n"); break;
2349                 case GST_MESSAGE_ANY:                           debug_log("GST_MESSAGE_ANY\n"); break;
2350                 case GST_MESSAGE_INFO:                          debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2351                 case GST_MESSAGE_STATE_DIRTY:           debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2352                 case GST_MESSAGE_STEP_DONE:                     debug_log("GST_MESSAGE_STEP_DONE\n"); break;
2353                 case GST_MESSAGE_CLOCK_PROVIDE:         debug_log("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
2354                 case GST_MESSAGE_STRUCTURE_CHANGE:      debug_log("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
2355                 case GST_MESSAGE_STREAM_STATUS:         debug_log("GST_MESSAGE_STREAM_STATUS\n"); break;
2356                 case GST_MESSAGE_APPLICATION:           debug_log("GST_MESSAGE_APPLICATION\n"); break;
2357                 case GST_MESSAGE_SEGMENT_START:         debug_log("GST_MESSAGE_SEGMENT_START\n"); break;
2358                 case GST_MESSAGE_SEGMENT_DONE:          debug_log("GST_MESSAGE_SEGMENT_DONE\n"); break;
2359                 case GST_MESSAGE_LATENCY:                               debug_log("GST_MESSAGE_LATENCY\n"); break;
2360                 #endif
2361
2362                 default:
2363                 break;
2364         }
2365
2366         /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
2367          * gst_element_post_message api takes ownership of the message.
2368          */
2369         //gst_message_unref( msg );
2370
2371         return ret;
2372 }
2373
2374 static gboolean
2375 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
2376 {
2377         gint64 bytes = 0;
2378
2379         MMPLAYER_FENTER();
2380
2381         return_val_if_fail(player, FALSE);
2382         return_val_if_fail(msg, FALSE);
2383
2384         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2385                 (msg->src) && (msg->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst))
2386         {
2387                 debug_log("msg src : [%s]", GST_ELEMENT_NAME(GST_ELEMENT_CAST(msg->src)));
2388
2389                 if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes))
2390                 {
2391                         debug_log("data total size of http content: %lld", bytes);
2392                         player->http_content_size = bytes;
2393                 }
2394         }
2395         else
2396         {
2397                 /* handling audio clip which has vbr. means duration is keep changing */
2398                 _mmplayer_update_content_attrs (player, ATTR_DURATION );
2399         }
2400
2401         MMPLAYER_FLEAVE();
2402
2403         return TRUE;
2404 }
2405
2406
2407 static gboolean
2408 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg) // @
2409 {
2410
2411 /* macro for better code readability */
2412 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
2413 if (gst_tag_list_get_string(tag_list, gsttag, &string)) \
2414 {\
2415         if (string != NULL)\
2416         {\
2417                 secure_debug_log ( "update tag string : %s\n", string); \
2418                 mm_attrs_set_string_by_name(attribute, playertag, string); \
2419                 g_free(string);\
2420                 string = NULL;\
2421         }\
2422 }
2423
2424 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
2425 GstSample *sample = NULL;\
2426 if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample))\
2427 {\
2428         GstMapInfo info = GST_MAP_INFO_INIT;\
2429         buffer = gst_sample_get_buffer(sample);\
2430         if (!gst_buffer_map(buffer, &info, GST_MAP_READ)){\
2431                 debug_log("failed to get image data from tag");\
2432                 return FALSE;\
2433         }\
2434         secure_debug_log ( "update album cover data : %p, size : %d\n", info.data, info.size);\
2435         MMPLAYER_FREEIF(player->album_art); \
2436         player->album_art = (gchar *)g_malloc(info.size); \
2437         if (player->album_art) \
2438         { \
2439                 memcpy(player->album_art, info.data, info.size); \
2440                 mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, info.size); \
2441                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) \
2442                 { \
2443                         msg_param.data = (void *)player->album_art; \
2444                         msg_param.size = info.size; \
2445                         MMPLAYER_POST_MSG (player, MM_MESSAGE_IMAGE_BUFFER, &msg_param); \
2446                         secure_debug_log ( "post message image buffer data : %p, size : %d\n", info.data, info.size); \
2447                 } \
2448         } \
2449         gst_buffer_unmap(buffer, &info); \
2450 }
2451
2452 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
2453 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint))\
2454 {\
2455         if(v_uint)\
2456         {\
2457                 if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) \
2458                 {\
2459                         if (player->updated_bitrate_count == 0) \
2460                                 mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
2461                         if (player->updated_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2462                         {\
2463                                 player->bitrate[player->updated_bitrate_count] = v_uint;\
2464                                 player->total_bitrate += player->bitrate[player->updated_maximum_bitrate_count]; \
2465                                 player->updated_bitrate_count++; \
2466                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate);\
2467                                 secure_debug_log ( "update bitrate %d[bps] of stream #%d.\n", v_uint, player->updated_bitrate_count);\
2468                         }\
2469                 }\
2470                 else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) \
2471                 {\
2472                         if (player->updated_maximum_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2473                         {\
2474                                 player->maximum_bitrate[player->updated_maximum_bitrate_count] = v_uint;\
2475                                 player->total_maximum_bitrate += player->maximum_bitrate[player->updated_maximum_bitrate_count]; \
2476                                 player->updated_maximum_bitrate_count++; \
2477                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate); \
2478                                 secure_debug_log ( "update maximum bitrate %d[bps] of stream #%d\n", v_uint, player->updated_maximum_bitrate_count);\
2479                         }\
2480                 }\
2481                 else\
2482                 {\
2483                         mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
2484                 }\
2485                 v_uint = 0;\
2486         }\
2487 }
2488
2489 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
2490 if (gst_tag_list_get_date(tag_list, gsttag, &date))\
2491 {\
2492         if (date != NULL)\
2493         {\
2494                 string = g_strdup_printf("%d", g_date_get_year(date));\
2495                 mm_attrs_set_string_by_name(attribute, playertag, string);\
2496                 secure_debug_log ( "metainfo year : %s\n", string);\
2497                 MMPLAYER_FREEIF(string);\
2498                 g_date_free(date);\
2499         }\
2500 }
2501
2502 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
2503 if(gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64))\
2504 {\
2505         if(v_uint64)\
2506         {\
2507                 /* FIXIT : don't know how to store date */\
2508                 g_assert(1);\
2509                 v_uint64 = 0;\
2510         }\
2511 }
2512
2513 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
2514 if(gst_tag_list_get_double(tag_list, gsttag, &v_double))\
2515 {\
2516         if(v_double)\
2517         {\
2518                 /* FIXIT : don't know how to store date */\
2519                 g_assert(1);\
2520                 v_double = 0;\
2521         }\
2522 }
2523
2524         /* function start */
2525         GstTagList* tag_list = NULL;
2526
2527         MMHandleType attrs = 0;
2528
2529         char *string = NULL;
2530         guint v_uint = 0;
2531         GDate *date = NULL;
2532         /* album cover */
2533         GstBuffer *buffer = NULL;
2534         gint index = 0;
2535         MMMessageParamType msg_param = {0, };
2536
2537         /* currently not used. but those are needed for above macro */
2538         //guint64 v_uint64 = 0;
2539         //gdouble v_double = 0;
2540
2541         return_val_if_fail( player && msg, FALSE );
2542
2543         attrs = MMPLAYER_GET_ATTRS(player);
2544
2545         return_val_if_fail( attrs, FALSE );
2546
2547         /* get tag list from gst message */
2548         gst_message_parse_tag(msg, &tag_list);
2549
2550         /* store tags to player attributes */
2551         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
2552         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
2553         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
2554         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
2555         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
2556         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
2557         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
2558         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
2559         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
2560         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
2561         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
2562         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
2563         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
2564         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
2565         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
2566         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
2567         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
2568         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
2569         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
2570         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
2571         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
2572         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
2573         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
2574         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
2575         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
2576         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
2577         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
2578         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
2579         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
2580         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
2581         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
2582         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
2583         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
2584         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
2585         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
2586         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
2587         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
2588         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
2589         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
2590         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
2591         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
2592         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
2593         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
2594         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
2595         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
2596         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, attrs, "content_video_orientation");
2597
2598         if ( mmf_attrs_commit ( attrs ) )
2599                 debug_error("failed to commit.\n");
2600
2601         gst_tag_list_free(tag_list);
2602
2603         return TRUE;
2604 }
2605
2606 static void
2607 __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data)  // @
2608 {
2609         mm_player_t* player = (mm_player_t*) data;
2610
2611         MMPLAYER_FENTER();
2612
2613         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2614           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2615           * num_dynamic_pad. and this is no-more-pad situation which means mo more pad will be added.
2616           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2617
2618           * [1] audio and video will be dumped with filesink.
2619           * [2] autoplugging is done by just using pad caps.
2620           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
2621           * and the video will be dumped via filesink.
2622           */
2623         if ( player->num_dynamic_pad == 0 )
2624         {
2625                 debug_log("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
2626
2627                 if ( ! __mmplayer_gst_remove_fakesink( player,
2628                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
2629                 {
2630                         /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
2631                          * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
2632                          * source element are not same. To overcome this situation, this function will called
2633                          * several places and several times. Therefore, this is not an error case.
2634                          */
2635                         return;
2636                 }
2637         }
2638
2639         /* create dot before error-return. for debugging */
2640         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-no-more-pad" );
2641
2642         player->no_more_pad = TRUE;
2643
2644         MMPLAYER_FLEAVE();
2645 }
2646
2647 static gboolean
2648 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink) // @
2649 {
2650         GstElement* parent = NULL;
2651
2652         return_val_if_fail(player && player->pipeline, FALSE);
2653
2654         /* if we have no fakesink. this meas we are using decodebin which doesn'
2655         t need to add extra fakesink */
2656         return_val_if_fail(fakesink, TRUE);
2657
2658         /* lock */
2659         g_mutex_lock(&player->fsink_lock );
2660
2661         if ( ! fakesink->gst )
2662         {
2663                 goto ERROR;
2664         }
2665
2666         /* get parent of fakesink */
2667         parent = (GstElement*)gst_object_get_parent( (GstObject*)fakesink->gst );
2668         if ( ! parent )
2669         {
2670                 debug_log("fakesink already removed\n");
2671                 goto ERROR;
2672         }
2673
2674         gst_element_set_locked_state( fakesink->gst, TRUE );
2675
2676         /* setting the state to NULL never returns async
2677          * so no need to wait for completion of state transiton
2678          */
2679         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (fakesink->gst, GST_STATE_NULL) )
2680         {
2681                 debug_error("fakesink state change failure!\n");
2682
2683                 /* FIXIT : should I return here? or try to proceed to next? */
2684                 /* return FALSE; */
2685         }
2686
2687         /* remove fakesink from it's parent */
2688         if ( ! gst_bin_remove( GST_BIN( parent ), fakesink->gst ) )
2689         {
2690                 debug_error("failed to remove fakesink\n");
2691
2692                 gst_object_unref( parent );
2693
2694                 goto ERROR;
2695         }
2696
2697         gst_object_unref( parent );
2698
2699         debug_log("state-holder removed\n");
2700
2701         gst_element_set_locked_state( fakesink->gst, FALSE );
2702
2703         g_mutex_unlock( &player->fsink_lock );
2704         return TRUE;
2705
2706 ERROR:
2707         if ( fakesink->gst )
2708         {
2709                 gst_element_set_locked_state( fakesink->gst, FALSE );
2710         }
2711
2712         g_mutex_unlock( &player->fsink_lock );
2713         return FALSE;
2714 }
2715
2716
2717 static void
2718 __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2719 {
2720         GstPad *sinkpad = NULL;
2721         GstCaps* caps = NULL;
2722         GstElement* new_element = NULL;
2723         GstStructure* str = NULL;
2724         const gchar* name = NULL;
2725
2726         mm_player_t* player = (mm_player_t*) data;
2727
2728         MMPLAYER_FENTER();
2729
2730         return_if_fail( element && pad );
2731         return_if_fail( player &&
2732                                         player->pipeline &&
2733                                         player->pipeline->mainbin );
2734
2735
2736         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2737          * num_dynamic_pad will decreased after creating a sinkbin.
2738          */
2739         player->num_dynamic_pad++;
2740         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2741
2742         /* perform autoplugging if dump is disabled */
2743         if ( player->ini.rtsp_do_typefinding )
2744         {
2745                 /* create typefind */
2746                 new_element = gst_element_factory_make( "typefind", NULL );
2747                 if ( ! new_element )
2748                 {
2749                         debug_error("failed to create typefind\n");
2750                         goto ERROR;
2751                 }
2752
2753                 MMPLAYER_SIGNAL_CONNECT(        player,
2754                                                                         G_OBJECT(new_element),
2755                                                                         MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2756                                                                         "have-type",
2757                                                                         G_CALLBACK(__mmplayer_typefind_have_type),
2758                                                                         (gpointer)player);
2759
2760                 /* FIXIT : try to remove it */
2761                 player->have_dynamic_pad = FALSE;
2762         }
2763         else  /* NOTE : use pad's caps directely. if enabled. what I am assuming is there's no elemnt has dynamic pad */
2764         {
2765                 debug_log("using pad caps to autopluging instead of doing typefind\n");
2766
2767                 caps = gst_pad_query_caps( pad, NULL );
2768
2769                 MMPLAYER_CHECK_NULL( caps );
2770
2771                 /* clear  previous result*/
2772                 player->have_dynamic_pad = FALSE;
2773
2774                 str = gst_caps_get_structure(caps, 0);
2775
2776                 if ( ! str )
2777                 {
2778                         debug_error ("cannot get structure from caps.\n");
2779                         goto ERROR;
2780                 }
2781
2782                 name = gst_structure_get_name (str);
2783                 if ( ! name )
2784                 {
2785                         debug_error ("cannot get mimetype from structure.\n");
2786                         goto ERROR;
2787                 }
2788
2789                 if (strstr(name, "video"))
2790                 {
2791                         gint stype = 0;
2792                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
2793
2794                         if (stype == MM_DISPLAY_SURFACE_NULL)
2795                         {
2796                                 if (player->v_stream_caps)
2797                                 {
2798                                         gst_caps_unref(player->v_stream_caps);
2799                                         player->v_stream_caps = NULL;
2800                                 }
2801
2802                                 new_element = gst_element_factory_make("fakesink", NULL);
2803                                 player->num_dynamic_pad--;
2804                                 goto NEW_ELEMENT;
2805                         }
2806                 }
2807
2808                 /* clear  previous result*/
2809                 player->have_dynamic_pad = FALSE;
2810
2811                 if ( !__mmplayer_try_to_plug_decodebin(player, pad, caps))
2812                 {
2813                         debug_error("failed to autoplug for caps");
2814                         goto ERROR;
2815                 }
2816
2817                 /* check if there's dynamic pad*/
2818                 if( player->have_dynamic_pad )
2819                 {
2820                         debug_error("using pad caps assums there's no dynamic pad !\n");
2821                         debug_error("try with enalbing rtsp_do_typefinding\n");
2822                         goto ERROR;
2823                 }
2824
2825                 gst_caps_unref( caps );
2826                 caps = NULL;
2827         }
2828
2829         NEW_ELEMENT:
2830
2831         /* excute new_element if created*/
2832         if ( new_element )
2833         {
2834                 debug_log("adding new element to pipeline\n");
2835
2836                 /* set state to READY before add to bin */
2837                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2838
2839                 /* add new element to the pipeline */
2840                 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2841                 {
2842                         debug_error("failed to add autoplug element to bin\n");
2843                         goto ERROR;
2844                 }
2845
2846                 /* get pad from element */
2847                 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2848                 if ( !sinkpad )
2849                 {
2850                         debug_error("failed to get sinkpad from autoplug element\n");
2851                         goto ERROR;
2852                 }
2853
2854                 /* link it */
2855                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2856                 {
2857                         debug_error("failed to link autoplug element\n");
2858                         goto ERROR;
2859                 }
2860
2861                 gst_object_unref (sinkpad);
2862                 sinkpad = NULL;
2863
2864                 /* run. setting PLAYING here since streamming source is live source */
2865                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2866         }
2867
2868         MMPLAYER_FLEAVE();
2869
2870         return;
2871
2872 STATE_CHANGE_FAILED:
2873 ERROR:
2874         /* FIXIT : take care if new_element has already added to pipeline */
2875         if ( new_element )
2876                 gst_object_unref(GST_OBJECT(new_element));
2877
2878         if ( sinkpad )
2879                 gst_object_unref(GST_OBJECT(sinkpad));
2880
2881         if ( caps )
2882                 gst_object_unref(GST_OBJECT(caps));
2883
2884         /* FIXIT : how to inform this error to MSL ????? */
2885         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2886          * then post an error to application
2887          */
2888 }
2889
2890
2891
2892 /* FIXIT : check indent */
2893 #if 0
2894 static void
2895 __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2896 {
2897   GstPad *sinkpad = NULL;
2898   GstCaps* caps = NULL;
2899   GstElement* new_element = NULL;
2900   enum MainElementID element_id = MMPLAYER_M_NUM;
2901
2902   mm_player_t* player = (mm_player_t*) data;
2903
2904   MMPLAYER_FENTER();
2905
2906   return_if_fail( element && pad );
2907   return_if_fail(  player &&
2908           player->pipeline &&
2909           player->pipeline->mainbin );
2910
2911   debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2912
2913   {
2914     debug_log("using pad caps to autopluging instead of doing typefind\n");
2915     caps = gst_pad_query_caps( pad );
2916     MMPLAYER_CHECK_NULL( caps );
2917     /* clear  previous result*/
2918     player->have_dynamic_pad = FALSE;
2919     new_element = gst_element_factory_make("rtpmp2tdepay", "wfd_rtp_depay");
2920     if ( !new_element )
2921     {
2922       debug_error ( "failed to create wfd rtp depay element\n" );
2923       goto ERROR;
2924     }
2925     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2926     /* add new element to the pipeline */
2927     if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2928     {
2929       debug_log("failed to add autoplug element to bin\n");
2930       goto ERROR;
2931     }
2932     /* get pad from element */
2933     sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2934     if ( !sinkpad )
2935     {
2936       debug_log("failed to get sinkpad from autoplug element\n");
2937       goto ERROR;
2938     }
2939     /* link it */
2940     if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2941     {
2942       debug_log("failed to link autoplug element\n");
2943       goto ERROR;
2944     }
2945     gst_object_unref (sinkpad);
2946     sinkpad = NULL;
2947     pad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "src" );
2948     caps = gst_pad_query_caps( pad );
2949     MMPLAYER_CHECK_NULL( caps );
2950     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2951     /* create typefind */
2952     new_element = gst_element_factory_make( "typefind", NULL );
2953     if ( ! new_element )
2954     {
2955       debug_log("failed to create typefind\n");
2956       goto ERROR;
2957     }
2958
2959     MMPLAYER_SIGNAL_CONNECT(   player,
2960                 G_OBJECT(new_element),
2961                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2962                 "have-type",
2963                 G_CALLBACK(__mmplayer_typefind_have_type),
2964                 (gpointer)player);
2965
2966     player->have_dynamic_pad = FALSE;
2967   }
2968
2969   /* excute new_element if created*/
2970   if ( new_element )
2971   {
2972     debug_log("adding new element to pipeline\n");
2973
2974     /* set state to READY before add to bin */
2975     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2976
2977     /* add new element to the pipeline */
2978     if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2979     {
2980       debug_log("failed to add autoplug element to bin\n");
2981       goto ERROR;
2982     }
2983
2984     /* get pad from element */
2985     sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2986     if ( !sinkpad )
2987     {
2988       debug_log("failed to get sinkpad from autoplug element\n");
2989       goto ERROR;
2990     }
2991
2992     /* link it */
2993     if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2994     {
2995       debug_log("failed to link autoplug element\n");
2996       goto ERROR;
2997     }
2998
2999     gst_object_unref (sinkpad);
3000     sinkpad = NULL;
3001
3002     /* run. setting PLAYING here since streamming source is live source */
3003     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
3004   }
3005
3006   /* store handle to futher manipulation */
3007   player->pipeline->mainbin[element_id].id = element_id;
3008   player->pipeline->mainbin[element_id].gst = new_element;
3009
3010   MMPLAYER_FLEAVE();
3011
3012   return;
3013
3014 STATE_CHANGE_FAILED:
3015 ERROR:
3016   /* FIXIT : take care if new_element has already added to pipeline */
3017   if ( new_element )
3018     gst_object_unref(GST_OBJECT(new_element));
3019
3020   if ( sinkpad )
3021     gst_object_unref(GST_OBJECT(sinkpad));
3022
3023   if ( caps )
3024     gst_object_unref(GST_OBJECT(caps));
3025
3026   /* FIXIT : how to inform this error to MSL ????? */
3027   /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
3028    * then post an error to application
3029    */
3030 }
3031 #endif
3032
3033 static GstPadProbeReturn
3034 __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
3035 {
3036         debug_log ("pad blocked callback, blocked");
3037         return GST_PAD_PROBE_OK;
3038 }
3039
3040 static GstPadProbeReturn
3041 __mmplayer_audio_data_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
3042 {
3043         mm_player_t* player = (mm_player_t*) u_data;
3044         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
3045
3046         /* TO_CHECK: performance */
3047         return_val_if_fail (player && GST_IS_BUFFER(pad_buffer), GST_PAD_PROBE_OK);
3048
3049         if (GST_BUFFER_PTS_IS_VALID(pad_buffer) && GST_BUFFER_DURATION_IS_VALID(pad_buffer))
3050                 player->gapless.next_pts = GST_BUFFER_PTS(pad_buffer) + GST_BUFFER_DURATION(pad_buffer);
3051
3052         return GST_PAD_PROBE_OK;
3053 }
3054
3055 static GstPadProbeReturn
3056 __mmplayer_gst_selector_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
3057 {
3058         GstPadProbeReturn ret = GST_PAD_PROBE_OK;
3059         GstEvent *event = GST_PAD_PROBE_INFO_DATA (info);
3060         mm_player_t* player = (mm_player_t*)data;
3061
3062         switch (GST_EVENT_TYPE (event)) {
3063                 case GST_EVENT_STREAM_START:
3064                 break;
3065                 case GST_EVENT_SEGMENT: {
3066                         GstSegment segment;
3067                         GstEvent *tmpev;
3068
3069                         if (!player->gapless.running)
3070                                 break;
3071
3072                         if (player->gapless.stream_changed) {
3073                                 player->gapless.start_time += player->gapless.next_pts;
3074                                 player->gapless.stream_changed = FALSE;
3075                         }
3076
3077                         debug_log ("event: %" GST_PTR_FORMAT, event);
3078                         gst_event_copy_segment (event, &segment);
3079
3080                         if (segment.format == GST_FORMAT_TIME)
3081                         {
3082                                 segment.base = player->gapless.start_time;
3083                                 debug_log ("base of segment: %" GST_TIME_FORMAT, GST_TIME_ARGS (segment.base));
3084
3085                                 tmpev = gst_event_new_segment (&segment);
3086                                 gst_event_set_seqnum (tmpev, gst_event_get_seqnum (event));
3087                                 gst_event_unref (event);
3088                                 GST_PAD_PROBE_INFO_DATA(info) = tmpev;
3089                         }
3090                         break;
3091                 }
3092                 default:
3093                 break;
3094         }
3095         return ret;
3096 }
3097
3098 static void
3099 __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data)
3100 {
3101         mm_player_t* player = NULL;
3102         GstElement* pipeline = NULL;
3103         GstElement* selector = NULL;
3104         GstElement* fakesink = NULL;
3105         GstCaps* caps = NULL;
3106         GstStructure* str = NULL;
3107         const gchar* name = NULL;
3108         GstPad* sinkpad = NULL;
3109         GstPad* srcpad = NULL;
3110         gboolean first_track = FALSE;
3111
3112         enum MainElementID elemId = MMPLAYER_M_NUM;
3113         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
3114
3115         /* check handles */
3116         player = (mm_player_t*)data;
3117
3118         return_if_fail (elem && pad);
3119         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3120
3121         //debug_log ("pad-added signal handling\n");
3122
3123         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3124
3125         /* get mimetype from caps */
3126         caps = gst_pad_query_caps (pad, NULL);
3127         if ( !caps )
3128         {
3129                 debug_error ("cannot get caps from pad.\n");
3130                 goto ERROR;
3131         }
3132
3133         str = gst_caps_get_structure (caps, 0);
3134         if ( ! str )
3135         {
3136                 debug_error ("cannot get structure from caps.\n");
3137                 goto ERROR;
3138         }
3139
3140         name = gst_structure_get_name (str);
3141         if ( ! name )
3142         {
3143                 debug_error ("cannot get mimetype from structure.\n");
3144                 goto ERROR;
3145         }
3146
3147         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3148         //debug_log ("detected mimetype : %s\n", name);
3149
3150         if (strstr(name, "video"))
3151         {
3152                 gint stype = 0;
3153                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
3154
3155                 /* don't make video because of not required, and not support multiple track */
3156                 if (stype == MM_DISPLAY_SURFACE_NULL)
3157                 {
3158                         debug_log ("no video sink by null surface or multiple track");
3159                         gchar *caps_str = gst_caps_to_string(caps);
3160                         if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
3161                         {
3162                                 player->set_mode.video_zc = TRUE;
3163                         }
3164                         MMPLAYER_FREEIF( caps_str );
3165
3166                         if (player->v_stream_caps)
3167                         {
3168                                 gst_caps_unref(player->v_stream_caps);
3169                                 player->v_stream_caps = NULL;
3170                         }
3171
3172                         debug_log ("create fakesink instead of videobin");
3173
3174                         /* fake sink */
3175                         fakesink = gst_element_factory_make ("fakesink", NULL);
3176                         if (fakesink == NULL)
3177                         {
3178                                 debug_error ("ERROR : fakesink create error\n");
3179                                 goto ERROR;
3180                         }
3181
3182                         player->video_fakesink = fakesink;
3183
3184                         gst_bin_add (GST_BIN(pipeline), fakesink);
3185
3186                         // link
3187                         sinkpad = gst_element_get_static_pad (fakesink, "sink");
3188
3189                         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3190                         {
3191                                 debug_warning ("failed to link fakesink\n");
3192                                 gst_object_unref (GST_OBJECT(fakesink));
3193                                 goto ERROR;
3194                         }
3195
3196                         if (player->set_mode.media_packet_video_stream)
3197                                 player->video_cb_probe_id = gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER, __mmplayer_video_stream_probe, player, NULL);
3198
3199                         g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
3200                         g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
3201                         gst_element_set_state (fakesink, GST_STATE_PAUSED);
3202
3203                         goto DONE;
3204                 }
3205                 __mmplayer_gst_decode_callback (elem, pad, player);
3206         }
3207         else
3208         {
3209                 if (strstr(name, "audio"))
3210                 {
3211                         gint samplerate = 0;
3212                         gint channels = 0;
3213
3214                         if (MMPLAYER_IS_ES_BUFF_SRC(player))
3215                         {
3216                                 __mmplayer_gst_decode_callback (elem, pad, player);
3217                                 return;
3218                         }
3219
3220                         debug_log ("audio selector \n");
3221                         elemId = MMPLAYER_M_A_INPUT_SELECTOR;
3222                         stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
3223
3224                         gst_structure_get_int (str, "rate", &samplerate);
3225                         gst_structure_get_int (str, "channels", &channels);
3226
3227                         if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
3228                                 /* fake sink */
3229                                 fakesink = gst_element_factory_make ("fakesink", NULL);
3230                                 if (fakesink == NULL)
3231                                 {
3232                                         debug_error ("ERROR : fakesink create error\n");
3233                                         goto ERROR;
3234                                 }
3235
3236                                 gst_bin_add (GST_BIN(pipeline), fakesink);
3237
3238                                 /* link */
3239                                 sinkpad = gst_element_get_static_pad (fakesink, "sink");
3240
3241                                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3242                                 {
3243                                         debug_warning ("failed to link fakesink\n");
3244                                         gst_object_unref (GST_OBJECT(fakesink));
3245                                         goto ERROR;
3246                                 }
3247
3248                                 g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
3249                                 g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
3250                                 gst_element_set_state (fakesink, GST_STATE_PAUSED);
3251
3252                                 goto DONE;
3253                         }
3254                 }
3255                 else if (strstr(name, "text"))
3256                 {
3257                         debug_log ("text selector \n");
3258                         elemId = MMPLAYER_M_T_INPUT_SELECTOR;
3259                         stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
3260                 }
3261                 else
3262                 {
3263                         debug_error ("wrong elem id \n");
3264                         goto ERROR;
3265                 }
3266         }
3267
3268         if(strstr(name, "video"))
3269                 return;
3270
3271         selector = player->pipeline->mainbin[elemId].gst;
3272
3273         if (selector == NULL)
3274         {
3275                 selector = gst_element_factory_make ("input-selector", NULL);
3276                 debug_log ("Creating input-selector\n");
3277                 if (selector == NULL)
3278                 {
3279                         debug_error ("ERROR : input-selector create error\n");
3280                         goto ERROR;
3281                 }
3282                 g_object_set (selector, "sync-streams", TRUE, NULL);
3283
3284                 player->pipeline->mainbin[elemId].id = elemId;
3285                 player->pipeline->mainbin[elemId].gst = selector;
3286
3287                 first_track = TRUE;
3288                 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK;      // default
3289
3290                 srcpad = gst_element_get_static_pad (selector, "src");
3291
3292 //              debug_log ("blocking %" GST_PTR_FORMAT, srcpad);
3293 //              gst_pad_set_blocked_async (srcpad, TRUE, __mmplayer_gst_selector_blocked, NULL);
3294 //              gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3295 //                      __mmplayer_gst_selector_blocked, NULL, NULL);
3296
3297                 player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
3298                         __mmplayer_gst_selector_event_probe, player, NULL);
3299
3300                 gst_element_set_state (selector, GST_STATE_PAUSED);
3301                 gst_bin_add (GST_BIN(pipeline), selector);
3302         }
3303         else
3304         {
3305                 debug_log ("input-selector is already created.\n");
3306                 selector = player->pipeline->mainbin[elemId].gst;
3307         }
3308
3309         // link
3310         debug_log ("Calling request pad with selector %p \n", selector);
3311         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3312
3313         debug_log ("got pad %s:%s from selector", GST_DEBUG_PAD_NAME (sinkpad));
3314
3315         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3316         {
3317                 debug_warning ("failed to link selector\n");
3318                 gst_object_unref (GST_OBJECT(selector));
3319                 goto ERROR;
3320         }
3321
3322         if (first_track)
3323         {
3324                 debug_log ("this is first track --> active track \n");
3325                 g_object_set (selector, "active-pad", sinkpad, NULL);
3326         }
3327
3328         _mmplayer_track_update_info(player, stream_type, sinkpad);
3329
3330
3331 DONE:
3332 ERROR:
3333
3334         if (caps)
3335         {
3336                 gst_caps_unref (caps);
3337         }
3338
3339         if (sinkpad)
3340         {
3341                 gst_object_unref (GST_OBJECT(sinkpad));
3342                 sinkpad = NULL;
3343         }
3344
3345         if (srcpad)
3346         {
3347                 gst_object_unref (GST_OBJECT(srcpad));
3348                 srcpad = NULL;
3349         }
3350
3351         return;
3352 }
3353
3354 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
3355 {
3356         GstPad* srcpad = NULL;
3357         MMHandleType attrs = 0;
3358         gint active_index = 0;
3359
3360         // [link] input-selector :: textbin
3361         srcpad = gst_element_get_static_pad (text_selector, "src");
3362         if (!srcpad)
3363         {
3364                 debug_error("failed to get srcpad from selector\n");
3365                 return;
3366         }
3367
3368         debug_log ("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
3369
3370         active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
3371         if ((active_index != DEFAULT_TRACK) &&
3372                 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE))
3373         {
3374                 debug_warning("failed to change text track\n");
3375                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
3376         }
3377
3378         player->no_more_pad = TRUE;
3379         __mmplayer_gst_decode_callback (text_selector, srcpad, player);
3380
3381         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3382 //      gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3383
3384         debug_log("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3385
3386         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
3387                 player->has_closed_caption = TRUE;
3388
3389         attrs = MMPLAYER_GET_ATTRS(player);
3390         if ( attrs )
3391         {
3392                 mm_attrs_set_int_by_name(attrs, "content_text_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3393                 if (mmf_attrs_commit (attrs))
3394                         debug_error("failed to commit.\n");
3395         }
3396         else
3397         {
3398                 debug_error("cannot get content attribute");
3399         }
3400
3401         if (srcpad)
3402         {
3403                 gst_object_unref ( GST_OBJECT(srcpad) );
3404                 srcpad = NULL;
3405         }
3406 }
3407
3408 int _mmplayer_gst_set_audio_channel(MMHandleType hplayer, MMPlayerAudioChannel ch_idx)
3409 {
3410         int result = MM_ERROR_NONE;
3411
3412         mm_player_t* player = (mm_player_t*)hplayer;
3413         MMPlayerGstElement* mainbin = NULL;
3414         gchar* change_pad_name = NULL;
3415         GstPad* sinkpad = NULL;
3416         GstCaps* caps = NULL;
3417
3418         MMPLAYER_FENTER();
3419
3420         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3421
3422         debug_log ("Change Audio mode to %d\n", ch_idx);
3423         player->use_deinterleave = TRUE;
3424
3425         if ((!player->pipeline) || (!player->pipeline->mainbin))
3426         {
3427                 debug_log ("pre setting : %d\n", ch_idx);
3428
3429                 player->audio_mode.active_pad_index = ch_idx;
3430                 return result;
3431         }
3432
3433         mainbin = player->pipeline->mainbin;
3434
3435         if (mainbin[MMPLAYER_M_A_SELECTOR].gst == NULL)
3436         {
3437                 if (player->max_audio_channels < 2)
3438                 {
3439                         debug_log ("mono channel track only\n");
3440                         return result;
3441                 }
3442
3443                 debug_warning ("selector doesn't exist\n");
3444                 return result;  /* keep playing */
3445         }
3446
3447         debug_log ("total_ch_num : %d\n", player->audio_mode.total_track_num);
3448
3449         if (player->audio_mode.total_track_num < 2)
3450         {
3451                 debug_warning ("there is no another audio path\n");
3452                 return result;  /* keep playing */
3453         }
3454
3455         if ((ch_idx < 0) || (ch_idx >= player->audio_mode.total_track_num))
3456         {
3457                 debug_warning ("Not a proper ch_idx : %d \n", ch_idx);
3458                 return result;  /* keep playing */
3459         }
3460
3461         /*To get the new pad from the selector*/
3462         change_pad_name = g_strdup_printf ("sink%d", ch_idx);
3463         if (change_pad_name == NULL)
3464         {
3465                 debug_warning ("Pad does not exists\n");
3466                 goto ERROR;     /* keep playing */
3467         }
3468
3469         debug_log ("new active pad name: %s\n", change_pad_name);
3470
3471         sinkpad = gst_element_get_static_pad (mainbin[MMPLAYER_M_A_SELECTOR].gst, change_pad_name);
3472         if (sinkpad == NULL)
3473         {
3474                 //result = MM_ERROR_PLAYER_INTERNAL;
3475                 goto ERROR;     /* keep playing */
3476         }
3477
3478         debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3479         g_object_set (mainbin[MMPLAYER_M_A_SELECTOR].gst, "active-pad", sinkpad, NULL);
3480
3481         caps = gst_pad_get_current_caps(sinkpad);
3482         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3483
3484         __mmplayer_set_audio_attrs (player, caps);
3485         player->audio_mode.active_pad_index = ch_idx;
3486
3487 ERROR:
3488
3489         if (sinkpad)
3490                 gst_object_unref (sinkpad);
3491
3492         MMPLAYER_FREEIF(change_pad_name);
3493
3494         MMPLAYER_FLEAVE();
3495         return result;
3496 }
3497
3498
3499
3500 static void
3501 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
3502 {
3503         mm_player_t* player = (mm_player_t*)data;
3504         GstElement* selector = NULL;
3505         GstElement* queue = NULL;
3506
3507         GstPad* srcpad = NULL;
3508         GstPad* sinkpad = NULL;
3509         gchar* caps_str= NULL;
3510
3511         MMPLAYER_FENTER();
3512         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3513
3514         caps_str = gst_caps_to_string(gst_pad_get_current_caps(pad));
3515         debug_log ("deinterleave new caps : %s\n", caps_str);
3516         MMPLAYER_FREEIF(caps_str);
3517
3518         if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL)
3519         {
3520                 debug_error ("ERROR : queue create error\n");
3521                 goto ERROR;
3522         }
3523
3524         g_object_set(G_OBJECT(queue),
3525                                 "max-size-buffers", 10,
3526                                 "max-size-bytes", 0,
3527                                 "max-size-time", (guint64)0,
3528                                 NULL);
3529
3530         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3531
3532         if (!selector)
3533         {
3534                 debug_error("there is no audio channel selector.\n");
3535                 goto ERROR;
3536         }
3537
3538         srcpad = gst_element_get_static_pad (queue, "src");
3539         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3540
3541         debug_log ("link (%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
3542
3543         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3544         {
3545                 debug_warning ("failed to link deinterleave - selector\n");
3546                 goto ERROR;
3547         }
3548
3549         gst_element_set_state (queue, GST_STATE_PAUSED);
3550         player->audio_mode.total_track_num++;
3551
3552 ERROR:
3553
3554         if (srcpad)
3555         {
3556                 gst_object_unref ( GST_OBJECT(srcpad) );
3557                 srcpad = NULL;
3558         }
3559
3560         if (sinkpad)
3561         {
3562                 gst_object_unref ( GST_OBJECT(sinkpad) );
3563                 sinkpad = NULL;
3564         }
3565
3566         MMPLAYER_FLEAVE();
3567         return;
3568 }
3569
3570 static void
3571 __mmplayer_gst_deinterleave_no_more_pads (GstElement *elem, gpointer data)
3572 {
3573         mm_player_t* player = NULL;
3574         GstElement* selector = NULL;
3575         GstPad* sinkpad = NULL;
3576         gint active_index = 0;
3577         gchar* change_pad_name = NULL;
3578         GstCaps* caps = NULL;   // no need to unref
3579
3580         MMPLAYER_FENTER();
3581         player = (mm_player_t*) data;
3582
3583         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3584
3585         if (!selector)
3586         {
3587                 debug_error("there is no audio channel selector.\n");
3588                 goto ERROR;
3589         }
3590
3591         active_index = player->audio_mode.active_pad_index;
3592
3593         if (active_index != DEFAULT_AUDIO_CH)
3594         {
3595                 gint audio_ch = DEFAULT_AUDIO_CH;
3596
3597                 /*To get the new pad from the selector*/
3598                 change_pad_name = g_strdup_printf ("sink%d", active_index);
3599                 if (change_pad_name != NULL)
3600                 {
3601                         sinkpad = gst_element_get_static_pad (selector, change_pad_name);
3602                         if (sinkpad != NULL)
3603                         {
3604                                 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3605                                 g_object_set (selector, "active-pad", sinkpad, NULL);
3606
3607                                 audio_ch = active_index;
3608
3609                                 caps = gst_pad_get_current_caps(sinkpad);
3610                                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3611
3612                                 __mmplayer_set_audio_attrs (player, caps);
3613                         }
3614                 }
3615
3616                 player->audio_mode.active_pad_index = audio_ch;
3617                 debug_log("audio LR info (0:stereo) = %d\n", player->audio_mode.active_pad_index);
3618         }
3619
3620 ERROR:
3621
3622         if (sinkpad)
3623                 gst_object_unref (sinkpad);
3624
3625         MMPLAYER_FLEAVE();
3626         return;
3627 }
3628
3629 static void
3630 __mmplayer_gst_build_deinterleave_path (GstElement *elem, GstPad *pad, gpointer data)
3631 {
3632         mm_player_t* player = NULL;
3633         MMPlayerGstElement *mainbin = NULL;
3634
3635         GstElement* tee = NULL;
3636         GstElement* stereo_queue = NULL;
3637         GstElement* mono_queue = NULL;
3638         GstElement* conv = NULL;
3639         GstElement* filter = NULL;
3640         GstElement* deinterleave = NULL;
3641         GstElement* selector = NULL;
3642
3643         GstPad* srcpad = NULL;
3644         GstPad* selector_srcpad = NULL;
3645         GstPad* sinkpad = NULL;
3646         GstCaps* caps = NULL;
3647
3648         MMPLAYER_FENTER();
3649
3650         /* check handles */
3651         player = (mm_player_t*) data;
3652
3653         return_if_fail( elem && pad );
3654         return_if_fail( player && player->pipeline && player->pipeline->mainbin );
3655
3656         mainbin = player->pipeline->mainbin;
3657
3658         /* tee */
3659         if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL)
3660         {
3661                 debug_error ("ERROR : tee create error\n");
3662                 goto ERROR;
3663         }
3664
3665         mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
3666         mainbin[MMPLAYER_M_A_TEE].gst = tee;
3667
3668         gst_element_set_state (tee, GST_STATE_PAUSED);
3669
3670         /* queue */
3671         srcpad = gst_element_get_request_pad (tee, "src_%u");
3672         if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3673         {
3674                 debug_error ("ERROR : stereo queue create error\n");
3675                 goto ERROR;
3676         }
3677
3678         g_object_set(G_OBJECT(stereo_queue),
3679                                 "max-size-buffers", 10,
3680                                 "max-size-bytes", 0,
3681                                 "max-size-time", (guint64)0,
3682                                 NULL);
3683
3684         player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
3685         player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
3686
3687         if (srcpad)
3688         {
3689                 gst_object_unref (GST_OBJECT(srcpad));
3690                 srcpad = NULL;
3691         }
3692
3693         srcpad = gst_element_get_request_pad (tee, "src_%u");
3694
3695         if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3696         {
3697                 debug_error ("ERROR : mono queue create error\n");
3698                 goto ERROR;
3699         }
3700
3701         g_object_set(G_OBJECT(mono_queue),
3702                                 "max-size-buffers", 10,
3703                                 "max-size-bytes", 0,
3704                                 "max-size-time", (guint64)0,
3705                                 NULL);
3706
3707         player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3708         player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3709
3710         gst_element_set_state (stereo_queue, GST_STATE_PAUSED);
3711         gst_element_set_state (mono_queue, GST_STATE_PAUSED);
3712
3713         /* audioconvert */
3714         srcpad = gst_element_get_static_pad (mono_queue, "src");
3715         if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL)
3716         {
3717                 debug_error ("ERROR : audioconvert create error\n");
3718                 goto ERROR;
3719         }
3720
3721         player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3722         player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3723
3724         /* caps filter */
3725         if (srcpad)
3726         {
3727                 gst_object_unref (GST_OBJECT(srcpad));
3728                 srcpad = NULL;
3729         }
3730         srcpad = gst_element_get_static_pad (conv, "src");
3731
3732         if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL)
3733         {
3734                 debug_error ("ERROR : capsfilter create error\n");
3735                 goto ERROR;
3736         }
3737
3738         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3739         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3740
3741         caps = gst_caps_from_string( "audio/x-raw-int, "
3742                                 "width = (int) 16, "
3743                                 "depth = (int) 16, "
3744                                 "channels = (int) 2");
3745
3746         g_object_set (GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL );
3747         gst_caps_unref( caps );
3748
3749         gst_element_set_state (conv, GST_STATE_PAUSED);
3750         gst_element_set_state (filter, GST_STATE_PAUSED);
3751
3752         /* deinterleave */
3753         if (srcpad)
3754         {
3755                 gst_object_unref (GST_OBJECT(srcpad));
3756                 srcpad = NULL;
3757         }
3758         srcpad = gst_element_get_static_pad (filter, "src");
3759
3760         if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL)
3761         {
3762                 debug_error ("ERROR : deinterleave create error\n");
3763                 goto ERROR;
3764         }
3765
3766         g_object_set (deinterleave, "keep-positions", TRUE, NULL);
3767
3768         MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3769                                                         G_CALLBACK (__mmplayer_gst_deinterleave_pad_added), player);
3770
3771         MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3772                                                         G_CALLBACK (__mmplayer_gst_deinterleave_no_more_pads), player);
3773
3774         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3775         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3776
3777         /* selector */
3778         selector = gst_element_factory_make ("input-selector", "audio-channel-selector");
3779         if (selector == NULL)
3780         {
3781                 debug_error ("ERROR : audio-selector create error\n");
3782                 goto ERROR;
3783         }
3784
3785         g_object_set (selector, "sync-streams", TRUE, NULL);
3786         gst_bin_add (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3787
3788         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3789         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3790
3791         selector_srcpad = gst_element_get_static_pad (selector, "src");
3792
3793         debug_log ("blocking %" GST_PTR_FORMAT, selector_srcpad);
3794         //gst_pad_set_blocked_async (selector_srcpad, TRUE, __mmplayer_gst_selector_blocked, NULL);
3795         gst_pad_add_probe(selector_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3796                         __mmplayer_gst_selector_blocked, NULL, NULL);
3797
3798         if (srcpad)
3799         {
3800                 gst_object_unref (GST_OBJECT(srcpad));
3801                 srcpad = NULL;
3802         }
3803
3804         srcpad = gst_element_get_static_pad(stereo_queue, "src");
3805         sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3806
3807         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3808         {
3809                 debug_warning ("failed to link queue_stereo - selector\n");
3810                 goto ERROR;
3811         }
3812
3813         player->audio_mode.total_track_num++;
3814
3815         g_object_set (selector, "active-pad", sinkpad, NULL);
3816         gst_element_set_state (deinterleave, GST_STATE_PAUSED);
3817         gst_element_set_state (selector, GST_STATE_PAUSED);
3818
3819         __mmplayer_gst_decode_callback (selector, selector_srcpad, player);
3820
3821         debug_log ("unblocking %" GST_PTR_FORMAT, selector_srcpad);
3822 //      gst_pad_set_blocked_async (selector_srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3823
3824 ERROR:
3825         if (sinkpad)
3826         {
3827                 gst_object_unref (GST_OBJECT(sinkpad));
3828                 sinkpad = NULL;
3829         }
3830
3831         if (srcpad)
3832         {
3833                 gst_object_unref (GST_OBJECT(srcpad));
3834                 srcpad = NULL;
3835         }
3836
3837         if (selector_srcpad)
3838         {
3839                 gst_object_unref (GST_OBJECT(selector_srcpad));
3840                 selector_srcpad = NULL;
3841         }
3842
3843         MMPLAYER_FLEAVE();
3844         return;
3845 }
3846
3847 static void
3848 __mmplayer_gst_decode_no_more_pads (GstElement *elem, gpointer data)
3849 {
3850         mm_player_t* player = NULL;
3851         GstPad* srcpad = NULL;
3852         GstElement* audio_selector = NULL;
3853         GstElement* text_selector = NULL;
3854         MMHandleType attrs = 0;
3855         gint active_index = 0;
3856         gint64 dur_bytes = 0L;
3857
3858         player = (mm_player_t*) data;
3859
3860         debug_log("no-more-pad signal handling\n");
3861
3862         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3863                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
3864         {
3865                 debug_warning("no need to go more");
3866
3867                 if (player->gapless.reconfigure)
3868                 {
3869                         player->gapless.reconfigure = FALSE;
3870                         MMPLAYER_PLAYBACK_UNLOCK(player);
3871                 }
3872
3873                 return;
3874         }
3875
3876         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3877                 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3878                 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3879                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
3880         {
3881                 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
3882
3883                 if (NULL == player->streamer)
3884                 {
3885                         debug_warning("invalid state for buffering");
3886                         goto ERROR;
3887                 }
3888
3889                 gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
3890                 guint buffer_bytes = init_buffering_time * ESTIMATED_BUFFER_UNIT;
3891
3892                 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
3893                 debug_log("[Decodebin2] set use-buffering on Q2 (pre buffer time: %d sec, buffer size : %d)\n", (gint)init_buffering_time, buffer_bytes);
3894
3895                 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
3896
3897                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
3898                         debug_error("fail to get duration.\n");
3899
3900                 // enable use-buffering on queue2 instead of multiqueue (ex)audio only streaming
3901                 // use file information was already set on Q2 when it was created.
3902                 __mm_player_streaming_set_queue2(player->streamer,
3903                                                 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
3904                                                 TRUE,                                                           // use_buffering
3905                                                 buffer_bytes,
3906                                                 init_buffering_time,
3907                                                 1.0,                                                            // low percent
3908                                                 player->ini.http_buffering_limit,       // high percent
3909                                                 FALSE,
3910                                                 NULL,
3911                                                 ((dur_bytes>0)?((guint64)dur_bytes):0));
3912         }
3913         audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
3914         text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3915         if (audio_selector)
3916         {
3917                 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
3918                 if ((active_index != DEFAULT_TRACK) &&
3919                         (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE))
3920                 {
3921                         debug_warning("failed to change audio track\n");
3922                         player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
3923                 }
3924
3925                 // [link] input-selector :: audiobin
3926                 srcpad = gst_element_get_static_pad (audio_selector, "src");
3927                 if (!srcpad)
3928                 {
3929                         debug_error("failed to get srcpad from selector\n");
3930                         goto ERROR;
3931                 }
3932
3933                 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3934                 if (!text_selector)
3935                         player->no_more_pad = TRUE;
3936
3937                 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2))
3938                 {
3939                         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3940 //                      gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3941
3942                         __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
3943                 }
3944                 else
3945                 {
3946                         __mmplayer_gst_decode_callback (audio_selector, srcpad, player);
3947
3948                         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3949 //                      gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3950                 }
3951
3952                 debug_log("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3953
3954                 attrs = MMPLAYER_GET_ATTRS(player);
3955                 if ( attrs )
3956                 {
3957                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3958                         if (mmf_attrs_commit (attrs))
3959                                 debug_error("failed to commit.\n");
3960                 }
3961                 else
3962                 {
3963                         debug_error("cannot get content attribute");
3964                 }
3965         }
3966         else
3967         {
3968                 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst))
3969                 {
3970                         debug_log ("There is no audio track : remove audiobin");
3971
3972                         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN );
3973                         __mmplayer_del_sink ( player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst );
3974
3975                         MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->audiobin, MMPLAYER_A_BIN );
3976                         MMPLAYER_FREEIF ( player->pipeline->audiobin )
3977                 }
3978
3979                 if (player->num_dynamic_pad == 0)
3980                 {
3981                         __mmplayer_pipeline_complete (NULL, player);
3982                 }
3983         }
3984
3985
3986         if (!MMPLAYER_IS_ES_BUFF_SRC(player))
3987         {
3988                 if (text_selector)
3989                 {
3990                         __mmplayer_handle_text_decode_path(player, text_selector);
3991                 }
3992         }
3993
3994         MMPLAYER_FLEAVE();
3995
3996 ERROR:
3997         if (srcpad)
3998         {
3999                 gst_object_unref ( GST_OBJECT(srcpad) );
4000                 srcpad = NULL;
4001         }
4002
4003         if (player->gapless.reconfigure)
4004         {
4005                 player->gapless.reconfigure = FALSE;
4006                 MMPLAYER_PLAYBACK_UNLOCK(player);
4007         }
4008 }
4009
4010 static void
4011 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // @
4012 {
4013         mm_player_t* player = NULL;
4014         MMHandleType attrs = 0;
4015         GstElement* pipeline = NULL;
4016         GstCaps* caps = NULL;
4017         gchar* caps_str = NULL;
4018         GstStructure* str = NULL;
4019         const gchar* name = NULL;
4020         GstPad* sinkpad = NULL;
4021         GstElement* sinkbin = NULL;
4022         gboolean reusing = FALSE;
4023         GstElement *text_selector = NULL;
4024
4025         /* check handles */
4026         player = (mm_player_t*) data;
4027
4028         return_if_fail( elem && pad );
4029         return_if_fail(player && player->pipeline && player->pipeline->mainbin);
4030
4031         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
4032
4033         attrs = MMPLAYER_GET_ATTRS(player);
4034         if ( !attrs )
4035         {
4036                 debug_error("cannot get content attribute\n");
4037                 goto ERROR;
4038         }
4039
4040         /* get mimetype from caps */
4041         caps = gst_pad_query_caps( pad, NULL );
4042         if ( !caps )
4043         {
4044                 debug_error("cannot get caps from pad.\n");
4045                 goto ERROR;
4046         }
4047         caps_str = gst_caps_to_string(caps);
4048
4049         str = gst_caps_get_structure( caps, 0 );
4050         if ( ! str )
4051         {
4052                 debug_error("cannot get structure from caps.\n");
4053                 goto ERROR;
4054         }
4055
4056         name = gst_structure_get_name(str);
4057         if ( ! name )
4058         {
4059                 debug_error("cannot get mimetype from structure.\n");
4060                 goto ERROR;
4061         }
4062
4063         //debug_log("detected mimetype : %s\n", name);
4064
4065         if (strstr(name, "audio"))
4066         {
4067                 if (player->pipeline->audiobin == NULL)
4068                 {
4069                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player))
4070                         {
4071                                 debug_error("failed to create audiobin. continuing without audio\n");
4072                                 goto ERROR;
4073                         }
4074
4075                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
4076                         debug_log("creating audiosink bin success\n");
4077                 }
4078                 else
4079                 {
4080                         reusing = TRUE;
4081                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
4082                         debug_log("reusing audiobin\n");
4083                         _mmplayer_update_content_attrs( player, ATTR_AUDIO);
4084                 }
4085
4086                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
4087                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
4088
4089                 player->audiosink_linked  = 1;
4090
4091                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
4092                 if ( !sinkpad )
4093                 {
4094                         debug_error("failed to get pad from sinkbin\n");
4095                         goto ERROR;
4096                 }
4097         }
4098         else if (strstr(name, "video"))
4099         {
4100                 if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
4101                 {
4102                         player->set_mode.video_zc = TRUE;
4103                 }
4104
4105                 if (player->pipeline->videobin == NULL)
4106                 {
4107                         /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
4108                         /* get video surface type */
4109                         int surface_type = 0;
4110                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
4111
4112                         if (surface_type == MM_DISPLAY_SURFACE_NULL)
4113                         {
4114                                 debug_log("not make videobin because it dose not want\n");
4115                                 goto ERROR;
4116                         }
4117
4118                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type) )
4119                         {
4120                                 debug_error("failed to create videobin. continuing without video\n");
4121                                 goto ERROR;
4122                         }
4123
4124                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
4125                         debug_log("creating videosink bin success\n");
4126                 }
4127                 else
4128                 {
4129                         reusing = TRUE;
4130                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
4131                         debug_log("re-using videobin\n");
4132                         _mmplayer_update_content_attrs( player, ATTR_VIDEO);
4133                 }
4134
4135                 /* FIXIT : track number shouldn't be hardcoded */
4136                 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 1);
4137                 player->videosink_linked  = 1;
4138
4139                 /* NOTE : intermediate code before doing H/W subtitle compositon */
4140                 if ( player->use_textoverlay && player->play_subtitle )
4141                 {
4142                         debug_log("using textoverlay for external subtitle");
4143                         /* check text bin has created well */
4144                         if ( player->pipeline && player->pipeline->textbin )
4145                         {
4146                                 /* get sinkpad from textoverlay */
4147                                 sinkpad = gst_element_get_static_pad(
4148                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
4149                                         "video_sink" );
4150                                 if ( ! sinkpad )
4151                                 {
4152                                         debug_error("failed to get sink pad from textoverlay");
4153                                         goto ERROR;
4154                                 }
4155
4156                                 /* link new pad with textoverlay first */
4157                                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
4158                                 {
4159                                         debug_error("failed to get pad from sinkbin\n");
4160                                         goto ERROR;
4161                                 }
4162
4163                                 gst_object_unref(sinkpad);
4164                                 sinkpad = NULL;
4165
4166                                 /* alright, override pad to textbin.src for futher link */
4167                                 pad = gst_element_get_static_pad(
4168                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
4169                                         "src" );
4170                                 if ( ! pad )
4171                                 {
4172                                         debug_error("failed to get sink pad from textoverlay");
4173                                         goto ERROR;
4174                                 }
4175                         }
4176                         else
4177                         {
4178                                 debug_error("should not reach here.");
4179                                 goto ERROR;
4180                         }
4181                 }
4182
4183                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
4184                 if ( !sinkpad )
4185                 {
4186                         debug_error("failed to get pad from sinkbin\n");
4187                         goto ERROR;
4188                 }
4189         }
4190         else if (strstr(name, "text"))
4191         {
4192                 if (player->pipeline->textbin == NULL)
4193                 {
4194                         MMPlayerGstElement* mainbin = NULL;
4195
4196                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
4197                         {
4198                                 debug_error("failed to create textbin. continuing without text\n");
4199                                 goto ERROR;
4200                         }
4201
4202                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
4203                         debug_log("creating textsink bin success\n");
4204
4205                         /* FIXIT : track number shouldn't be hardcoded */
4206                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
4207
4208                         player->textsink_linked  = 1;
4209                         debug_msg("player->textsink_linked set to 1\n");
4210
4211                         sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "text_sink" );
4212                         if ( !sinkpad )
4213                         {
4214                                 debug_error("failed to get pad from sinkbin\n");
4215                                 goto ERROR;
4216                         }
4217
4218                         mainbin = player->pipeline->mainbin;
4219
4220                         if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst)
4221                         {
4222                           /* input selector */
4223                           text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
4224                           if ( !text_selector )
4225                           {
4226                             debug_error ( "failed to create subtitle input selector element\n" );
4227                             goto ERROR;
4228                           }
4229                           g_object_set (text_selector, "sync-streams", TRUE, NULL);
4230
4231                           mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
4232                           mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
4233
4234                           /* warm up */
4235                           if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_READY))
4236                           {
4237                             debug_error("failed to set state(READY) to sinkbin\n");
4238                             goto ERROR;
4239                           }
4240
4241                           if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector))
4242                           {
4243                             debug_warning("failed to add subtitle input selector\n");
4244                             goto ERROR;
4245                           }
4246
4247                           debug_log ("created element input-selector");
4248
4249                         }
4250                         else
4251                         {
4252                           debug_log ("already having subtitle input selector");
4253                           text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
4254                         }
4255                 }
4256
4257                 else
4258                 {
4259                         if (!player->textsink_linked)
4260                         {
4261                                 debug_log("re-using textbin\n");
4262
4263                                 reusing = TRUE;
4264                                 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
4265
4266                                 player->textsink_linked  = 1;
4267                                 debug_msg("player->textsink_linked set to 1\n");
4268                         }
4269                         else
4270                         {
4271                                 debug_log("ignoring internal subtutle since external subtitle is available");
4272                         }
4273                 }
4274         }
4275         else
4276         {
4277                 debug_warning("unknown type of elementary stream! ignoring it...\n");
4278                 goto ERROR;
4279         }
4280
4281         if ( sinkbin )
4282         {
4283                 if(!reusing)
4284                 {
4285                         /* warm up */
4286                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_READY ) )
4287                         {
4288                                 debug_error("failed to set state(READY) to sinkbin\n");
4289                                 goto ERROR;
4290                         }
4291
4292                         /* Added for multi audio support to avoid adding audio bin again*/
4293                         /* add */
4294                         if ( FALSE == gst_bin_add( GST_BIN(pipeline), sinkbin ) )
4295                         {
4296                                 debug_error("failed to add sinkbin to pipeline\n");
4297                                 goto ERROR;
4298                         }
4299                 }
4300
4301                 /* link */
4302                 if (GST_PAD_LINK_OK != GST_PAD_LINK (pad, sinkpad))
4303                 {
4304                         debug_error("failed to get pad from sinkbin\n");
4305                         goto ERROR;
4306                 }
4307
4308                 if (!reusing)
4309                 {
4310                         /* run */
4311                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (sinkbin, GST_STATE_PAUSED))
4312                         {
4313                                 debug_error("failed to set state(PLAYING) to sinkbin\n");
4314                                 goto ERROR;
4315                         }
4316
4317                         if (text_selector)
4318                         {
4319                           if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_PAUSED))
4320                           {
4321                             debug_error("failed to set state(READY) to sinkbin\n");
4322                             goto ERROR;
4323                           }
4324                         }
4325                 }
4326
4327                 gst_object_unref (sinkpad);
4328                 sinkpad = NULL;
4329         }
4330
4331         debug_log ("linking sink bin success\n");
4332
4333         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
4334          * streaming task. if the task blocked, then buffer will not flow to the next element
4335          * ( autoplugging element ). so this is special hack for streaming. please try to remove it
4336          */
4337         /* dec stream count. we can remove fakesink if it's zero */
4338         if (player->num_dynamic_pad)
4339                 player->num_dynamic_pad--;
4340
4341         debug_log ("no more pads: %d stream count dec : %d (num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
4342
4343         if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
4344         {
4345                 __mmplayer_pipeline_complete (NULL, player);
4346         }
4347
4348         /* FIXIT : please leave a note why this code is needed */
4349         if(MMPLAYER_IS_WFD_STREAMING( player ))
4350         {
4351                 player->no_more_pad = TRUE;
4352         }
4353
4354 ERROR:
4355
4356         MMPLAYER_FREEIF(caps_str);
4357
4358         if ( caps )
4359                 gst_caps_unref( caps );
4360
4361         if ( sinkpad )
4362                 gst_object_unref(GST_OBJECT(sinkpad));
4363
4364         /* flusing out new attributes */
4365         if (  mmf_attrs_commit ( attrs ) )
4366         {
4367                 debug_error("failed to comit attributes\n");
4368         }
4369
4370         return;
4371 }
4372
4373 static gboolean
4374 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
4375 {
4376         int pro_value = 0; // in the case of expection, default will be returned.
4377         int dest_angle = rotation_angle;
4378         int rotation_type = -1;
4379         #define ROTATION_USING_SINK 0
4380         #define ROTATION_USING_CUSTOM 1
4381         #define ROTATION_USING_FLIP     2
4382
4383         return_val_if_fail(player, FALSE);
4384         return_val_if_fail(value, FALSE);
4385         return_val_if_fail(rotation_angle >= 0, FALSE);
4386
4387         if (rotation_angle >= 360)
4388         {
4389                 dest_angle = rotation_angle - 360;
4390         }
4391
4392         /* chech if supported or not */
4393         if ( dest_angle % 90 )
4394         {
4395                 debug_log("not supported rotation angle = %d", rotation_angle);
4396                 return FALSE;
4397         }
4398
4399         /*
4400           * xvimagesink only     (A)
4401           * custom_convert - no xv (e.g. memsink, evasimagesink  (B)
4402           * videoflip - avsysmemsink (C)
4403           */
4404         if (player->set_mode.video_zc)
4405         {
4406                 if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
4407                 {
4408                         rotation_type = ROTATION_USING_CUSTOM;
4409                 }
4410                 else // A
4411                 {
4412                         rotation_type = ROTATION_USING_SINK;
4413                 }
4414         }
4415         else
4416         {
4417                 int surface_type = 0;
4418                 rotation_type = ROTATION_USING_FLIP;
4419
4420                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
4421                 debug_log("check display surface type attribute: %d", surface_type);
4422
4423                 if ((surface_type == MM_DISPLAY_SURFACE_X) ||
4424                         (surface_type == MM_DISPLAY_SURFACE_EVAS && !strcmp(player->ini.videosink_element_evas, "evaspixmapsink")))
4425                 {
4426                         rotation_type = ROTATION_USING_SINK;
4427                 }
4428                 else
4429                 {
4430                         rotation_type = ROTATION_USING_FLIP; //C
4431                 }
4432
4433                 debug_log("using %d type for rotation", rotation_type);
4434         }
4435
4436         /* get property value for setting */
4437         switch(rotation_type)
4438         {
4439                 case ROTATION_USING_SINK: // xvimagesink, pixmap
4440                         {
4441                                 switch (dest_angle)
4442                                 {
4443                                         case 0:
4444                                                 break;
4445                                         case 90:
4446                                                 pro_value = 3; // clockwise 90
4447                                                 break;
4448                                         case 180:
4449                                                 pro_value = 2;
4450                                                 break;
4451                                         case 270:
4452                                                 pro_value = 1; // counter-clockwise 90
4453                                                 break;
4454                                 }
4455                         }
4456                         break;
4457                 case ROTATION_USING_CUSTOM:
4458                         {
4459                                 gchar *ename = NULL;
4460                                 ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
4461
4462                                 if (g_strrstr(ename, "fimcconvert"))
4463                                 {
4464                                         switch (dest_angle)
4465                                         {
4466                                                 case 0:
4467                                                         break;
4468                                                 case 90:
4469                                                         pro_value = 90; // clockwise 90
4470                                                         break;
4471                                                 case 180:
4472                                                         pro_value = 180;
4473                                                         break;
4474                                                 case 270:
4475                                                         pro_value = 270; // counter-clockwise 90
4476                                                         break;
4477                                         }
4478                                 }
4479                         }
4480                         break;
4481                 case ROTATION_USING_FLIP: // videoflip
4482                         {
4483                                         switch (dest_angle)
4484                                         {
4485
4486                                                 case 0:
4487                                                         break;
4488                                                 case 90:
4489                                                         pro_value = 1; // clockwise 90
4490                                                         break;
4491                                                 case 180:
4492                                                         pro_value = 2;
4493                                                         break;
4494                                                 case 270:
4495                                                         pro_value = 3; // counter-clockwise 90
4496                                                         break;
4497                                         }
4498                         }
4499                         break;
4500         }
4501
4502         debug_log("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
4503
4504         *value = pro_value;
4505
4506         return TRUE;
4507 }
4508
4509 int
4510 _mmplayer_update_video_param(mm_player_t* player) // @
4511 {
4512         MMHandleType attrs = 0;
4513         int surface_type = 0;
4514         int org_angle = 0; // current supported angle values are 0, 90, 180, 270
4515         int user_angle = 0;
4516         int user_angle_type= 0;
4517         int rotation_value = 0;
4518         gchar *org_orient = NULL;
4519
4520         MMPLAYER_FENTER();
4521
4522         /* check video sinkbin is created */
4523         return_val_if_fail ( player &&
4524                 player->pipeline &&
4525                 player->pipeline->videobin &&
4526                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
4527                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4528                 MM_ERROR_PLAYER_NOT_INITIALIZED );
4529
4530         attrs = MMPLAYER_GET_ATTRS(player);
4531         if ( !attrs )
4532         {
4533                 debug_error("cannot get content attribute");
4534                 return MM_ERROR_PLAYER_INTERNAL;
4535         }
4536
4537         /* update user roation */
4538         mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
4539
4540         /* get angle with user type */
4541         switch(user_angle_type)
4542         {
4543                 case MM_DISPLAY_ROTATION_NONE:
4544                         user_angle = 0;
4545                         break;
4546                 case MM_DISPLAY_ROTATION_90: // counter-clockwise 90
4547                         user_angle = 270;
4548                         break;
4549                 case MM_DISPLAY_ROTATION_180:
4550                         user_angle = 180;
4551                         break;
4552                 case MM_DISPLAY_ROTATION_270: // clockwise 90
4553                         user_angle = 90;
4554                         break;
4555         }
4556
4557         /* get original orientation */
4558         mm_attrs_get_string_by_name(attrs, "content_video_orientation", &org_orient);
4559
4560         if (org_orient)
4561         {
4562                 if (!strcmp (org_orient, "rotate-90"))
4563                         org_angle = 90;
4564                 else if (!strcmp (org_orient, "rotate-180"))
4565                         org_angle = 180;
4566                 else if (!strcmp (org_orient, "rotate-270"))
4567                         org_angle = 270;
4568                 else
4569                         debug_log ("original rotation is %s", org_orient);
4570         }
4571         else
4572         {
4573                 debug_log ("content_video_orientation get fail");
4574         }
4575
4576         debug_log("check user angle: %d, orientation: %d", user_angle, org_angle);
4577
4578         /* check video stream callback is used */
4579         if(!player->set_mode.media_packet_video_stream && player->use_video_stream )
4580         {
4581                 if (player->set_mode.video_zc)
4582                 {
4583                         gchar *ename = NULL;
4584                         int width = 0;
4585                         int height = 0;
4586
4587                         mm_attrs_get_int_by_name(attrs, "display_width", &width);
4588                         mm_attrs_get_int_by_name(attrs, "display_height", &height);
4589
4590                         /* resize video frame with requested values for fimcconvert */
4591                         ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
4592
4593                         if (ename && g_strrstr(ename, "fimcconvert"))
4594                         {
4595                                 if (width)
4596                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
4597
4598                                 if (height)
4599                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
4600
4601                                 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
4602                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
4603
4604                                 /* get rotation value to set */
4605                                 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4606
4607                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "rotate", rotation_value, NULL);
4608
4609                                 debug_log("updating fimcconvert - r[%d], w[%d], h[%d]", rotation_value, width, height);
4610                         }
4611                 }
4612                 else
4613                 {
4614                         debug_log("using video stream callback with memsink. player handle : [%p]", player);
4615
4616                         /* get rotation value to set */
4617                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4618
4619                         g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
4620                 }
4621
4622                 return MM_ERROR_NONE;
4623         }
4624
4625         /* update display surface */
4626         mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
4627         debug_log("check display surface type attribute: %d", surface_type);
4628
4629         /* configuring display */
4630         switch ( surface_type )
4631         {
4632                 case MM_DISPLAY_SURFACE_X:
4633                 {
4634                         /* ximagesink or xvimagesink */
4635                         void *surface = NULL;
4636                         int display_method = 0;
4637                         int roi_x = 0;
4638                         int roi_y = 0;
4639                         int roi_w = 0;
4640                         int roi_h = 0;
4641                         int src_crop_x = 0;
4642                         int src_crop_y = 0;
4643                         int src_crop_w = 0;
4644                         int src_crop_h = 0;
4645                         int force_aspect_ratio = 0;
4646                         gboolean visible = TRUE;
4647
4648 #ifdef HAVE_WAYLAND
4649                         /*set wl_display*/
4650                         void* wl_display = NULL;
4651                         GstContext *context = NULL;
4652                         int wl_window_x = 0;
4653                         int wl_window_y = 0;
4654                         int wl_window_width = 0;
4655                         int wl_window_height = 0;
4656
4657                         mm_attrs_get_data_by_name(attrs, "wl_display", &wl_display);
4658                         if (wl_display)
4659                                 context = gst_wayland_display_handle_context_new(wl_display);
4660                         if (context)
4661                                 gst_element_set_context(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), context);
4662
4663                         /*It should be set after setting window*/
4664                         mm_attrs_get_int_by_name(attrs, "wl_window_render_x", &wl_window_x);
4665                         mm_attrs_get_int_by_name(attrs, "wl_window_render_y", &wl_window_y);
4666                         mm_attrs_get_int_by_name(attrs, "wl_window_render_width", &wl_window_width);
4667                         mm_attrs_get_int_by_name(attrs, "wl_window_render_height", &wl_window_height);
4668 #endif
4669                         /* common case if using x surface */
4670                         mm_attrs_get_data_by_name(attrs, "display_overlay", &surface);
4671                         if ( surface )
4672                         {
4673 #ifdef HAVE_WAYLAND
4674                                 int wl_surface = 0;
4675                                 wl_surface = (int*)surface;
4676                                 debug_log("set video param : xid %p", (int*)surface);
4677                                 if (wl_surface)
4678                                 {
4679                                         gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), (int*)surface );
4680                                         /* After setting window handle, set render      rectangle */
4681                                         gst_video_overlay_set_render_rectangle(
4682                                                  GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ),
4683                                                  wl_window_x,wl_window_y,wl_window_width,wl_window_height);
4684                                 }
4685 #else // HAVE_X11
4686                                 int xwin_id = 0;
4687                                 xwin_id = *(int*)surface;
4688                                 debug_log("set video param : xid %p", *(int*)surface);
4689                                 if (xwin_id)
4690                                 {
4691                                         gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)surface );
4692                                 }
4693 #endif
4694                         }
4695                         else
4696                         {
4697                                 /* FIXIT : is it error case? */
4698                                 debug_warning("still we don't have xid on player attribute. create it's own surface.");
4699                         }
4700
4701                         /* if xvimagesink */
4702                         if (!strcmp(player->ini.videosink_element_x,"xvimagesink"))
4703                         {
4704                                 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
4705                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4706                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_x", &src_crop_x);
4707                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_y", &src_crop_y);
4708                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_width", &src_crop_w);
4709                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_height", &src_crop_h);
4710                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
4711                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
4712                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
4713                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
4714                                 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4715                                 #define DEFAULT_DISPLAY_MODE    2       // TV only, PRI_VIDEO_OFF_AND_SEC_VIDEO_FULL_SCREEN
4716
4717                                 /* setting for cropping media source */
4718                                 if (src_crop_w && src_crop_h)
4719                                 {
4720                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4721                                                 "src-crop-x", src_crop_x,
4722                                                 "src-crop-y", src_crop_y,
4723                                                 "src-crop-w", src_crop_w,
4724                                                 "src-crop-h", src_crop_h,
4725                                                 NULL );
4726                                 }
4727
4728                                 /* setting for ROI mode */
4729                                 if (display_method == 5)        // 5 for ROI mode
4730                                 {
4731                                         int roi_mode = 0;
4732                                         mm_attrs_get_int_by_name(attrs, "display_roi_mode", &roi_mode);
4733                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4734                                                 "dst-roi-mode", roi_mode,
4735                                                 "dst-roi-x", roi_x,
4736                                                 "dst-roi-y", roi_y,
4737                                                 "dst-roi-w", roi_w,
4738                                                 "dst-roi-h", roi_h,
4739                                                 NULL );
4740                                         /* get rotation value to set,
4741                                            do not use org_angle because ROI mode in xvimagesink needs both a rotation value and an orientation value */
4742                                         __mmplayer_get_property_value_for_rotation(player, user_angle, &rotation_value);
4743                                 }
4744                                 else
4745                                 {
4746                                         /* get rotation value to set */
4747                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4748                                 }
4749
4750                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4751                                         "force-aspect-ratio", force_aspect_ratio,
4752                                         "orientation", org_angle/90, // setting for orientation of media, it is used for ROI/ZOOM feature in xvimagesink
4753                                         "rotate", rotation_value,
4754                                         "handle-events", TRUE,
4755                                         "display-geometry-method", display_method,
4756                                         "draw-borders", FALSE,
4757                                         "handle-expose", FALSE,
4758                                         "visible", visible,
4759                                         "display-mode", DEFAULT_DISPLAY_MODE,
4760                                         NULL );
4761
4762                                 debug_log("set video param : rotate %d, method %d visible %d", rotation_value, display_method, visible);
4763                                 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 );
4764                                 debug_log("set video param : force aspect ratio %d, display mode %d", force_aspect_ratio, DEFAULT_DISPLAY_MODE);
4765                         }
4766                 }
4767                 break;
4768                 case MM_DISPLAY_SURFACE_EVAS:
4769                 {
4770                         void *object = NULL;
4771                         int scaling = 0;
4772                         gboolean visible = TRUE;
4773                         int display_method = 0;
4774
4775                         /* common case if using evas surface */
4776                         mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
4777                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4778                         mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
4779                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4780
4781                         /* if evasimagesink */
4782                         if (!strcmp(player->ini.videosink_element_evas,"evasimagesink"))
4783                         {
4784                                 if (object)
4785                                 {
4786                                         /* if it is evasimagesink, we are not supporting rotation */
4787                                         if (user_angle_type!=MM_DISPLAY_ROTATION_NONE)
4788                                         {
4789                                                 mm_attrs_set_int_by_name(attrs, "display_rotation", MM_DISPLAY_ROTATION_NONE);
4790                                                 if (mmf_attrs_commit (attrs)) /* return -1 if error */
4791                                                         debug_error("failed to commit\n");
4792                                                 debug_warning("unsupported feature");
4793                                                 return MM_ERROR_NOT_SUPPORT_API;
4794                                         }
4795                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4796                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4797                                                         "evas-object", object,
4798                                                         "visible", visible,
4799                                                         "display-geometry-method", display_method,
4800                                                         "rotate", rotation_value,
4801                                                         NULL);
4802                                         debug_log("set video param : method %d", display_method);
4803                                         debug_log("set video param : evas-object %x, visible %d", object, visible);
4804                                         debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
4805                                 }
4806                                 else
4807                                 {
4808                                         debug_error("no evas object");
4809                                         return MM_ERROR_PLAYER_INTERNAL;
4810                                 }
4811
4812
4813                                 /* if evasimagesink using converter */
4814                                 if (player->set_mode.video_zc && player->pipeline->videobin[MMPLAYER_V_CONV].gst)
4815                                 {
4816                                         int width = 0;
4817                                         int height = 0;
4818                                         int no_scaling = !scaling;
4819
4820                                         mm_attrs_get_int_by_name(attrs, "display_width", &width);
4821                                         mm_attrs_get_int_by_name(attrs, "display_height", &height);
4822
4823                                         /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
4824                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
4825                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-buffer-num", 5, NULL);
4826
4827                                         if (no_scaling)
4828                                         {
4829                                                 /* no-scaling order to fimcconvert, original width, height size of media src will be passed to sink plugin */
4830                                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst,
4831                                                                 "dst-width", 0, /* setting 0, output video width will be media src's width */
4832                                                                 "dst-height", 0, /* setting 0, output video height will be media src's height */
4833                                                                 NULL);
4834                                         }
4835                                         else
4836                                         {
4837                                                 /* scaling order to fimcconvert */
4838                                                 if (width)
4839                                                 {
4840                                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
4841                                                 }
4842                                                 if (height)
4843                                                 {
4844                                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
4845                                                 }
4846                                                 debug_log("set video param : video frame scaling down to width(%d) height(%d)", width, height);
4847                                         }
4848                                         debug_log("set video param : display_evas_do_scaling %d", scaling);
4849                                 }
4850                         }
4851
4852                         /* if evaspixmapsink */
4853                         if (!strcmp(player->ini.videosink_element_evas,"evaspixmapsink"))
4854                         {
4855                                 if (object)
4856                                 {
4857                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4858                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4859                                                         "evas-object", object,
4860                                                         "visible", visible,
4861                                                         "display-geometry-method", display_method,
4862                                                         "rotate", rotation_value,
4863                                                         NULL);
4864                                         debug_log("set video param : method %d", display_method);
4865                                         debug_log("set video param : evas-object %x, visible %d", object, visible);
4866                                         debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
4867                                 }
4868                                 else
4869                                 {
4870                                         debug_error("no evas object");
4871                                         return MM_ERROR_PLAYER_INTERNAL;
4872                                 }
4873
4874                                 int display_method = 0;
4875                                 int roi_x = 0;
4876                                 int roi_y = 0;
4877                                 int roi_w = 0;
4878                                 int roi_h = 0;
4879                                 int origin_size = !scaling;
4880
4881                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4882                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
4883                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
4884                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
4885                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
4886
4887                                 /* get rotation value to set */
4888                                 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4889
4890                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4891                                         "origin-size", origin_size,
4892                                         "rotate", rotation_value,
4893                                         "dst-roi-x", roi_x,
4894                                         "dst-roi-y", roi_y,
4895                                         "dst-roi-w", roi_w,
4896                                         "dst-roi-h", roi_h,
4897                                         "display-geometry-method", display_method,
4898                                         NULL );
4899
4900                                 debug_log("set video param : method %d", display_method);
4901                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
4902                                                                 roi_x, roi_y, roi_w, roi_h );
4903                                 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
4904                         }
4905                 }
4906                 break;
4907                 case MM_DISPLAY_SURFACE_X_EXT:  /* NOTE : this surface type is used for the videoTexture(canvasTexture) overlay */
4908                 {
4909                         void *pixmap_id_cb = NULL;
4910                         void *pixmap_id_cb_user_data = NULL;
4911                         int display_method = 0;
4912                         gboolean visible = TRUE;
4913
4914                         /* if xvimagesink */
4915                         if (strcmp(player->ini.videosink_element_x,"xvimagesink"))
4916                         {
4917                                 debug_error("videosink is not xvimagesink");
4918                                 return MM_ERROR_PLAYER_INTERNAL;
4919                         }
4920
4921                         /* get information from attributes */
4922                         mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
4923                         mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
4924                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4925                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4926
4927                         if ( pixmap_id_cb )
4928                         {
4929                                 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
4930                                 if (pixmap_id_cb_user_data)
4931                                 {
4932                                         debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
4933                                 }
4934                         }
4935                         else
4936                         {
4937                                 debug_error("failed to set pixmap-id-callback");
4938                                 return MM_ERROR_PLAYER_INTERNAL;
4939                         }
4940                         /* get rotation value to set */
4941                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4942
4943                         debug_log("set video param : rotate %d, method %d, visible %d", rotation_value, display_method, visible);
4944
4945                         /* set properties of videosink plugin */
4946                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4947                                 "display-geometry-method", display_method,
4948                                 "draw-borders", FALSE,
4949                                 "visible", visible,
4950                                 "rotate", rotation_value,
4951                                 "pixmap-id-callback", pixmap_id_cb,
4952                                 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
4953                                 NULL );
4954                 }
4955                 break;
4956                 case MM_DISPLAY_SURFACE_NULL:
4957                 {
4958                         /* do nothing */
4959                 }
4960                 break;
4961         }
4962
4963         MMPLAYER_FLEAVE();
4964
4965         return MM_ERROR_NONE;
4966 }
4967
4968 static int
4969 __mmplayer_gst_element_link_bucket(GList* element_bucket) // @
4970 {
4971         GList* bucket = element_bucket;
4972         MMPlayerGstElement* element = NULL;
4973         MMPlayerGstElement* prv_element = NULL;
4974         gint successful_link_count = 0;
4975
4976         MMPLAYER_FENTER();
4977
4978         return_val_if_fail(element_bucket, -1);
4979
4980         prv_element = (MMPlayerGstElement*)bucket->data;
4981         bucket = bucket->next;
4982
4983         for ( ; bucket; bucket = bucket->next )
4984         {
4985                 element = (MMPlayerGstElement*)bucket->data;
4986
4987                 if ( element && element->gst )
4988                 {
4989                         /* If next element is audio appsrc then make a seprate audio pipeline */
4990                         if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),"audio_appsrc") ||
4991                                 !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),"subtitle_appsrc"))
4992                         {
4993                                 prv_element = element;
4994                                 continue;
4995                         }
4996
4997                         if ( GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst)) )
4998                         {
4999                                 debug_log("linking [%s] to [%s] success\n",
5000                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
5001                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
5002                                 successful_link_count ++;
5003                         }
5004                         else
5005                         {
5006                                 debug_log("linking [%s] to [%s] failed\n",
5007                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
5008                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
5009                                 return -1;
5010                         }
5011                 }
5012
5013                 prv_element = element;
5014         }
5015
5016         MMPLAYER_FLEAVE();
5017
5018         return successful_link_count;
5019 }
5020
5021 static int
5022 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket) // @
5023 {
5024         GList* bucket = element_bucket;
5025         MMPlayerGstElement* element = NULL;
5026         int successful_add_count = 0;
5027
5028         MMPLAYER_FENTER();
5029
5030         return_val_if_fail(element_bucket, 0);
5031         return_val_if_fail(bin, 0);
5032
5033         for ( ; bucket; bucket = bucket->next )
5034         {
5035                 element = (MMPlayerGstElement*)bucket->data;
5036
5037                 if ( element && element->gst )
5038                 {
5039                         if( !gst_bin_add(bin, GST_ELEMENT(element->gst)) )
5040                         {
5041                                 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
5042                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
5043                                         GST_ELEMENT_NAME(GST_ELEMENT(bin) ) );
5044                                 return 0;
5045                         }
5046                         successful_add_count ++;
5047                 }
5048         }
5049
5050         MMPLAYER_FLEAVE();
5051
5052         return successful_add_count;
5053 }
5054
5055 static void __mmplayer_gst_caps_notify_cb (GstPad * pad, GParamSpec * unused, gpointer data)
5056 {
5057         mm_player_t* player = (mm_player_t*) data;
5058         GstCaps *caps = NULL;
5059         GstStructure *str = NULL;
5060         const char *name;
5061
5062         MMPLAYER_FENTER();
5063
5064         return_if_fail ( pad )
5065         return_if_fail ( unused )
5066         return_if_fail ( data )
5067
5068         caps = gst_pad_query_caps(pad, NULL);
5069         if ( !caps )
5070         {
5071                 return;
5072         }
5073
5074         str = gst_caps_get_structure(caps, 0);
5075         if ( !str )
5076         {
5077                 goto ERROR;
5078         }
5079
5080         name = gst_structure_get_name(str);
5081         if ( !name )
5082         {
5083                 goto ERROR;
5084         }
5085
5086         debug_log("name = %s\n", name);
5087
5088         if (strstr(name, "audio"))
5089         {
5090                 _mmplayer_update_content_attrs (player, ATTR_AUDIO);
5091
5092                 if (player->audio_stream_changed_cb)
5093                 {
5094                         debug_error("call the audio stream changed cb\n");
5095                         player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
5096                 }
5097         }
5098         else if (strstr(name, "video"))
5099         {
5100                 _mmplayer_update_content_attrs (player, ATTR_VIDEO);
5101
5102                 if (player->video_stream_changed_cb)
5103                 {
5104                         debug_error("call the video stream changed cb\n");
5105                         player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
5106                 }
5107         }
5108         else
5109         {
5110                 goto ERROR;
5111         }
5112
5113 ERROR:
5114
5115         gst_caps_unref(caps);
5116
5117         MMPLAYER_FLEAVE();
5118
5119         return;
5120 }
5121
5122
5123
5124 /**
5125  * This function is to create audio pipeline for playing.
5126  *
5127  * @param       player          [in]    handle of player
5128  *
5129  * @return      This function returns zero on success.
5130  * @remark
5131  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
5132  */
5133 #define MMPLAYER_CREATEONLY_ELEMENT(x_bin, x_id, x_factory, x_name) \
5134 x_bin[x_id].id = x_id;\
5135 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5136 if ( ! x_bin[x_id].gst )\
5137 {\
5138         debug_error("failed to create %s \n", x_factory);\
5139         goto ERROR;\
5140 }\
5141
5142 #define MMPLAYER_CREATE_ELEMENT_ADD_BIN(x_bin, x_id, x_factory, x_name, y_bin, x_player) \
5143 x_bin[x_id].id = x_id;\
5144 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5145 if ( ! x_bin[x_id].gst )\
5146 {\
5147         debug_error("failed to create %s \n", x_factory);\
5148         goto ERROR;\
5149 }\
5150 else\
5151 {\
5152         if (x_player->ini.set_dump_element_flag)\
5153                 __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
5154 }\
5155 if( !gst_bin_add(GST_BIN(y_bin), GST_ELEMENT(x_bin[x_id].gst)))\
5156 {\
5157         debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",\
5158                 GST_ELEMENT_NAME(GST_ELEMENT(x_bin[x_id].gst)),\
5159                 GST_ELEMENT_NAME(GST_ELEMENT(y_bin) ) );\
5160         goto ERROR;\
5161 }\
5162
5163 /* macro for code readability. just for sinkbin-creation functions */
5164 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
5165 do \
5166 { \
5167         x_bin[x_id].id = x_id;\
5168         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5169         if ( ! x_bin[x_id].gst )\
5170         {\
5171                 debug_error("failed to create %s \n", x_factory);\
5172                 goto ERROR;\
5173         }\
5174         else\
5175         {\
5176                 if (x_player->ini.set_dump_element_flag)\
5177                         __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
5178         }\
5179         if ( x_add_bucket )\
5180                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
5181 } while(0);
5182
5183 static void
5184 __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5185 {
5186         mm_player_t* player = (mm_player_t*) data;
5187
5188         gint channel = 0;
5189         gint rate = 0;
5190         gint depth = 0;
5191         gint endianness = 0;
5192         guint64 channel_mask = 0;
5193
5194         MMPlayerAudioStreamDataType audio_stream = { 0, };
5195         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5196
5197         MMPLAYER_FENTER();
5198         return_if_fail(player->audio_stream_render_cb_ex);
5199
5200         debug_log ("__mmplayer_audio_stream_decoded_render_cb new pad: %s", GST_PAD_NAME (pad));
5201
5202         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
5203         audio_stream.data = mapinfo.data;
5204         audio_stream.data_size = mapinfo.size;
5205
5206         GstCaps *caps = gst_pad_get_current_caps( pad );
5207         GstStructure *structure = gst_caps_get_structure (caps, 0);
5208
5209         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5210         gst_structure_get_int (structure, "rate", &rate);
5211         gst_structure_get_int (structure, "channels", &channel);
5212         gst_structure_get_int (structure, "depth", &depth);
5213         gst_structure_get_int (structure, "endianness", &endianness);
5214         gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
5215
5216         gst_caps_unref(GST_CAPS(caps));
5217
5218         audio_stream.bitrate = rate;
5219         audio_stream.channel = channel;
5220         audio_stream.depth = depth;
5221         audio_stream.is_little_endian = (endianness == 1234 ? 1 : 0);
5222         audio_stream.channel_mask = channel_mask;
5223         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);
5224         player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param);
5225         gst_buffer_unmap(buffer, &mapinfo);
5226
5227         MMPLAYER_FLEAVE();
5228 }
5229
5230 static void
5231 __mmplayer_gst_audio_deinterleave_pad_added (GstElement *elem, GstPad *pad, gpointer data)
5232 {
5233         mm_player_t* player = (mm_player_t*)data;
5234         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
5235         GstPad* sinkpad = NULL;
5236         GstElement *queue = NULL, *sink = NULL;
5237
5238         MMPLAYER_FENTER();
5239         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
5240
5241         queue = gst_element_factory_make ("queue", NULL);
5242         if (queue == NULL)
5243         {
5244                 debug_log ("fail make queue\n");
5245                 goto ERROR;
5246         }
5247
5248         sink = gst_element_factory_make ("fakesink", NULL);
5249         if (sink == NULL)
5250         {
5251                 debug_log ("fail make fakesink\n");
5252                 goto ERROR;
5253         }
5254
5255         gst_bin_add_many (GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
5256
5257         if (!gst_element_link_pads_full (queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING))
5258         {
5259                 debug_warning("failed to link queue & sink\n");
5260                 goto ERROR;
5261         }
5262
5263         sinkpad = gst_element_get_static_pad (queue, "sink");
5264
5265         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
5266         {
5267                 debug_warning ("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
5268                 goto ERROR;
5269         }
5270
5271         debug_error("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
5272
5273         gst_object_unref (sinkpad);
5274         g_object_set (sink, "sync", player->audio_stream_sink_sync, NULL);
5275         g_object_set (sink, "signal-handoffs", TRUE, NULL);
5276
5277         gst_element_set_state (sink, GST_STATE_PAUSED);
5278         gst_element_set_state (queue, GST_STATE_PAUSED);
5279
5280         MMPLAYER_SIGNAL_CONNECT( player,
5281                 G_OBJECT(sink),
5282                 MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
5283                 "handoff",
5284                 G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
5285                 (gpointer)player );
5286
5287         MMPLAYER_FLEAVE();
5288         return ;
5289
5290 ERROR:
5291         debug_error("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
5292         if (queue)
5293         {
5294                 gst_object_unref(GST_OBJECT(queue));
5295                 queue = NULL;
5296         }
5297         if (sink)
5298         {
5299                 gst_object_unref(GST_OBJECT(sink));
5300                 sink = NULL;
5301         }
5302         if (sinkpad)
5303         {
5304                 gst_object_unref ( GST_OBJECT(sinkpad) );
5305                 sinkpad = NULL;
5306         }
5307
5308         return;
5309 }
5310
5311 void __mmplayer_gst_set_audiosink_property(mm_player_t* player, MMHandleType attrs)
5312 {
5313         #define MAX_PROPS_LEN 64
5314         gint volume_type = 0;
5315         gint latency_mode = 0;
5316         gchar *stream_type = NULL;
5317         gint stream_id = 0;
5318         gchar stream_props[MAX_PROPS_LEN] = {0,};
5319         GstStructure *props = NULL;
5320
5321         /* set volume table
5322          * It should be set after player creation through attribute.
5323          * But, it can not be changed during playing.
5324          */
5325         MMPLAYER_FENTER();
5326         mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
5327         mm_attrs_get_string_by_name (attrs, "sound_stream_type", &stream_type );
5328
5329         if ( stream_id < 1 || !stream_type || strlen(stream_type) < 1)
5330         {
5331                 debug_error("stream_id[%d] or stream_type[%s] is not valid.\n", stream_id, stream_type);
5332         }
5333         else
5334         {
5335                 snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d", stream_type, stream_id);
5336                 props = gst_structure_from_string(stream_props, NULL);
5337                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
5338                 debug_log("stream_id[%d], stream_type[%s], result[%s].\n", stream_id, stream_type, stream_props);
5339         }
5340
5341         mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
5342         mm_attrs_get_int_by_name(attrs, "sound_volume_type", &volume_type);
5343
5344         /* hook sound_type if emergency case */
5345         if (player->sm.event == ASM_EVENT_EMERGENCY)
5346         {
5347                 debug_log ("emergency session, hook sound_type from [%d] to [%d]\n", volume_type, MM_SOUND_VOLUME_TYPE_EMERGENCY);
5348                 volume_type = MM_SOUND_VOLUME_TYPE_EMERGENCY;
5349         }
5350
5351         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
5352                         "latency", latency_mode,
5353                         "volumetype", volume_type,
5354                         NULL);
5355
5356         debug_log("audiosink property - volume type=%d, latency=%d \n",
5357                 volume_type, latency_mode);
5358
5359         MMPLAYER_FLEAVE();
5360 }
5361
5362 static int
5363 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
5364 {
5365         MMPlayerGstElement* first_element = NULL;
5366         MMPlayerGstElement* audiobin = NULL;
5367         MMHandleType attrs = 0;
5368         GstPad *pad = NULL;
5369         GstPad *ghostpad = NULL;
5370         GList* element_bucket = NULL;
5371         gboolean link_audio_sink_now = TRUE;
5372         int i =0;
5373
5374         MMPLAYER_FENTER();
5375
5376         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5377
5378         /* alloc handles */
5379         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
5380         if ( ! audiobin )
5381         {
5382                 debug_error("failed to allocate memory for audiobin\n");
5383                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5384         }
5385
5386         attrs = MMPLAYER_GET_ATTRS(player);
5387
5388         /* create bin */
5389         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
5390         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
5391         if ( !audiobin[MMPLAYER_A_BIN].gst )
5392         {
5393                 debug_error("failed to create audiobin\n");
5394                 goto ERROR;
5395         }
5396
5397         /* take it */
5398         player->pipeline->audiobin = audiobin;
5399
5400         player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
5401
5402         /* Adding audiotp plugin for reverse trickplay feature */
5403 //      MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
5404
5405         /* converter */
5406         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
5407
5408         /* resampler */
5409         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER,  player->ini.name_of_audio_resampler, "audio resampler", TRUE, player);
5410
5411         if (player->set_mode.pcm_extraction) // pcm extraction only and no sound output
5412         {
5413                 if(player->audio_stream_render_cb_ex)
5414                 {
5415                         char *caps_str = NULL;
5416                         GstCaps* caps = NULL;
5417                         gchar *format = NULL;
5418
5419                         /* capsfilter */
5420                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
5421
5422                         mm_attrs_get_string_by_name (player->attrs, "pcm_audioformat", &format );
5423
5424                         debug_log("contents : format: %s samplerate : %d pcm_channel: %d", format, player->pcm_samplerate, player->pcm_channel);
5425
5426                         caps = gst_caps_new_simple ("audio/x-raw",
5427                                         "format", G_TYPE_STRING, format,
5428                                         "rate", G_TYPE_INT, player->pcm_samplerate,
5429                                         "channels", G_TYPE_INT, player->pcm_channel,
5430                                         NULL);
5431                         caps_str = gst_caps_to_string(caps);
5432                         debug_log("new caps : %s\n", caps_str);
5433
5434                         g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5435
5436                         /* clean */
5437                         gst_caps_unref( caps );
5438                         MMPLAYER_FREEIF( caps_str );
5439
5440                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
5441
5442                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
5443                         /* raw pad handling signal */
5444                         MMPLAYER_SIGNAL_CONNECT( player,
5445                                 (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
5446                                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
5447                                                                                                 G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
5448                 }
5449                 else
5450                 {
5451                         int dst_samplerate = 0;
5452                         int dst_channels = 0;
5453                         int dst_depth = 0;
5454                         char *caps_str = NULL;
5455                         GstCaps* caps = NULL;
5456
5457                         /* get conf. values */
5458                         mm_attrs_multiple_get(player->attrs,
5459                                                 NULL,
5460                                                 "pcm_extraction_samplerate", &dst_samplerate,
5461                                                 "pcm_extraction_channels", &dst_channels,
5462                                                 "pcm_extraction_depth", &dst_depth,
5463                                                 NULL);
5464
5465                         /* capsfilter */
5466                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
5467                         caps = gst_caps_new_simple ("audio/x-raw",
5468                                         "rate", G_TYPE_INT, dst_samplerate,
5469                                         "channels", G_TYPE_INT, dst_channels,
5470                                         "depth", G_TYPE_INT, dst_depth,
5471                                         NULL);
5472                         caps_str = gst_caps_to_string(caps);
5473                         debug_log("new caps : %s\n", caps_str);
5474
5475                         g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5476
5477                         /* clean */
5478                         gst_caps_unref( caps );
5479                         MMPLAYER_FREEIF( caps_str );
5480
5481                         /* fake sink */
5482                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
5483
5484                         /* set sync */
5485                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
5486                 }
5487         }
5488         else // normal playback
5489         {
5490                 //GstCaps* caps = NULL;
5491                 gint channels = 0;
5492
5493                 /* for logical volume control */
5494                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
5495                 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
5496
5497                 if (player->sound.mute)
5498                 {
5499                         debug_log("mute enabled\n");
5500                         g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
5501                 }
5502
5503 #if 0
5504                 /*capsfilter */
5505                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
5506                 caps = gst_caps_from_string( "audio/x-raw-int, "
5507                                         "endianness = (int) LITTLE_ENDIAN, "
5508                                         "signed = (boolean) true, "
5509                                         "width = (int) 16, "
5510                                         "depth = (int) 16" );
5511                 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5512                 gst_caps_unref( caps );
5513 #endif
5514
5515                 /* chech if multi-chennels */
5516                 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)
5517                 {
5518                         GstPad *srcpad = NULL;
5519                         GstCaps *caps = NULL;
5520
5521                         if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src")))
5522                         {
5523                                 if ((caps = gst_pad_query_caps(srcpad, NULL)))
5524                                 {
5525                                         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5526                                         GstStructure *str = gst_caps_get_structure(caps, 0);
5527                                         if (str)
5528                                                 gst_structure_get_int (str, "channels", &channels);
5529                                         gst_caps_unref(caps);
5530                                 }
5531                                 gst_object_unref(srcpad);
5532                         }
5533                 }
5534
5535                 /* audio effect element. if audio effect is enabled */
5536                 if ( (strcmp(player->ini.name_of_audio_effect, ""))
5537                         && (channels <= 2)
5538                         && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom) )
5539                 {
5540                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.name_of_audio_effect, "audio effect filter", TRUE, player);
5541
5542                         debug_log("audio effect config. bypass = %d, effect type  = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
5543
5544                         if ( (!player->bypass_audio_effect)
5545                                 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom) )
5546                         {
5547                                 if ( MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type )
5548                                 {
5549                                         if (!_mmplayer_audio_effect_custom_apply(player))
5550                                         {
5551                                                 debug_msg("apply audio effect(custom) setting success\n");
5552                                         }
5553                                 }
5554                         }
5555
5556                         if ( (strcmp(player->ini.name_of_audio_effect_sec, ""))
5557                                 && (player->set_mode.rich_audio) )
5558                         {
5559                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.name_of_audio_effect_sec, "audio effect filter", TRUE, player);
5560                         }
5561                 }
5562                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
5563                 {
5564                         if (player->set_mode.rich_audio && channels <= 2)
5565                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VSP, "audiovsp", "x-speed", TRUE, player);
5566                 }
5567
5568                 /* create audio sink */
5569                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.name_of_audiosink, "audiosink", link_audio_sink_now, player);
5570
5571                 /* qos on */
5572                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);     /* qos on */
5573                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
5574
5575                 /* FIXIT : using system clock. isn't there another way? */
5576                 if (player->videodec_linked)
5577                 {
5578                         debug_log("provide clock for movie = %s", (player->ini.provide_clock_for_movie)?"audio_clock":"sys_clock");
5579                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_movie,  NULL);
5580                 }
5581                 else
5582                 {
5583                         debug_log("provide clock for music = %s", (player->ini.provide_clock_for_music)?"audio_clock":"sys_clock");
5584                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_music,  NULL);
5585                 }
5586
5587                 if (g_strrstr(player->ini.name_of_audiosink, "pulsesink"))
5588                         __mmplayer_gst_set_audiosink_property(player, attrs);
5589
5590                 /* Antishock can be enabled when player is resumed by soundCM.
5591                  * But, it's not used in MMS, setting and etc.
5592                  * Because, player start seems like late.
5593                  */
5594                 __mmplayer_set_antishock( player , FALSE );
5595         }
5596
5597         if (audiobin[MMPLAYER_A_SINK].gst)
5598         {
5599                 GstPad *sink_pad = NULL;
5600                 sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
5601                 MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
5602                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
5603                 gst_object_unref (GST_OBJECT(sink_pad));
5604         }
5605
5606         __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
5607
5608         /* adding created elements to bin */
5609         debug_log("adding created elements to bin\n");
5610         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket ))
5611         {
5612                 debug_error("failed to add elements\n");
5613                 goto ERROR;
5614         }
5615
5616         /* linking elements in the bucket by added order. */
5617         debug_log("Linking elements in the bucket by added order.\n");
5618         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5619         {
5620                 debug_error("failed to link elements\n");
5621                 goto ERROR;
5622         }
5623
5624         /* get first element's sinkpad for creating ghostpad */
5625         first_element = (MMPlayerGstElement *)element_bucket->data;
5626
5627         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5628         if ( ! pad )
5629         {
5630                 debug_error("failed to get pad from first element of audiobin\n");
5631                 goto ERROR;
5632         }
5633
5634         ghostpad = gst_ghost_pad_new("sink", pad);
5635         if ( ! ghostpad )
5636         {
5637                 debug_error("failed to create ghostpad\n");
5638                 goto ERROR;
5639         }
5640
5641         if ( FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad) )
5642         {
5643                 debug_error("failed to add ghostpad to audiobin\n");
5644                 goto ERROR;
5645         }
5646
5647         player->gapless.audio_data_probe_id = gst_pad_add_probe(ghostpad, GST_PAD_PROBE_TYPE_BUFFER,
5648                         __mmplayer_audio_data_probe, player, NULL);
5649
5650         gst_object_unref(pad);
5651
5652         g_list_free(element_bucket);
5653
5654         mm_attrs_set_int_by_name(attrs, "content_audio_found", TRUE);
5655
5656         MMPLAYER_FLEAVE();
5657
5658         return MM_ERROR_NONE;
5659
5660 ERROR:
5661
5662         debug_log("ERROR : releasing audiobin\n");
5663
5664         if ( pad )
5665                 gst_object_unref(GST_OBJECT(pad));
5666
5667         if ( ghostpad )
5668                 gst_object_unref(GST_OBJECT(ghostpad));
5669
5670         g_list_free( element_bucket );
5671
5672         /* release element which are not added to bin */
5673         for ( i = 1; i < MMPLAYER_A_NUM; i++ )  /* NOTE : skip bin */
5674         {
5675                 if ( audiobin[i].gst )
5676                 {
5677                         GstObject* parent = NULL;
5678                         parent = gst_element_get_parent( audiobin[i].gst );
5679
5680                         if ( !parent )
5681                         {
5682                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
5683                                 audiobin[i].gst = NULL;
5684                         }
5685                         else
5686                         {
5687                                 gst_object_unref(GST_OBJECT(parent));
5688                         }
5689                 }
5690         }
5691
5692         /* release audiobin with it's childs */
5693         if ( audiobin[MMPLAYER_A_BIN].gst )
5694         {
5695                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
5696         }
5697
5698         MMPLAYER_FREEIF( audiobin );
5699
5700         player->pipeline->audiobin = NULL;
5701
5702         return MM_ERROR_PLAYER_INTERNAL;
5703 }
5704
5705 static GstPadProbeReturn
5706 __mmplayer_audio_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
5707 {
5708         mm_player_t* player = (mm_player_t*) u_data;
5709         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
5710         GstMapInfo probe_info = GST_MAP_INFO_INIT;
5711
5712         gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
5713
5714         if (player->audio_stream_cb && probe_info.size && probe_info.data)
5715                 player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
5716
5717         return GST_PAD_PROBE_OK;
5718 }
5719
5720 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
5721 {
5722     return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
5723 }
5724
5725 static GstPadProbeReturn
5726 __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
5727 {
5728         GstCaps *caps = NULL;
5729         MMPlayerVideoStreamDataType stream;
5730         MMVideoBuffer *video_buffer = NULL;
5731         GstMemory *dataBlock = NULL;
5732         GstMemory *metaBlock = NULL;
5733         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5734         GstStructure *structure = NULL;
5735         const gchar *string_format = NULL;
5736         unsigned int fourcc = 0;
5737         mm_player_t* player = (mm_player_t*)user_data;
5738         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
5739
5740         return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
5741         return_val_if_fail(gst_buffer_n_memory(buffer)  , GST_PAD_PROBE_DROP);
5742
5743         caps = gst_pad_get_current_caps(pad);
5744         if (caps == NULL) {
5745                 debug_error( "Caps is NULL." );
5746                 return GST_PAD_PROBE_OK;
5747         }
5748
5749         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5750
5751         /* clear stream data structure */
5752         memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
5753
5754         structure = gst_caps_get_structure( caps, 0 );
5755         gst_structure_get_int(structure, "width", &(stream.width));
5756         gst_structure_get_int(structure, "height", &(stream.height));
5757         string_format = gst_structure_get_string(structure, "format");
5758         if(string_format) {
5759                 fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
5760         }
5761         stream.format = util_get_pixtype(fourcc);
5762         gst_caps_unref( caps );
5763         caps = NULL;
5764
5765     /*
5766         debug_log( "Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
5767                         GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format );
5768     */
5769
5770         if (stream.width == 0 || stream.height == 0 || stream.format == MM_PIXEL_FORMAT_INVALID) {
5771                 debug_error("Wrong condition!!");
5772                 return TRUE;
5773         }
5774
5775         /* set size and timestamp */
5776         dataBlock = gst_buffer_peek_memory(buffer, 0);
5777         stream.length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
5778         stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano sec -> mili sec */
5779
5780         /* check zero-copy */
5781         if (player->set_mode.video_zc &&
5782                 player->set_mode.media_packet_video_stream &&
5783                 gst_buffer_n_memory(buffer) > 1) {
5784                 metaBlock = gst_buffer_peek_memory(buffer, 1);
5785                 gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
5786                 video_buffer = (MMVideoBuffer *)mapinfo.data;
5787         }
5788
5789         if (video_buffer) {
5790                 /* set tbm bo */
5791                 if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
5792                         /* copy pointer of tbm bo, stride, elevation */
5793                         memcpy(stream.bo, video_buffer->handle.bo,
5794                                         sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
5795                 }
5796                 else if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
5797                         memcpy(stream.data, video_buffer->data,
5798                                         sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
5799                 }
5800                 memcpy(stream.stride, video_buffer->stride_width,
5801                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5802                 memcpy(stream.elevation, video_buffer->stride_height,
5803                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5804                 /* set gst buffer */
5805                 stream.internal_buffer = buffer;
5806         } else {
5807                 tbm_bo_handle thandle;
5808                 int stride = ((stream.width + 3) & (~3));
5809                 int elevation = stream.height;
5810                 int size = stride * elevation * 3 / 2;
5811                 gboolean gst_ret;
5812                 gst_ret = gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
5813                 if(!gst_ret) {
5814                         debug_error("fail to gst_memory_map");
5815                         return GST_PAD_PROBE_OK;
5816                 }
5817
5818                 stream.stride[0] = stride;
5819                 stream.elevation[0] = elevation;
5820                 if(stream.format == MM_PIXEL_FORMAT_I420) {
5821                         stream.stride[1] = stream.stride[2] = stride / 2;
5822                         stream.elevation[1] = stream.elevation[2] = elevation / 2;
5823                 }
5824                 else {
5825                         debug_error("default #plane is 2, format %d", stream.format);
5826                         stream.stride[1] = stride;
5827                         stream.elevation[1] = elevation / 2;
5828                 }
5829
5830                 stream.bo[0] = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
5831                 if(!stream.bo[0]) {
5832                         debug_error("Fail to tbm_bo_alloc!!");
5833                         return TRUE;
5834                 }
5835                 thandle = tbm_bo_map(stream.bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
5836                 if(thandle.ptr && mapinfo.data)
5837                         memcpy(thandle.ptr, mapinfo.data, size);
5838                 else
5839                         debug_error("data pointer is wrong. dest : %p, src : %p",
5840                                         thandle.ptr, mapinfo.data);
5841
5842                 tbm_bo_unmap(stream.bo[0]);
5843
5844         }
5845
5846         if (player->video_stream_cb) {
5847                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
5848         }
5849
5850         if (metaBlock) {
5851                 gst_memory_unmap(metaBlock, &mapinfo);
5852         }else {
5853                 gst_memory_unmap(dataBlock, &mapinfo);
5854                 tbm_bo_unref(stream.bo[0]);
5855         }
5856
5857         return GST_PAD_PROBE_OK;
5858 }
5859
5860 static int
5861 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket, gboolean use_video_stream)
5862 {
5863         gchar* video_csc = "videoconvert"; // default colorspace converter
5864         GList* element_bucket = *bucket;
5865
5866         return_val_if_fail(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5867
5868         MMPLAYER_FENTER();
5869
5870         if (!player->set_mode.media_packet_video_stream && use_video_stream)
5871         {
5872                 if (player->set_mode.video_zc && strlen(player->ini.name_of_video_converter) > 0)
5873                 {
5874                         video_csc = player->ini.name_of_video_converter;
5875                 }
5876
5877                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5878                 debug_log("using video converter: %s", video_csc);
5879
5880                 if ( !player->set_mode.video_zc)
5881                 {
5882                         gint width = 0;         //width of video
5883                         gint height = 0;                //height of video
5884                         GstCaps* video_caps = NULL;
5885                         GstStructure *structure = NULL;
5886
5887                         /* rotator, scaler and capsfilter */
5888                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5889                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "video scaler", TRUE, player);
5890                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CAPS, "capsfilter", "videocapsfilter", TRUE, player);
5891
5892                         /* get video stream caps parsed by demuxer */
5893
5894                         mm_attrs_get_int_by_name(player->attrs, "display_width", &width);
5895
5896                         if(width)
5897                                 structure = gst_structure_new("video/x-raw", "width", G_TYPE_INT, width, NULL);
5898
5899                         mm_attrs_get_int_by_name(player->attrs, "display_height", &height);
5900
5901                         if(structure && height) {
5902                                 gst_structure_set (structure, "height", G_TYPE_INT, height, NULL);
5903
5904                                 video_caps = gst_caps_new_full(structure, NULL);
5905                                 g_object_set (GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_CAPS].gst), "caps", video_caps, NULL );
5906                                 MMPLAYER_LOG_GST_CAPS_TYPE(video_caps);
5907                                 gst_caps_unref(video_caps);
5908                         }
5909                         else
5910                                 debug_error("fail to set capsfilter %p, width %d, height %d", structure, width, height);
5911
5912                         if(structure)
5913                                 gst_structure_free(structure);
5914
5915                 }
5916         }
5917         else
5918         {
5919                 MMDisplaySurfaceType surface_type = MM_DISPLAY_SURFACE_NULL;
5920                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", (int *)&surface_type);
5921
5922                 if (player->set_mode.video_zc)
5923                 {
5924                         if ( (surface_type == MM_DISPLAY_SURFACE_EVAS) && ( !strcmp(player->ini.videosink_element_evas, "evasimagesink")) )
5925                         {
5926                                 video_csc = player->ini.name_of_video_converter;
5927                         }
5928                         else
5929                         {
5930                                 video_csc = "";
5931                         }
5932                 }
5933
5934                 if (video_csc && (strcmp(video_csc, "")))
5935                 {
5936                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5937                         debug_log("using video converter: %s", video_csc);
5938                 }
5939
5940                 /* set video rotator */
5941                 if ( !player->set_mode.video_zc )
5942                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5943
5944                 /* videoscaler */
5945                 #if !defined(__arm__)
5946                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "videoscaler", TRUE, player);
5947                 #endif
5948         }
5949
5950         *bucket = element_bucket;
5951         MMPLAYER_FLEAVE();
5952         return MM_ERROR_NONE;
5953
5954 ERROR:
5955         *bucket = NULL;
5956         MMPLAYER_FLEAVE();
5957         return MM_ERROR_PLAYER_INTERNAL;
5958 }
5959
5960 /**
5961  * This function is to create video pipeline.
5962  *
5963  * @param       player          [in]    handle of player
5964  *              caps            [in]    src caps of decoder
5965  *              surface_type    [in]    surface type for video rendering
5966  *
5967  * @return      This function returns zero on success.
5968  * @remark
5969  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5970  */
5971 /**
5972   * VIDEO PIPELINE
5973   * - x surface (arm/x86) : xvimagesink
5974   * - evas surface  (arm) : evaspixmapsink
5975   *                         fimcconvert ! evasimagesink
5976   * - evas surface  (x86) : videoconvertor ! videoflip ! evasimagesink
5977   */
5978 static int
5979 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5980 {
5981         GstPad *pad = NULL;
5982         MMHandleType attrs;
5983         GList*element_bucket = NULL;
5984         MMPlayerGstElement* first_element = NULL;
5985         MMPlayerGstElement* videobin = NULL;
5986         gchar *videosink_element = NULL;
5987
5988         MMPLAYER_FENTER();
5989
5990         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5991
5992         /* alloc handles */
5993         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5994         if ( !videobin )
5995         {
5996                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5997         }
5998
5999         player->pipeline->videobin = videobin;
6000
6001         attrs = MMPLAYER_GET_ATTRS(player);
6002         if ( !attrs )
6003         {
6004                 debug_error("cannot get content attribute");
6005                 return MM_ERROR_PLAYER_INTERNAL;
6006         }
6007
6008         /* create bin */
6009         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
6010         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
6011         if ( !videobin[MMPLAYER_V_BIN].gst )
6012         {
6013                 debug_error("failed to create videobin");
6014                 goto ERROR;
6015         }
6016
6017         if( player->use_video_stream ) // video stream callback, so send raw video data to application
6018         {
6019                 debug_log("using memsink\n");
6020
6021                 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, TRUE) != MM_ERROR_NONE)
6022                         goto ERROR;
6023
6024                 /* finally, create video sink. output will be BGRA8888. */
6025                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, "avsysmemsink", "videosink", TRUE, player);
6026
6027                 MMPLAYER_SIGNAL_CONNECT( player,
6028                                                                          videobin[MMPLAYER_V_SINK].gst,
6029                                                                          MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
6030                                                                          "video-stream",
6031                                                                          G_CALLBACK(__mmplayer_videostream_cb),
6032                                                                          player );
6033         }
6034         else // render video data using sink plugin like xvimagesink
6035         {
6036                 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, FALSE) != MM_ERROR_NONE)
6037                         goto ERROR;
6038
6039                 /* set video sink */
6040                 switch (surface_type)
6041                 {
6042                         case MM_DISPLAY_SURFACE_X:
6043                                 if (strlen(player->ini.videosink_element_x) > 0)
6044                                         videosink_element = player->ini.videosink_element_x;
6045                                 else
6046                                         goto ERROR;
6047                                 break;
6048                         case MM_DISPLAY_SURFACE_EVAS:
6049                                 if (strlen(player->ini.videosink_element_evas) > 0)
6050                                         videosink_element = player->ini.videosink_element_evas;
6051                                 else
6052                                         goto ERROR;
6053                                 break;
6054                         case MM_DISPLAY_SURFACE_X_EXT:
6055                         {
6056                                 void *pixmap_id_cb = NULL;
6057                                 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
6058                                 if (pixmap_id_cb) /* this is used for the videoTextue(canvasTexture) overlay */
6059                                 {
6060                                         videosink_element = player->ini.videosink_element_x;
6061                                 }
6062                                 else
6063                                 {
6064                                         debug_error("something wrong.. callback function for getting pixmap id is null");
6065                                         goto ERROR;
6066                                 }
6067                                 break;
6068                         }
6069                         case MM_DISPLAY_SURFACE_NULL:
6070                                 if (strlen(player->ini.videosink_element_fake) > 0)
6071                                         videosink_element = player->ini.videosink_element_fake;
6072                                 else
6073                                         goto ERROR;
6074                                 break;
6075                         default:
6076                                 debug_error("unidentified surface type");
6077                                 goto ERROR;
6078                 }
6079
6080                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, videosink_element, TRUE, player);
6081                 debug_log("selected videosink name: %s", videosink_element);
6082
6083                 /* connect signal handlers for sink plug-in */
6084                 switch (surface_type) {
6085                         case MM_DISPLAY_SURFACE_X_EXT:
6086                                 MMPLAYER_SIGNAL_CONNECT( player,
6087                                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
6088                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
6089                                                                                 "frame-render-error",
6090                                                                                 G_CALLBACK(__mmplayer_videoframe_render_error_cb),
6091                                                                                 player );
6092                                 debug_log("videoTexture usage, connect a signal handler for pixmap rendering error");
6093                                 break;
6094                         default:
6095                                 break;
6096                 }
6097         }
6098
6099         if (_mmplayer_update_video_param(player) != MM_ERROR_NONE)
6100                 goto ERROR;
6101
6102         if (videobin[MMPLAYER_V_SINK].gst)
6103         {
6104                 GstPad *sink_pad = NULL;
6105                 sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
6106                 if (sink_pad)
6107                 {
6108                         MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
6109                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
6110                         gst_object_unref (GST_OBJECT(sink_pad));
6111                 }
6112                 else
6113                 {
6114                         debug_warning("failed to get sink pad from videosink\n");
6115                 }
6116         }
6117
6118         /* store it as it's sink element */
6119         __mmplayer_add_sink( player, videobin[MMPLAYER_V_SINK].gst );
6120
6121         /* adding created elements to bin */
6122         if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket) )
6123         {
6124                 debug_error("failed to add elements\n");
6125                 goto ERROR;
6126         }
6127
6128         /* Linking elements in the bucket by added order */
6129         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
6130         {
6131                 debug_error("failed to link elements\n");
6132                 goto ERROR;
6133         }
6134
6135         /* get first element's sinkpad for creating ghostpad */
6136         first_element = (MMPlayerGstElement *)element_bucket->data;
6137         if ( !first_element )
6138         {
6139                 debug_error("failed to get first element from bucket\n");
6140                 goto ERROR;
6141         }
6142
6143         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
6144         if ( !pad )
6145         {
6146                 debug_error("failed to get pad from first element\n");
6147                 goto ERROR;
6148         }
6149
6150         /* create ghostpad */
6151         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
6152         if ( FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
6153         {
6154                 debug_error("failed to add ghostpad to videobin\n");
6155                 goto ERROR;
6156         }
6157         gst_object_unref(pad);
6158
6159         /* done. free allocated variables */
6160         g_list_free(element_bucket);
6161
6162         mm_attrs_set_int_by_name(attrs, "content_video_found", TRUE);
6163
6164         MMPLAYER_FLEAVE();
6165
6166         return MM_ERROR_NONE;
6167
6168 ERROR:
6169         debug_error("ERROR : releasing videobin\n");
6170
6171         g_list_free( element_bucket );
6172
6173         if (pad)
6174                 gst_object_unref(GST_OBJECT(pad));
6175
6176         /* release videobin with it's childs */
6177         if ( videobin[MMPLAYER_V_BIN].gst )
6178         {
6179                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
6180         }
6181
6182
6183         MMPLAYER_FREEIF( videobin );
6184
6185         player->pipeline->videobin = NULL;
6186
6187         return MM_ERROR_PLAYER_INTERNAL;
6188 }
6189
6190 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
6191 {
6192         GList *element_bucket = NULL;
6193         MMPlayerGstElement *textbin = player->pipeline->textbin;
6194
6195         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", TRUE, player);
6196         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", TRUE, player);
6197         g_object_set (G_OBJECT (textbin[MMPLAYER_T_IDENTITY].gst),
6198                                                         "signal-handoffs", FALSE,
6199                                                         NULL);
6200
6201         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
6202         MMPLAYER_SIGNAL_CONNECT( player,
6203                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
6204                                                         MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
6205                                                         "handoff",
6206                                                         G_CALLBACK(__mmplayer_update_subtitle),
6207                                                         (gpointer)player );
6208
6209         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
6210         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
6211         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
6212
6213         if (!player->play_subtitle)
6214         {
6215                 debug_log ("add textbin sink as sink element of whole pipeline.\n");
6216                 __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
6217         }
6218
6219         /* adding created elements to bin */
6220         debug_log("adding created elements to bin\n");
6221         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
6222         {
6223                 debug_error("failed to add elements\n");
6224                 goto ERROR;
6225         }
6226
6227         /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
6228         GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
6229         GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
6230
6231         /* linking elements in the bucket by added order. */
6232         debug_log("Linking elements in the bucket by added order.\n");
6233         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
6234         {
6235                 debug_error("failed to link elements\n");
6236                 goto ERROR;
6237         }
6238
6239         /* done. free allocated variables */
6240         g_list_free(element_bucket);
6241
6242         if (textbin[MMPLAYER_T_QUEUE].gst)
6243         {
6244                 GstPad *pad = NULL;
6245                 GstPad *ghostpad = NULL;
6246
6247                 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_QUEUE].gst), "sink");
6248                 if (!pad)
6249                 {
6250                         debug_error("failed to get video pad of textbin\n");
6251                         return MM_ERROR_PLAYER_INTERNAL;
6252                 }
6253
6254                 ghostpad = gst_ghost_pad_new("text_sink", pad);
6255                 gst_object_unref(pad);
6256
6257                 if (!ghostpad)
6258                 {
6259                         debug_error("failed to create ghostpad of textbin\n");
6260                         goto ERROR;
6261                 }
6262
6263                 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad))
6264                 {
6265                         debug_error("failed to add ghostpad to textbin\n");
6266                         goto ERROR;
6267                 }
6268         }
6269
6270         return MM_ERROR_NONE;
6271
6272 ERROR:
6273         g_list_free(element_bucket);
6274
6275         return MM_ERROR_PLAYER_INTERNAL;
6276 }
6277
6278 static int __mmplayer_gst_create_text_pipeline(mm_player_t* player)
6279 {
6280         MMPlayerGstElement *textbin = NULL;
6281         GList *element_bucket = NULL;
6282         gint i = 0;
6283
6284         MMPLAYER_FENTER();
6285
6286         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6287
6288         /* alloc handles */
6289         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
6290         if ( ! textbin )
6291         {
6292                 debug_error("failed to allocate memory for textbin\n");
6293                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
6294         }
6295
6296         /* create bin */
6297         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
6298         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
6299         if ( !textbin[MMPLAYER_T_BIN].gst )
6300         {
6301                 debug_error("failed to create textbin\n");
6302                 goto ERROR;
6303         }
6304
6305         /* take it */
6306         player->pipeline->textbin = textbin;
6307
6308         /* fakesink */
6309         if (player->use_textoverlay)
6310         {
6311                 debug_log ("use textoverlay for displaying \n");
6312
6313                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_QUEUE, "queue", "text_t_queue", textbin[MMPLAYER_T_BIN].gst, player);
6314
6315                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_QUEUE, "queue", "text_v_queue", textbin[MMPLAYER_T_BIN].gst, player);
6316
6317                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_CONVERTER, "fimcconvert", "text_v_converter", textbin[MMPLAYER_T_BIN].gst, player);
6318
6319                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_OVERLAY, "textoverlay", "text_overlay", textbin[MMPLAYER_T_BIN].gst, player);
6320
6321                 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_QUEUE].gst, "src", textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "sink"))
6322                 {
6323                         debug_error("failed to link queue and converter\n");
6324                         goto ERROR;
6325                 }
6326
6327                 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "video_sink"))
6328                 {
6329                         debug_error("failed to link queue and textoverlay\n");
6330                         goto ERROR;
6331                 }
6332
6333                 if (!gst_element_link_pads (textbin[MMPLAYER_T_QUEUE].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "text_sink"))
6334                 {
6335                         debug_error("failed to link queue and textoverlay\n");
6336                         goto ERROR;
6337                 }
6338         }
6339         else
6340         {
6341                 int surface_type = 0;
6342
6343                 debug_log ("use subtitle message for displaying \n");
6344
6345                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
6346
6347                 switch(surface_type)
6348                 {
6349                         case MM_DISPLAY_SURFACE_X:
6350                         case MM_DISPLAY_SURFACE_EVAS:
6351                         case MM_DISPLAY_SURFACE_GL:
6352                         case MM_DISPLAY_SURFACE_NULL:
6353                         case MM_DISPLAY_SURFACE_X_EXT:
6354                                 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE)
6355                                 {
6356                                         debug_error("failed to make plain text elements\n");
6357                                         goto ERROR;
6358                                 }
6359                                 break;
6360
6361                         default:
6362                                 break;
6363                 }
6364         }
6365
6366         MMPLAYER_FLEAVE();
6367
6368         return MM_ERROR_NONE;
6369
6370 ERROR:
6371
6372         debug_log("ERROR : releasing textbin\n");
6373
6374         g_list_free( element_bucket );
6375
6376         /* release element which are not added to bin */
6377         for ( i = 1; i < MMPLAYER_T_NUM; i++ )  /* NOTE : skip bin */
6378         {
6379                 if ( textbin[i].gst )
6380                 {
6381                         GstObject* parent = NULL;
6382                         parent = gst_element_get_parent( textbin[i].gst );
6383
6384                         if ( !parent )
6385                         {
6386                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
6387                                 textbin[i].gst = NULL;
6388                         }
6389                         else
6390                         {
6391                                 gst_object_unref(GST_OBJECT(parent));
6392                         }
6393                 }
6394         }
6395
6396         /* release textbin with it's childs */
6397         if ( textbin[MMPLAYER_T_BIN].gst )
6398         {
6399                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
6400         }
6401
6402         MMPLAYER_FREEIF( textbin );
6403
6404         player->pipeline->textbin = NULL;
6405
6406         return MM_ERROR_PLAYER_INTERNAL;
6407 }
6408
6409
6410 static int
6411 __mmplayer_gst_create_subtitle_src(mm_player_t* player)
6412 {
6413         MMPlayerGstElement* mainbin = NULL;
6414         MMHandleType attrs = 0;
6415         GstElement *subsrc = NULL;
6416         GstElement *subparse = NULL;
6417         gchar *subtitle_uri =NULL;
6418         const gchar *charset = NULL;
6419         GstPad *pad = NULL;
6420
6421         MMPLAYER_FENTER();
6422
6423         /* get mainbin */
6424         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
6425
6426         mainbin = player->pipeline->mainbin;
6427
6428         attrs = MMPLAYER_GET_ATTRS(player);
6429         if ( !attrs )
6430         {
6431                 debug_error("cannot get content attribute\n");
6432                 return MM_ERROR_PLAYER_INTERNAL;
6433         }
6434
6435         mm_attrs_get_string_by_name ( attrs, "subtitle_uri", &subtitle_uri );
6436         if ( !subtitle_uri || strlen(subtitle_uri) < 1)
6437         {
6438                 debug_error("subtitle uri is not proper filepath.\n");
6439                 return MM_ERROR_PLAYER_INVALID_URI;
6440         }
6441         debug_log("subtitle file path is [%s].\n", subtitle_uri);
6442
6443
6444         /* create the subtitle source */
6445         subsrc = gst_element_factory_make("filesrc", "subtitle_source");
6446         if ( !subsrc )
6447         {
6448                 debug_error ( "failed to create filesrc element\n" );
6449                 goto ERROR;
6450         }
6451         g_object_set(G_OBJECT (subsrc), "location", subtitle_uri, NULL);
6452
6453         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6454         mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
6455
6456         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc))
6457         {
6458                 debug_warning("failed to add queue\n");
6459                 goto ERROR;
6460         }
6461
6462         /* subparse */
6463         subparse = gst_element_factory_make("subparse", "subtitle_parser");
6464         if ( !subparse )
6465         {
6466                 debug_error ( "failed to create subparse element\n" );
6467                 goto ERROR;
6468         }
6469
6470         charset = util_get_charset(subtitle_uri);
6471         if (charset)
6472         {
6473                 debug_log ("detected charset is %s\n", charset );
6474                 g_object_set (G_OBJECT (subparse), "subtitle-encoding", charset, NULL);
6475         }
6476
6477         mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE;
6478         mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
6479
6480         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse))
6481         {
6482                 debug_warning("failed to add subparse\n");
6483                 goto ERROR;
6484         }
6485
6486         if (!gst_element_link_pads (subsrc, "src", subparse, "sink"))
6487         {
6488                 debug_warning("failed to link subsrc and subparse\n");
6489                 goto ERROR;
6490         }
6491
6492         player->play_subtitle = TRUE;
6493         player->adjust_subtitle_pos = 0;
6494
6495         debug_log ("play subtitle using subtitle file\n");
6496
6497         if (player->pipeline->textbin == NULL)
6498         {
6499                 if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
6500                 {
6501                         debug_error("failed to create textbin. continuing without text\n");
6502                         goto ERROR;
6503                 }
6504
6505                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst)))
6506                 {
6507                         debug_warning("failed to add textbin\n");
6508                         goto ERROR;
6509                 }
6510
6511                 debug_log ("link text input selector and textbin ghost pad");
6512
6513                 player->textsink_linked = 1;
6514                 player->external_text_idx = 0;
6515                 debug_msg("player->textsink_linked set to 1\n");
6516         }
6517         else
6518         {
6519                 debug_log("text bin has been created. reuse it.");
6520                 player->external_text_idx = 1;
6521         }
6522
6523         if (!gst_element_link_pads (subparse, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink"))
6524         {
6525                 debug_warning("failed to link subparse and textbin\n");
6526                 goto ERROR;
6527         }
6528
6529         pad = gst_element_get_static_pad (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
6530
6531         if (!pad)
6532         {
6533                 debug_error("failed to get sink pad from textsink to probe data");
6534                 return MM_ERROR_PLAYER_INTERNAL;
6535         }
6536
6537         gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
6538                                 __mmplayer_subtitle_adjust_position_probe, player, NULL);
6539
6540         gst_object_unref(pad);
6541         pad=NULL;
6542
6543         /* create dot. for debugging */
6544         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-with-subtitle" );
6545         MMPLAYER_FLEAVE();
6546
6547         return MM_ERROR_NONE;
6548
6549 ERROR:
6550         player->textsink_linked = 0;
6551         return MM_ERROR_PLAYER_INTERNAL;
6552 }
6553
6554 gboolean
6555 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
6556 {
6557         mm_player_t* player = (mm_player_t*) data;
6558         MMMessageParamType msg = {0, };
6559         GstClockTime duration = 0;
6560         gpointer text = NULL;
6561         guint text_size = 0;
6562         gboolean ret = TRUE;
6563         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
6564
6565         MMPLAYER_FENTER();
6566
6567         return_val_if_fail ( player, FALSE );
6568         return_val_if_fail ( buffer, FALSE );
6569
6570         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
6571         text = g_memdup(mapinfo.data, mapinfo.size);
6572         text_size = mapinfo.size;
6573         duration = GST_BUFFER_DURATION(buffer);
6574
6575
6576         if ( player->set_mode.subtitle_off )
6577         {
6578                 debug_log("subtitle is OFF.\n" );
6579                 return TRUE;
6580         }
6581
6582         if ( !text || (text_size == 0))
6583         {
6584                 debug_log("There is no subtitle to be displayed.\n" );
6585                 return TRUE;
6586         }
6587
6588         msg.data = (void *) text;
6589         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
6590
6591         debug_log("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
6592
6593         MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
6594         gst_buffer_unmap(buffer, &mapinfo);
6595
6596         MMPLAYER_FLEAVE();
6597
6598         return ret;
6599 }
6600
6601 static GstPadProbeReturn
6602 __mmplayer_subtitle_adjust_position_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
6603
6604 {
6605         mm_player_t *player = (mm_player_t *) u_data;
6606         GstClockTime cur_timestamp = 0;
6607         gint64 adjusted_timestamp = 0;
6608         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
6609         GstMapInfo probe_info = GST_MAP_INFO_INIT;
6610
6611         return_val_if_fail ( player, FALSE );
6612
6613         gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
6614
6615         if ( player->set_mode.subtitle_off )
6616         {
6617                 debug_log("subtitle is OFF.\n" );
6618                 return TRUE;
6619         }
6620
6621         if (player->adjust_subtitle_pos == 0 )
6622         {
6623                 debug_log("nothing to do");
6624                 return TRUE;
6625         }
6626
6627         cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
6628         adjusted_timestamp = (gint64) cur_timestamp + ((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
6629
6630         gst_buffer_unmap(buffer, &probe_info);
6631
6632         if ( adjusted_timestamp < 0)
6633         {
6634                 debug_log("adjusted_timestamp under zero");
6635                 MMPLAYER_FLEAVE();
6636                 return FALSE;
6637         }
6638
6639         GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
6640         debug_log("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
6641                                 GST_TIME_ARGS(cur_timestamp),
6642                                 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
6643
6644         return GST_PAD_PROBE_OK;
6645 }
6646 static int      __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
6647 {
6648         MMPLAYER_FENTER();
6649
6650         /* check player and subtitlebin are created */
6651         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6652         return_val_if_fail ( player->play_subtitle, MM_ERROR_NOT_SUPPORT_API );
6653
6654         if (position == 0)
6655         {
6656                 debug_log ("nothing to do\n");
6657                 MMPLAYER_FLEAVE();
6658                 return MM_ERROR_NONE;
6659         }
6660
6661         switch (format)
6662         {
6663                 case MM_PLAYER_POS_FORMAT_TIME:
6664                 {
6665                         /* check current postion */
6666                         player->adjust_subtitle_pos = position;
6667
6668                         debug_log("save adjust_subtitle_pos in player") ;
6669                 }
6670                 break;
6671
6672                 default:
6673                 {
6674                         debug_warning("invalid format.\n");
6675                         MMPLAYER_FLEAVE();
6676                         return MM_ERROR_INVALID_ARGUMENT;
6677                 }
6678         }
6679
6680         MMPLAYER_FLEAVE();
6681
6682         return MM_ERROR_NONE;
6683 }
6684 static int __gst_adjust_video_position(mm_player_t* player, int offset)
6685 {
6686         MMPLAYER_FENTER();
6687         debug_log("adjusting video_pos in player") ;
6688         int current_pos = 0;
6689         /* check player and videobin are created */
6690         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6691         if ( !player->pipeline->videobin ||
6692                         !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
6693         {
6694                 debug_log("no video pipeline or sink is there");
6695                 return MM_ERROR_PLAYER_INVALID_STATE ;
6696         }
6697         if (offset == 0)
6698         {
6699                 debug_log ("nothing to do\n");
6700                 MMPLAYER_FLEAVE();
6701                 return MM_ERROR_NONE;
6702         }
6703         if(__gst_get_position ( player, MM_PLAYER_POS_FORMAT_TIME, (unsigned long*)&current_pos ) != MM_ERROR_NONE )
6704         {
6705                 debug_log("failed to get current position");
6706                 return MM_ERROR_PLAYER_INTERNAL;
6707         }
6708         if ( (current_pos - offset ) < GST_TIME_AS_MSECONDS(player->duration) )
6709         {
6710                 debug_log("enter video delay is valid");
6711         }
6712         else {
6713                 debug_log("enter video delay is crossing content boundary");
6714                 return MM_ERROR_INVALID_ARGUMENT ;
6715         }
6716         g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst),"ts-offset",((gint64) offset * G_GINT64_CONSTANT(1000000)),NULL);
6717         debug_log("video delay has been done");
6718         MMPLAYER_FLEAVE();
6719
6720         return MM_ERROR_NONE;
6721 }
6722
6723 static void
6724 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data) // @
6725 {
6726         GstElement *appsrc = element;
6727         tBuffer *buf = (tBuffer *)user_data;
6728         GstBuffer *buffer = NULL;
6729         GstFlowReturn ret = GST_FLOW_OK;
6730         gint len = size;
6731
6732         return_if_fail ( element );
6733         return_if_fail ( buf );
6734
6735         buffer = gst_buffer_new ();
6736
6737         if (buf->offset >= buf->len)
6738         {
6739                 debug_log("call eos appsrc\n");
6740                 g_signal_emit_by_name (appsrc, "end-of-stream", &ret);
6741                 return;
6742         }
6743
6744         if ( buf->len - buf->offset < size)
6745         {
6746                 len = buf->len - buf->offset + buf->offset;
6747         }
6748
6749         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));
6750         GST_BUFFER_OFFSET(buffer) = buf->offset;
6751         GST_BUFFER_OFFSET_END(buffer) = buf->offset + len;
6752
6753         //debug_log("feed buffer %p, offset %u-%u length %u\n", buffer, buf->offset, buf->len,len);
6754         g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
6755
6756         buf->offset += len;
6757 }
6758
6759 static gboolean
6760 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data) // @
6761 {
6762         tBuffer *buf = (tBuffer *)user_data;
6763
6764         return_val_if_fail ( buf, FALSE );
6765
6766         buf->offset  = (int)size;
6767
6768         return TRUE;
6769 }
6770
6771 static void
6772 __gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data) // @
6773 {
6774         mm_player_t *player  = (mm_player_t*)user_data;
6775         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
6776
6777         return_if_fail ( player );
6778
6779         debug_msg("app-src: feed data\n");
6780
6781         if (player->media_stream_buffer_status_cb[type])
6782                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
6783 }
6784
6785 static gboolean
6786 __gst_appsrc_seek_data(GstElement *element, guint64 offset, gpointer user_data) // @
6787 {
6788         mm_player_t *player  = (mm_player_t*)user_data;
6789         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
6790
6791         return_val_if_fail ( player, FALSE );
6792
6793         debug_msg("app-src: seek data\n");
6794
6795         if(player->media_stream_seek_data_cb[type])
6796                 player->media_stream_seek_data_cb[type](type, offset, player->buffer_cb_user_param);
6797
6798         return TRUE;
6799 }
6800
6801
6802 static gboolean
6803 __gst_appsrc_enough_data(GstElement *element, gpointer user_data) // @
6804 {
6805         mm_player_t *player  = (mm_player_t*)user_data;
6806         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
6807
6808         return_val_if_fail ( player, FALSE );
6809
6810         debug_msg("app-src: enough data:%p\n", player->media_stream_buffer_status_cb[type]);
6811
6812         if (player->media_stream_buffer_status_cb[type])
6813                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
6814
6815         return TRUE;
6816 }
6817
6818 int
6819 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
6820 {
6821         mm_player_t* player = (mm_player_t*)hplayer;
6822         GstBuffer *buffer = NULL;
6823         GstFlowReturn gst_ret = GST_FLOW_OK;
6824         int ret = MM_ERROR_NONE;
6825 //      gint len = size;
6826
6827         MMPLAYER_FENTER();
6828
6829         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6830
6831         /* check current state */
6832 //      MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
6833
6834
6835         /* NOTE : we should check and create pipeline again if not created as we destroy
6836          * whole pipeline when stopping in streamming playback
6837          */
6838         if ( ! player->pipeline )
6839         {
6840                 if ( MM_ERROR_NONE != __gst_realize( player ) )
6841                 {
6842                         debug_error("failed to realize before starting. only in streamming\n");
6843                         return MM_ERROR_PLAYER_INTERNAL;
6844                 }
6845         }
6846
6847         debug_msg("app-src: pushing data\n");
6848
6849         if ( buf == NULL )
6850         {
6851                 debug_error("buf is null\n");
6852                 return MM_ERROR_NONE;
6853         }
6854
6855         buffer = gst_buffer_new ();
6856
6857         if (size <= 0)
6858         {
6859                 debug_log("call eos appsrc\n");
6860                 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
6861                 return MM_ERROR_NONE;
6862         }
6863
6864         //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));
6865
6866         debug_log("feed buffer %p, length %u\n", buf, size);
6867         g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
6868
6869         MMPLAYER_FLEAVE();
6870
6871         return ret;
6872 }
6873
6874 /* if retval is FALSE, it will be dropped for perfomance. */
6875 static gboolean
6876 __mmplayer_check_useful_message(mm_player_t *player, GstMessage * message)
6877 {
6878         gboolean retval = FALSE;
6879
6880         if ( !(player->pipeline && player->pipeline->mainbin) )
6881         {
6882                 debug_error("player pipeline handle is null");
6883                 return TRUE;
6884         }
6885
6886         switch (GST_MESSAGE_TYPE (message))
6887         {
6888                 case GST_MESSAGE_TAG:
6889                 case GST_MESSAGE_EOS:
6890                 case GST_MESSAGE_ERROR:
6891                 case GST_MESSAGE_WARNING:
6892                 case GST_MESSAGE_CLOCK_LOST:
6893                 case GST_MESSAGE_NEW_CLOCK:
6894                 case GST_MESSAGE_ELEMENT:
6895                 case GST_MESSAGE_DURATION_CHANGED:
6896                 case GST_MESSAGE_ASYNC_START:
6897                         retval = TRUE;
6898                         break;
6899                 case GST_MESSAGE_ASYNC_DONE:
6900                 case GST_MESSAGE_STATE_CHANGED:
6901                         /* we only handle messages from pipeline */
6902                         if(( message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst ) && (!player->gapless.reconfigure))
6903                                 retval = TRUE;
6904                         else
6905                                 retval = FALSE;
6906                         break;
6907                 case GST_MESSAGE_BUFFERING:
6908                 {
6909                         gint buffer_percent = 0;
6910
6911                         gst_message_parse_buffering (message, &buffer_percent);
6912
6913                         if ((MMPLAYER_IS_STREAMING(player)) &&
6914                                 (player->streamer) &&
6915                                 (player->streamer->is_buffering == TRUE) &&
6916                                 (buffer_percent == MAX_BUFFER_PERCENT))
6917                         {
6918                                 debug_log (">>> [%s] Buffering DONE is detected !!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
6919                                 player->streamer->is_buffering_done = TRUE;
6920                         }
6921
6922                         retval = TRUE;
6923                         break;
6924                 }
6925                 default:
6926                         retval = FALSE;
6927                         break;
6928         }
6929
6930         return retval;
6931 }
6932
6933 static GstBusSyncReply
6934 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
6935 {
6936         mm_player_t *player = (mm_player_t *)data;
6937         GstBusSyncReply reply = GST_BUS_DROP;
6938
6939         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
6940         {
6941                 debug_error("player pipeline handle is null");
6942                 return GST_BUS_PASS;
6943         }
6944
6945         if (!__mmplayer_check_useful_message(player, message))
6946         {
6947                 gst_message_unref (message);
6948                 return GST_BUS_DROP;
6949         }
6950
6951         switch (GST_MESSAGE_TYPE (message))
6952         {
6953                 case GST_MESSAGE_STATE_CHANGED:
6954                         /* post directly for fast launch */
6955                         if (player->sync_handler) {
6956                                 __mmplayer_gst_callback(NULL, message, player);
6957                                 reply = GST_BUS_DROP;
6958                         }
6959                         else {
6960                                 reply = GST_BUS_PASS;
6961                         }
6962                         break;
6963                 case GST_MESSAGE_TAG:
6964                         __mmplayer_gst_extract_tag_from_msg(player, message);
6965
6966                         #if 0 // debug
6967                         {
6968                                 GstTagList *tags = NULL;
6969
6970                                 gst_message_parse_tag (message, &tags);
6971                                 if (tags) {
6972                                         debug_error("TAGS received from element \"%s\".\n",
6973                                         GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
6974
6975                                         gst_tag_list_foreach (tags, print_tag, NULL);
6976                                         gst_tag_list_free (tags);
6977                                         tags = NULL;
6978                                 }
6979                                 break;
6980                         }
6981                         #endif
6982                         break;
6983
6984                 case GST_MESSAGE_DURATION_CHANGED:
6985                         __mmplayer_gst_handle_duration(player, message);
6986                         break;
6987                 case GST_MESSAGE_ASYNC_DONE:
6988                         /* NOTE:Don't call gst_callback directly
6989                          * because previous frame can be showed even though this message is received for seek.
6990                          */
6991                 default:
6992                         reply = GST_BUS_PASS;
6993                         break;
6994         }
6995
6996         if (reply == GST_BUS_DROP)
6997                 gst_message_unref (message);
6998
6999         return reply;
7000 }
7001
7002 static gboolean
7003 __mmplayer_gst_create_decoder ( mm_player_t *player,
7004                                                                 MMPlayerTrackType track,
7005                                                                 GstPad* srcpad,
7006                                                                 enum MainElementID elemId,
7007                                                                 const gchar* name)
7008 {
7009         gboolean ret = TRUE;
7010         GstPad *sinkpad = NULL;
7011
7012         MMPLAYER_FENTER();
7013
7014         return_val_if_fail( player &&
7015                                                 player->pipeline &&
7016                                                 player->pipeline->mainbin, FALSE);
7017         return_val_if_fail((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE);
7018         return_val_if_fail(srcpad, FALSE);
7019         return_val_if_fail((player->pipeline->mainbin[elemId].gst == NULL), FALSE);
7020
7021         GstElement *decodebin = NULL;
7022         GstCaps *dec_caps = NULL;
7023
7024         /* create decodebin */
7025         decodebin = gst_element_factory_make("decodebin", name);
7026
7027         if (!decodebin)
7028         {
7029                 debug_error("error : fail to create decodebin for %d decoder\n", track);
7030                 ret = FALSE;
7031                 goto ERROR;
7032         }
7033
7034         /* raw pad handling signal */
7035         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7036                                                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
7037
7038         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
7039         before looking for any elements that can handle that stream.*/
7040         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
7041                                                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
7042
7043         /* This signal is emitted when a element is added to the bin.*/
7044         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
7045                                                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
7046
7047         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), decodebin))
7048         {
7049                 debug_error("failed to add new decodebin\n");
7050                 ret = FALSE;
7051                 goto ERROR;
7052         }
7053
7054         dec_caps = gst_pad_query_caps (srcpad, NULL);
7055         if (dec_caps)
7056         {
7057                 //debug_log ("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
7058                 g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
7059                 gst_caps_unref(dec_caps);
7060         }
7061
7062         player->pipeline->mainbin[elemId].id = elemId;
7063         player->pipeline->mainbin[elemId].gst = decodebin;
7064
7065         sinkpad = gst_element_get_static_pad (decodebin, "sink");
7066
7067         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
7068         {
7069                 debug_warning ("failed to link [%s:%s] to decoder\n", GST_DEBUG_PAD_NAME(srcpad));
7070                 gst_object_unref (GST_OBJECT(decodebin));
7071         }
7072
7073         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (decodebin))
7074         {
7075                 debug_error("failed to sync second level decodebin state with parent\n");
7076         }
7077
7078         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
7079 // TO CHECK :   gst_pad_set_blocked_async (srcpad, FALSE, __mm_player_src_pad_block_cb, NULL);
7080
7081         debug_log("Total num of %d tracks = %d \n", track, player->selector[track].total_track_num);
7082
7083 ERROR:
7084         if (sinkpad)
7085         {
7086                 gst_object_unref ( GST_OBJECT(sinkpad) );
7087                 sinkpad = NULL;
7088         }
7089         MMPLAYER_FLEAVE();
7090
7091         return ret;
7092 }
7093
7094 /**
7095  * This function is to create  audio or video pipeline for playing.
7096  *
7097  * @param       player          [in]    handle of player
7098  *
7099  * @return      This function returns zero on success.
7100  * @remark
7101  * @see
7102  */
7103 static int
7104 __mmplayer_gst_create_pipeline(mm_player_t* player) // @
7105 {
7106         GstBus  *bus = NULL;
7107         MMPlayerGstElement *mainbin = NULL;
7108         MMHandleType attrs = 0;
7109         GstElement* element = NULL;
7110         GstElement* elem_src_audio = NULL;
7111         GstElement* elem_src_subtitle = NULL;
7112         GstElement* es_video_queue = NULL;
7113         GstElement* es_audio_queue = NULL;
7114         GstElement* es_subtitle_queue = NULL;
7115         GList* element_bucket = NULL;
7116         gboolean need_state_holder = TRUE;
7117         gint i = 0;
7118
7119         MMPLAYER_FENTER();
7120
7121         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7122
7123         /* get profile attribute */
7124         attrs = MMPLAYER_GET_ATTRS(player);
7125         if ( !attrs )
7126         {
7127                 debug_error("cannot get content attribute\n");
7128                 goto INIT_ERROR;
7129         }
7130
7131         /* create pipeline handles */
7132         if ( player->pipeline )
7133         {
7134                 debug_warning("pipeline should be released before create new one\n");
7135                 goto INIT_ERROR;
7136         }
7137
7138         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0( sizeof(MMPlayerGstPipelineInfo) );
7139         if (player->pipeline == NULL)
7140                 goto INIT_ERROR;
7141
7142         memset( player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo) );
7143
7144
7145         /* create mainbin */
7146         mainbin = (MMPlayerGstElement*) g_malloc0( sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM );
7147         if (mainbin == NULL)
7148                 goto INIT_ERROR;
7149
7150         memset( mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
7151
7152         /* create pipeline */
7153         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
7154         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
7155         if ( ! mainbin[MMPLAYER_M_PIPE].gst )
7156         {
7157                 debug_error("failed to create pipeline\n");
7158                 goto INIT_ERROR;
7159         }
7160         player->demux_pad_index = 0;
7161         player->subtitle_language_list = NULL;
7162
7163         player->is_subtitle_force_drop = FALSE;
7164         player->last_multiwin_status = FALSE;
7165
7166         _mmplayer_track_initialize(player);
7167
7168         /* create source element */
7169         switch ( player->profile.uri_type )
7170         {
7171                 /* rtsp streamming */
7172                 case MM_PLAYER_URI_TYPE_URL_RTSP:
7173                 {
7174                         gint network_bandwidth;
7175                         gchar *user_agent, *wap_profile;
7176
7177                         element = gst_element_factory_make(player->ini.name_of_rtspsrc, "streaming_source");
7178
7179                         if ( !element )
7180                         {
7181                                 debug_error("failed to create streaming source element\n");
7182                                 break;
7183                         }
7184
7185                         debug_log("using streamming source [%s].\n", player->ini.name_of_rtspsrc);
7186
7187                         /* make it zero */
7188                         network_bandwidth = 0;
7189                         user_agent = wap_profile = NULL;
7190
7191                         /* get attribute */
7192                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
7193                         mm_attrs_get_string_by_name ( attrs,"streaming_wap_profile", &wap_profile );
7194                         mm_attrs_get_int_by_name ( attrs, "streaming_network_bandwidth", &network_bandwidth );
7195
7196                         secure_debug_log("user_agent : %s\n", user_agent);
7197                         secure_debug_log("wap_profile : %s\n", wap_profile);
7198
7199                         /* setting property to streaming source */
7200                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7201                         if ( user_agent )
7202                                 g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
7203                         if ( wap_profile )
7204                                 g_object_set(G_OBJECT(element), "wap_profile", wap_profile, NULL);
7205
7206                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7207                                 G_CALLBACK (__mmplayer_gst_rtp_dynamic_pad), player );
7208                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
7209                                 G_CALLBACK (__mmplayer_gst_rtp_no_more_pads), player );
7210
7211                         player->use_decodebin = FALSE;
7212                 }
7213                 break;
7214 #if 0
7215                 /* WFD streamming */
7216                 case MM_PLAYER_URI_TYPE_URL_WFD:
7217                 {
7218                         element = gst_element_factory_make("wfdrtspsrc", "wfd_source");
7219                         if ( !element )
7220                         {
7221                                 debug_error("failed to create wfd streaming source element\n");
7222                                 break;
7223                         }
7224                         debug_log("using wfd streamming source wfdrtspsrc.\n");
7225                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7226                         g_object_set(G_OBJECT(element), "debug", TRUE, NULL);
7227                         g_object_set(G_OBJECT(element), "latency", 0, NULL);
7228                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7229                                G_CALLBACK (__mmplayer_gst_wfd_dynamic_pad), player );
7230
7231                         player->use_decodebin = FALSE;
7232                 }
7233                 break;
7234 #endif
7235                 /* http streaming*/
7236                 case MM_PLAYER_URI_TYPE_URL_HTTP:
7237                 {
7238                         gchar *user_agent, *proxy, *cookies, **cookie_list;
7239                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
7240                         user_agent = proxy = cookies = NULL;
7241                         cookie_list = NULL;
7242                         gint mode = MM_PLAYER_PD_MODE_NONE;
7243
7244                         mm_attrs_get_int_by_name ( attrs, "pd_mode", &mode );
7245
7246                         player->pd_mode = mode;
7247
7248                         debug_log("http playback, PD mode : %d\n", player->pd_mode);
7249
7250                         if ( ! MMPLAYER_IS_HTTP_PD(player) )
7251                         {
7252                                 element = gst_element_factory_make(player->ini.name_of_httpsrc, "http_streaming_source");
7253                                 if ( !element )
7254                                 {
7255                                         debug_error("failed to create http streaming source element[%s].\n", player->ini.name_of_httpsrc);
7256                                         break;
7257                                 }
7258                                 debug_log("using http streamming source [%s].\n", player->ini.name_of_httpsrc);
7259
7260                                 /* get attribute */
7261                                 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
7262                                 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
7263                                 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
7264                                 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
7265
7266                                 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
7267                                         (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
7268                                 {
7269                                         debug_log("get timeout from ini\n");
7270                                         http_timeout = player->ini.http_timeout;
7271                                 }
7272
7273                                 /* get attribute */
7274                                 secure_debug_log("location : %s\n", player->profile.uri);
7275                                 secure_debug_log("cookies : %s\n", cookies);
7276                                 secure_debug_log("proxy : %s\n", proxy);
7277                                 secure_debug_log("user_agent :  %s\n",  user_agent);
7278                                 debug_log("timeout : %d\n",  http_timeout);
7279
7280                                 /* setting property to streaming source */
7281                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7282                                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
7283                                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
7284
7285                                 /* check if prosy is vailid or not */
7286                                 if ( util_check_valid_url ( proxy ) )
7287                                         g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
7288                                 /* parsing cookies */
7289                                 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
7290                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
7291                                 if ( user_agent )
7292                                         g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
7293
7294                                 if ( MMPLAYER_URL_HAS_DASH_SUFFIX(player) )
7295                                 {
7296                                         debug_warning("it's dash. and it's still experimental feature.");
7297                                 }
7298                         }
7299                         else // progressive download
7300                         {
7301                                 gchar* location = NULL;
7302
7303                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
7304                                 {
7305                                         gchar *path = NULL;
7306
7307                                         mm_attrs_get_string_by_name ( attrs, "pd_location", &path );
7308
7309                                         MMPLAYER_FREEIF(player->pd_file_save_path);
7310
7311                                         debug_log("PD Location : %s\n", path);
7312
7313                                         if ( path )
7314                                         {
7315                                                 player->pd_file_save_path = g_strdup(path);
7316                                         }
7317                                         else
7318                                         {
7319                                                 debug_error("can't find pd location so, it should be set \n");
7320                                                 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
7321                                         }
7322                                 }
7323
7324                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
7325                                 if ( !element )
7326                                 {
7327                                         debug_error("failed to create PD push source element[%s].\n", "pdpushsrc");
7328                                         break;
7329                                 }
7330
7331                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
7332                                         g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
7333                                 else
7334                                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7335
7336                                 g_object_get(element, "location", &location, NULL);
7337                                 debug_log("PD_LOCATION [%s].\n", location);
7338                                 if (location)
7339                                         g_free (location);
7340                         }
7341                 }
7342                 break;
7343
7344                 /* file source */
7345                 case MM_PLAYER_URI_TYPE_FILE:
7346                 {
7347
7348                         debug_log("using filesrc for 'file://' handler.\n");
7349
7350                         element = gst_element_factory_make("filesrc", "source");
7351
7352                         if ( !element )
7353                         {
7354                                 debug_error("failed to create filesrc\n");
7355                                 break;
7356                         }
7357
7358                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
7359                         //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL);
7360                 }
7361                 break;
7362
7363                 case MM_PLAYER_URI_TYPE_SS:
7364                 {
7365                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
7366                         element = gst_element_factory_make("souphttpsrc", "http streaming source");
7367                         if ( !element )
7368                         {
7369                                 debug_error("failed to create http streaming source element[%s]", player->ini.name_of_httpsrc);
7370                                 break;
7371                         }
7372
7373                         mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
7374
7375                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
7376                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
7377                         {
7378                                 debug_log("get timeout from ini\n");
7379                                 http_timeout = player->ini.http_timeout;
7380                         }
7381
7382                         /* setting property to streaming source */
7383                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7384                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
7385                 }
7386                 break;
7387
7388                 /* appsrc */
7389                 case MM_PLAYER_URI_TYPE_BUFF:
7390                 {
7391                         guint64 stream_type = GST_APP_STREAM_TYPE_STREAM;
7392
7393                         debug_log("mem src is selected\n");
7394
7395                         element = gst_element_factory_make("appsrc", "buff-source");
7396                         if ( !element )
7397                         {
7398                                 debug_error("failed to create appsrc element\n");
7399                                 break;
7400                         }
7401
7402                         g_object_set( element, "stream-type", stream_type, NULL );
7403                         //g_object_set( element, "size", player->mem_buf.len, NULL );
7404                         //g_object_set( element, "blocksize", (guint64)20480, NULL );
7405
7406                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7407                                 G_CALLBACK(__gst_appsrc_seek_data), player);
7408                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7409                                 G_CALLBACK(__gst_appsrc_feed_data), player);
7410                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7411                                 G_CALLBACK(__gst_appsrc_enough_data), player);
7412                 }
7413                 break;
7414                 case MM_PLAYER_URI_TYPE_ES_BUFF:
7415                 {
7416                         debug_log("es buff src is selected\n");
7417
7418                         if (player->v_stream_caps)
7419                         {
7420                                 element = gst_element_factory_make("appsrc", "video_appsrc");
7421                                 if ( !element )
7422                                 {
7423                                         debug_critical("failed to create video app source element[appsrc].\n" );
7424                                         break;
7425                                 }
7426
7427                                 if ( player->a_stream_caps )
7428                                 {
7429                                         elem_src_audio = gst_element_factory_make("appsrc", "audio_appsrc");
7430                                         if ( !elem_src_audio )
7431                                         {
7432                                                 debug_critical("failed to create audio app source element[appsrc].\n" );
7433                                                 break;
7434                                         }
7435                                 }
7436                         }
7437                         else if ( player->a_stream_caps )
7438                         {
7439                                 /* no video, only audio pipeline*/
7440                                 element = gst_element_factory_make("appsrc", "audio_appsrc");
7441                                 if ( !element )
7442                                 {
7443                                         debug_critical("failed to create audio app source element[appsrc].\n" );
7444                                         break;
7445                                 }
7446                         }
7447
7448                         if ( player->s_stream_caps )
7449                         {
7450                                 elem_src_subtitle = gst_element_factory_make("appsrc", "subtitle_appsrc");
7451                                 if ( !elem_src_subtitle )
7452                                 {
7453                                         debug_critical("failed to create subtitle app source element[appsrc].\n" );
7454                                         break;
7455                                 }
7456                         }
7457
7458                         debug_log("setting app sources properties.\n");
7459                         debug_log("location : %s\n", player->profile.uri);
7460
7461                         if ( player->v_stream_caps && element )
7462                         {
7463                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
7464                                                                                             "blocksize", (guint)1048576,        /* size of many video frames are larger than default blocksize as 4096 */
7465                                                                                                 "caps", player->v_stream_caps, NULL);
7466
7467                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
7468                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
7469                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
7470                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
7471
7472                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
7473                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
7474                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7475                                                                                                                 G_CALLBACK(__gst_seek_video_data), player);
7476
7477                                 if (player->a_stream_caps && elem_src_audio)
7478                                 {
7479                                         g_object_set(G_OBJECT(elem_src_audio), "format", GST_FORMAT_TIME,
7480                                                                                                                         "caps", player->a_stream_caps, NULL);
7481
7482                                         if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7483                                                 g_object_set(G_OBJECT(elem_src_audio), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7484                                         if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7485                                                 g_object_set(G_OBJECT(elem_src_audio), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7486
7487                                         /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
7488                                         gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_audio), GST_APP_STREAM_TYPE_SEEKABLE);
7489                                         MMPLAYER_SIGNAL_CONNECT( player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7490                                                                                                                 G_CALLBACK(__gst_seek_audio_data), player);
7491                                 }
7492                         }
7493                         else if (player->a_stream_caps && element)
7494                         {
7495                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
7496                                                                                                 "caps", player->a_stream_caps, NULL);
7497
7498                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7499                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7500                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7501                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7502
7503                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
7504                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
7505                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7506                                                                                                                         G_CALLBACK(__gst_seek_audio_data), player);
7507                         }
7508
7509                         if (player->s_stream_caps && elem_src_subtitle)
7510                         {
7511                                 g_object_set(G_OBJECT(elem_src_subtitle), "format", GST_FORMAT_TIME,
7512                                                                                                                  "caps", player->s_stream_caps, NULL);
7513
7514                                 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
7515                                         g_object_set(G_OBJECT(elem_src_subtitle), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
7516                                 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
7517                                         g_object_set(G_OBJECT(elem_src_subtitle), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
7518
7519                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_subtitle), GST_APP_STREAM_TYPE_SEEKABLE);
7520
7521                                 MMPLAYER_SIGNAL_CONNECT( player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7522                                                                                                                                 G_CALLBACK(__gst_seek_subtitle_data), player);
7523                         }
7524
7525                         if (!player->es_player_push_mode)
7526                         {
7527                                 if (player->v_stream_caps && element)
7528                                 {
7529                                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7530                                                                                                                         G_CALLBACK(__gst_appsrc_feed_video_data), player);
7531                                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7532                                                                                                                         G_CALLBACK(__gst_appsrc_enough_video_data), player);
7533
7534                                         if (player->a_stream_caps && elem_src_audio)
7535                                         {
7536                                                 MMPLAYER_SIGNAL_CONNECT( player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7537                                                                                                                         G_CALLBACK(__gst_appsrc_feed_audio_data), player);
7538                                                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7539                                                                                                                         G_CALLBACK(__gst_appsrc_enough_audio_data), player);
7540                                         }
7541                                 }
7542                                 else if (player->a_stream_caps && element)
7543                                 {
7544                                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7545                                                                                                                         G_CALLBACK(__gst_appsrc_feed_audio_data), player);
7546                                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7547                                                                                                                         G_CALLBACK(__gst_appsrc_enough_audio_data), player);
7548                                 }
7549
7550                                 if (player->s_stream_caps && elem_src_subtitle)
7551                                 {
7552                                         MMPLAYER_SIGNAL_CONNECT( player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7553                                                                                                                         G_CALLBACK(__gst_appsrc_feed_subtitle_data), player);
7554                                 }
7555                         }
7556
7557                         need_state_holder = FALSE;
7558                 }
7559                 break;
7560                 /* appsrc */
7561                 case MM_PLAYER_URI_TYPE_MEM:
7562                 {
7563                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
7564
7565                         debug_log("mem src is selected\n");
7566
7567                         element = gst_element_factory_make("appsrc", "mem-source");
7568                         if ( !element )
7569                         {
7570                                 debug_error("failed to create appsrc element\n");
7571                                 break;
7572                         }
7573
7574                         g_object_set( element, "stream-type", stream_type, NULL );
7575                         g_object_set( element, "size", player->mem_buf.len, NULL );
7576                         g_object_set( element, "blocksize", (guint64)20480, NULL );
7577
7578                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7579                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->mem_buf );
7580                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7581                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->mem_buf );
7582                 }
7583                 break;
7584                 case MM_PLAYER_URI_TYPE_URL:
7585                 break;
7586
7587                 case MM_PLAYER_URI_TYPE_TEMP:
7588                 break;
7589
7590                 case MM_PLAYER_URI_TYPE_NONE:
7591                 default:
7592                 break;
7593         }
7594
7595         /* check source element is OK */
7596         if ( ! element )
7597         {
7598                 debug_error("no source element was created.\n");
7599                 goto INIT_ERROR;
7600         }
7601
7602         /* take source element */
7603         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
7604         mainbin[MMPLAYER_M_SRC].gst = element;
7605         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
7606
7607         if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL))
7608         {
7609                 player->streamer = __mm_player_streaming_create();
7610                 __mm_player_streaming_initialize(player->streamer);
7611         }
7612
7613         if ( MMPLAYER_IS_HTTP_PD(player) )
7614         {
7615                 gdouble pre_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
7616
7617                 debug_log ("Picked queue2 element(pre buffer : %d sec)....\n", pre_buffering_time);
7618                 element = gst_element_factory_make("queue2", "queue2");
7619                 if ( !element )
7620                 {
7621                         debug_error ( "failed to create http streaming buffer element\n" );
7622                         goto INIT_ERROR;
7623                 }
7624
7625                 /* take it */
7626                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
7627                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
7628                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
7629
7630                 pre_buffering_time = (pre_buffering_time > 0)?(pre_buffering_time):(player->ini.http_buffering_time);
7631
7632                 __mm_player_streaming_set_queue2(player->streamer,
7633                                 element,
7634                                 TRUE,
7635                                 player->ini.http_max_size_bytes,
7636                                 pre_buffering_time,
7637                                 1.0,
7638                                 player->ini.http_buffering_limit,
7639                                 FALSE,
7640                                 NULL,
7641                                 0);
7642         }
7643         if (MMPLAYER_IS_ES_BUFF_SRC(player))
7644         {
7645                 if (player->v_stream_caps)
7646                 {
7647                         es_video_queue = gst_element_factory_make("queue2", "video_queue");
7648                         if (!es_video_queue)
7649                         {
7650                                 debug_error ("create es_video_queue for es player failed\n");
7651                                 goto INIT_ERROR;
7652                         }
7653                         mainbin[MMPLAYER_M_V_BUFFER].id = MMPLAYER_M_V_BUFFER;
7654                         mainbin[MMPLAYER_M_V_BUFFER].gst = es_video_queue;
7655                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_V_BUFFER]);
7656
7657                         /* Adding audio appsrc to bucket */
7658                         if (player->a_stream_caps && elem_src_audio)
7659                         {
7660                                 mainbin[MMPLAYER_M_2ND_SRC].id = MMPLAYER_M_2ND_SRC;
7661                                 mainbin[MMPLAYER_M_2ND_SRC].gst = elem_src_audio;
7662                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_2ND_SRC]);
7663
7664                                 es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
7665                                 if (!es_audio_queue)
7666                                 {
7667                                         debug_error ("create es_audio_queue for es player failed\n");
7668                                         goto INIT_ERROR;
7669                                 }
7670                                 mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
7671                                 mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
7672                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
7673                         }
7674                 }
7675                 /* Only audio stream, no video */
7676                 else if (player->a_stream_caps)
7677                 {
7678                         es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
7679                         if (!es_audio_queue)
7680                         {
7681                                 debug_error ("create es_audio_queue for es player failed\n");
7682                                 goto INIT_ERROR;
7683                         }
7684                         mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
7685                         mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
7686                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
7687                 }
7688
7689                 if (player->s_stream_caps && elem_src_subtitle)
7690                 {
7691                         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
7692                         mainbin[MMPLAYER_M_SUBSRC].gst = elem_src_subtitle;
7693                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SUBSRC]);
7694
7695                         es_subtitle_queue = gst_element_factory_make("queue2", "subtitle_queue");
7696                         if (!es_subtitle_queue)
7697                         {
7698                                 debug_error ("create es_subtitle_queue for es player failed\n");
7699                                 goto INIT_ERROR;
7700                         }
7701                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_V_BUFFER;
7702                         mainbin[MMPLAYER_M_S_BUFFER].gst = es_subtitle_queue;
7703                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
7704                 }
7705         }
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                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_ES_BUFF))
7711         {
7712                 element = NULL;
7713                 enum MainElementID elemId = MMPLAYER_M_NUM;
7714
7715                 if ((player->use_decodebin) &&
7716                         ((MMPLAYER_IS_HTTP_PD(player)) ||
7717                          (!MMPLAYER_IS_HTTP_STREAMING(player))))
7718                 {
7719                         elemId = MMPLAYER_M_AUTOPLUG;
7720                         element = __mmplayer_create_decodebin(player);
7721                         need_state_holder = FALSE;
7722                 }
7723                 else
7724                 {
7725                         elemId = MMPLAYER_M_TYPEFIND;
7726                         element = gst_element_factory_make("typefind", "typefinder");
7727                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
7728                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
7729                 }
7730
7731
7732                 /* check autoplug element is OK */
7733                 if ( ! element )
7734                 {
7735                         debug_error("can not create element (%d)\n", elemId);
7736                         goto INIT_ERROR;
7737                 }
7738
7739                 mainbin[elemId].id = elemId;
7740                 mainbin[elemId].gst = element;
7741
7742                 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
7743         }
7744
7745         /* add elements to pipeline */
7746         if( !__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket))
7747         {
7748                 debug_error("Failed to add elements to pipeline\n");
7749                 goto INIT_ERROR;
7750         }
7751
7752
7753         /* linking elements in the bucket by added order. */
7754         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
7755         {
7756                 debug_error("Failed to link some elements\n");
7757                 goto INIT_ERROR;
7758         }
7759
7760
7761         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
7762         if ( need_state_holder )
7763         {
7764                 /* create */
7765                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
7766                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make ("fakesink", "state-holder");
7767
7768                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
7769                 {
7770                         debug_error ("fakesink element could not be created\n");
7771                         goto INIT_ERROR;
7772                 }
7773                 GST_OBJECT_FLAG_UNSET (mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
7774
7775                 /* take ownership of fakesink. we are reusing it */
7776                 gst_object_ref( mainbin[MMPLAYER_M_SRC_FAKESINK].gst );
7777
7778                 /* add */
7779                 if ( FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
7780                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst) )
7781                 {
7782                         debug_error("failed to add fakesink to bin\n");
7783                         goto INIT_ERROR;
7784                 }
7785         }
7786
7787         /* now we have completed mainbin. take it */
7788         player->pipeline->mainbin = mainbin;
7789
7790         if (MMPLAYER_IS_ES_BUFF_SRC(player))
7791         {
7792                 GstPad *srcpad = NULL;
7793
7794                 if (mainbin[MMPLAYER_M_V_BUFFER].gst)
7795                 {
7796                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_V_BUFFER].gst, "src");
7797                         if (srcpad)
7798                         {
7799                                 __mmplayer_gst_create_decoder ( player,
7800                                                                                                 MM_PLAYER_TRACK_TYPE_VIDEO,
7801                                                                                                 srcpad,
7802                                                                                                 MMPLAYER_M_AUTOPLUG_V_DEC,
7803                                                                                                 "video_decodebin");
7804
7805                                 gst_object_unref ( GST_OBJECT(srcpad) );
7806                                 srcpad = NULL;
7807                         }
7808                 }
7809
7810                 if ((player->a_stream_caps) && (mainbin[MMPLAYER_M_A_BUFFER].gst))
7811                 {
7812                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_BUFFER].gst, "src");
7813                         if (srcpad)
7814                         {
7815                                 __mmplayer_gst_create_decoder ( player,
7816                                                                                                 MM_PLAYER_TRACK_TYPE_AUDIO,
7817                                                                                                 srcpad,
7818                                                                                                 MMPLAYER_M_AUTOPLUG_A_DEC,
7819                                                                                                 "audio_decodebin");
7820
7821                                 gst_object_unref ( GST_OBJECT(srcpad) );
7822                                 srcpad = NULL;
7823                         } // else error
7824                 } //  else error
7825
7826                 if (mainbin[MMPLAYER_M_S_BUFFER].gst)
7827                 {
7828                         __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
7829                 }
7830         }
7831
7832         /* connect bus callback */
7833         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
7834         if ( !bus )
7835         {
7836                 debug_error ("cannot get bus from pipeline.\n");
7837                 goto INIT_ERROR;
7838         }
7839
7840         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
7841
7842         player->context.thread_default = g_main_context_get_thread_default();
7843
7844         if (NULL == player->context.thread_default)
7845         {
7846                 player->context.thread_default = g_main_context_default();
7847                 debug_log("thread-default context is the global default context");
7848         }
7849         debug_warning("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
7850
7851         /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
7852         if ( __mmplayer_check_subtitle ( player ) )
7853         {
7854                 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
7855                         debug_error("fail to create subtitle src\n");
7856         }
7857
7858         /* set sync handler to get tag synchronously */
7859         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL);
7860
7861         /* finished */
7862         gst_object_unref(GST_OBJECT(bus));
7863         g_list_free(element_bucket);
7864
7865         MMPLAYER_FLEAVE();
7866
7867         return MM_ERROR_NONE;
7868
7869 INIT_ERROR:
7870
7871         __mmplayer_gst_destroy_pipeline(player);
7872         g_list_free(element_bucket);
7873
7874         /* release element which are not added to bin */
7875         for ( i = 1; i < MMPLAYER_M_NUM; i++ )  /* NOTE : skip pipeline */
7876         {
7877                 if ( mainbin[i].gst )
7878                 {
7879                         GstObject* parent = NULL;
7880                         parent = gst_element_get_parent( mainbin[i].gst );
7881
7882                         if ( !parent )
7883                         {
7884                                 gst_object_unref(GST_OBJECT(mainbin[i].gst));
7885                                 mainbin[i].gst = NULL;
7886                         }
7887                         else
7888                         {
7889                                 gst_object_unref(GST_OBJECT(parent));
7890                         }
7891                 }
7892         }
7893
7894         /* release pipeline with it's childs */
7895         if ( mainbin[MMPLAYER_M_PIPE].gst )
7896         {
7897                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7898         }
7899
7900         MMPLAYER_FREEIF( player->pipeline );
7901         MMPLAYER_FREEIF( mainbin );
7902
7903         return MM_ERROR_PLAYER_INTERNAL;
7904 }
7905
7906 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
7907 {
7908         GSource *source = NULL;
7909
7910         MMPLAYER_FENTER();
7911
7912         source = g_main_context_find_source_by_id (context, source_id);
7913
7914         if (source != NULL)
7915         {
7916                 debug_warning("context: %p, source id: %d, source: %p", context, source_id, source);
7917                 g_source_destroy(source);
7918         }
7919
7920         MMPLAYER_FLEAVE();
7921 }
7922
7923 static void
7924 __mmplayer_reset_gapless_state(mm_player_t* player)
7925 {
7926         MMPLAYER_FENTER();
7927         return_if_fail(player
7928                 && player->pipeline
7929                 && player->pipeline->audiobin
7930                 && player->pipeline->audiobin[MMPLAYER_A_BIN].gst);
7931
7932         if (player->gapless.audio_data_probe_id != 0)
7933         {
7934                 GstPad *sinkpad;
7935                 sinkpad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_BIN].gst, "sink");
7936                 gst_pad_remove_probe (sinkpad, player->gapless.audio_data_probe_id);
7937                 gst_object_unref (sinkpad);
7938         }
7939         memset(&player->gapless, 0, sizeof(mm_player_gapless_t));
7940
7941         MMPLAYER_FLEAVE();
7942         return;
7943 }
7944
7945 static int
7946 __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
7947 {
7948         gint timeout = 0;
7949         int ret = MM_ERROR_NONE;
7950
7951         MMPLAYER_FENTER();
7952
7953         return_val_if_fail ( player, MM_ERROR_INVALID_HANDLE );
7954
7955         /* cleanup stuffs */
7956         MMPLAYER_FREEIF(player->type);
7957         player->have_dynamic_pad = FALSE;
7958         player->no_more_pad = FALSE;
7959         player->num_dynamic_pad = 0;
7960         player->demux_pad_index = 0;
7961         player->subtitle_language_list = NULL;
7962         player->use_deinterleave = FALSE;
7963         player->max_audio_channels = 0;
7964         player->video_share_api_delta = 0;
7965         player->video_share_clock_delta = 0;
7966         player->video_hub_download_mode = 0;
7967         __mmplayer_reset_gapless_state(player);
7968         __mmplayer_post_proc_reset(player);
7969
7970         if (player->streamer)
7971         {
7972                 __mm_player_streaming_deinitialize (player->streamer);
7973                 __mm_player_streaming_destroy(player->streamer);
7974                 player->streamer = NULL;
7975         }
7976
7977         /* cleanup unlinked mime type */
7978         MMPLAYER_FREEIF(player->unlinked_audio_mime);
7979         MMPLAYER_FREEIF(player->unlinked_video_mime);
7980         MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
7981
7982         /* cleanup running stuffs */
7983         __mmplayer_cancel_eos_timer( player );
7984
7985         /* remove sound cb */
7986         if ( MM_ERROR_NONE != mm_sound_remove_device_information_changed_callback())
7987         {
7988                 debug_error("failed to mm_sound_remove_device_information_changed_callback()");
7989         }
7990
7991         /* cleanup gst stuffs */
7992         if ( player->pipeline )
7993         {
7994                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
7995                 GstTagList* tag_list = player->pipeline->tag_list;
7996
7997                 /* first we need to disconnect all signal hander */
7998                 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_ALL );
7999
8000                 /* disconnecting bus watch */
8001                 if ( player->bus_watcher )
8002                         __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
8003                 player->bus_watcher = 0;
8004
8005                 if ( mainbin )
8006                 {
8007                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
8008                         MMPlayerGstElement* videobin = player->pipeline->videobin;
8009                         MMPlayerGstElement* textbin = player->pipeline->textbin;
8010                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mainbin[MMPLAYER_M_PIPE].gst));
8011                         gst_bus_set_sync_handler (bus, NULL, NULL, NULL);
8012                         gst_object_unref(bus);
8013
8014                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8015                         ret = __mmplayer_gst_set_state ( player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout );
8016                         if ( ret != MM_ERROR_NONE )
8017                         {
8018                                 debug_error("fail to change state to NULL\n");
8019                                 return MM_ERROR_PLAYER_INTERNAL;
8020                         }
8021
8022                         debug_warning("succeeded in chaning state to NULL\n");
8023
8024                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
8025
8026                         /* free fakesink */
8027                         if ( mainbin[MMPLAYER_M_SRC_FAKESINK].gst )
8028                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
8029
8030                         /* free avsysaudiosink
8031                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
8032                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
8033                         */
8034                         MMPLAYER_FREEIF( audiobin );
8035                         MMPLAYER_FREEIF( videobin );
8036                         MMPLAYER_FREEIF( textbin );
8037                         MMPLAYER_FREEIF( mainbin );
8038                 }
8039
8040                 if ( tag_list )
8041                         gst_tag_list_free(tag_list);
8042
8043                 MMPLAYER_FREEIF( player->pipeline );
8044         }
8045         MMPLAYER_FREEIF(player->album_art);
8046
8047         if (player->v_stream_caps)
8048         {
8049                 gst_caps_unref(player->v_stream_caps);
8050                 player->v_stream_caps = NULL;
8051         }
8052         if (player->a_stream_caps)
8053         {
8054                 gst_caps_unref(player->a_stream_caps);
8055                 player->a_stream_caps = NULL;
8056         }
8057         if (player->s_stream_caps)
8058         {
8059                 gst_caps_unref(player->s_stream_caps);
8060                 player->s_stream_caps = NULL;
8061         }
8062         _mmplayer_track_destroy(player);
8063
8064         if ( player->sink_elements )
8065                 g_list_free ( player->sink_elements );
8066         player->sink_elements = NULL;
8067
8068         debug_warning("finished destroy pipeline\n");
8069
8070         MMPLAYER_FLEAVE();
8071
8072         return ret;
8073 }
8074
8075 static int __gst_realize(mm_player_t* player) // @
8076 {
8077         gint timeout = 0;
8078         int ret = MM_ERROR_NONE;
8079
8080         MMPLAYER_FENTER();
8081
8082         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8083
8084         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
8085
8086         ret = __mmplayer_gst_create_pipeline(player);
8087         if ( ret )
8088         {
8089                 debug_error("failed to create pipeline\n");
8090                 return ret;
8091         }
8092
8093         /* set pipeline state to READY */
8094         /* NOTE : state change to READY must be performed sync. */
8095         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8096         ret = __mmplayer_gst_set_state(player,
8097                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
8098
8099         if ( ret != MM_ERROR_NONE )
8100         {
8101                 /* return error if failed to set state */
8102                 debug_error("failed to set READY state");
8103                 return ret;
8104         }
8105         else
8106         {
8107                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
8108         }
8109
8110         /* create dot before error-return. for debugging */
8111         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-realize" );
8112
8113         MMPLAYER_FLEAVE();
8114
8115         return ret;
8116 }
8117
8118 static int __gst_unrealize(mm_player_t* player) // @
8119 {
8120         int ret = MM_ERROR_NONE;
8121
8122         MMPLAYER_FENTER();
8123
8124         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8125
8126         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
8127         MMPLAYER_PRINT_STATE(player);
8128
8129         /* release miscellaneous information */
8130         __mmplayer_release_misc( player );
8131
8132         /* destroy pipeline */
8133         ret = __mmplayer_gst_destroy_pipeline( player );
8134         if ( ret != MM_ERROR_NONE )
8135         {
8136                 debug_error("failed to destory pipeline\n");
8137                 return ret;
8138         }
8139
8140         /* release miscellaneous information.
8141            these info needs to be released after pipeline is destroyed. */
8142         __mmplayer_release_misc_post( player );
8143
8144         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
8145
8146         MMPLAYER_FLEAVE();
8147
8148         return ret;
8149 }
8150
8151 static int __gst_pending_seek ( mm_player_t* player )
8152 {
8153         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
8154         int ret = MM_ERROR_NONE;
8155
8156         MMPLAYER_FENTER();
8157
8158         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8159
8160         if ( !player->pending_seek.is_pending )
8161         {
8162                 debug_log("pending seek is not reserved. nothing to do.\n" );
8163                 return ret;
8164         }
8165
8166         /* check player state if player could pending seek or not. */
8167         current_state = MMPLAYER_CURRENT_STATE(player);
8168
8169         if ( current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING  )
8170         {
8171                 debug_warning("try to pending seek in %s state, try next time. \n",
8172                         MMPLAYER_STATE_GET_NAME(current_state));
8173                 return ret;
8174         }
8175
8176         debug_log("trying to play from (%lu) pending position\n", player->pending_seek.pos);
8177
8178         ret = __gst_set_position ( player, player->pending_seek.format, player->pending_seek.pos, FALSE );
8179
8180         if ( MM_ERROR_NONE != ret )
8181                 debug_error("failed to seek pending postion. just keep staying current position.\n");
8182
8183         player->pending_seek.is_pending = FALSE;
8184
8185         MMPLAYER_FLEAVE();
8186
8187         return ret;
8188 }
8189
8190 static int __gst_start(mm_player_t* player) // @
8191 {
8192         gboolean sound_extraction = 0;
8193         int ret = MM_ERROR_NONE;
8194         gboolean async = FALSE;
8195
8196         MMPLAYER_FENTER();
8197
8198         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8199
8200         /* get sound_extraction property */
8201         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
8202
8203         /* NOTE : if SetPosition was called before Start. do it now */
8204         /* streaming doesn't support it. so it should be always sync */
8205         /* !! create one more api to check if there is pending seek rather than checking variables */
8206         if ( (player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player))
8207         {
8208                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
8209                 ret = __gst_pause(player, FALSE);
8210                 if ( ret != MM_ERROR_NONE )
8211                 {
8212                         debug_error("failed to set state to PAUSED for pending seek\n");
8213                         return ret;
8214                 }
8215
8216                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
8217
8218                 if ( sound_extraction )
8219                 {
8220                         debug_log("setting pcm extraction\n");
8221
8222                         ret = __mmplayer_set_pcm_extraction(player);
8223                         if ( MM_ERROR_NONE != ret )
8224                         {
8225                                 debug_warning("failed to set pcm extraction\n");
8226                                 return ret;
8227                         }
8228                 }
8229                 else
8230                 {
8231                         if ( MM_ERROR_NONE != __gst_pending_seek(player) )
8232                         {
8233                                 debug_warning("failed to seek pending postion. starting from the begin of content.\n");
8234                         }
8235                 }
8236         }
8237
8238         debug_log("current state before doing transition");
8239         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
8240         MMPLAYER_PRINT_STATE(player);
8241
8242         /* set pipeline state to PLAYING  */
8243         if (player->es_player_push_mode)
8244         {
8245                 async = TRUE;
8246         }
8247         /* set pipeline state to PLAYING  */
8248         ret = __mmplayer_gst_set_state(player,
8249                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
8250
8251         if (ret == MM_ERROR_NONE)
8252         {
8253                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
8254         }
8255         else
8256         {
8257                 debug_error("failed to set state to PLAYING");
8258                 return ret;
8259         }
8260
8261         /* generating debug info before returning error */
8262         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-start" );
8263
8264         MMPLAYER_FLEAVE();
8265
8266         return ret;
8267 }
8268
8269 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
8270 {
8271         MMPLAYER_FENTER();
8272
8273         return_if_fail(player
8274                 && player->pipeline
8275                 && player->pipeline->audiobin
8276                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
8277
8278         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
8279
8280         usleep(time);
8281
8282         MMPLAYER_FLEAVE();
8283 }
8284
8285 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
8286 {
8287         MMPLAYER_FENTER();
8288
8289         return_if_fail(player
8290                 && player->pipeline
8291                 && player->pipeline->audiobin
8292                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
8293
8294         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
8295
8296         MMPLAYER_FLEAVE();
8297 }
8298
8299 static int __gst_stop(mm_player_t* player) // @
8300 {
8301         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
8302         MMHandleType attrs = 0;
8303         gboolean fadedown = FALSE;
8304         gboolean rewind = FALSE;
8305         gint timeout = 0;
8306         int ret = MM_ERROR_NONE;
8307         GstState state;
8308         gboolean async = FALSE;
8309
8310         MMPLAYER_FENTER();
8311
8312         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
8313         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
8314
8315         debug_log("current state before doing transition");
8316         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
8317         MMPLAYER_PRINT_STATE(player);
8318
8319         attrs = MMPLAYER_GET_ATTRS(player);
8320         if ( !attrs )
8321         {
8322                 debug_error("cannot get content attribute\n");
8323                 return MM_ERROR_PLAYER_INTERNAL;
8324         }
8325
8326         mm_attrs_get_int_by_name(attrs, "sound_fadedown", &fadedown);
8327
8328         /* enable fadedown */
8329         if (fadedown || player->sm.by_asm_cb)
8330                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8331
8332         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
8333         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
8334
8335         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_BUFF ||
8336                 player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS)
8337         {
8338                 state = GST_STATE_READY;
8339         }
8340         else
8341         {
8342                 state = GST_STATE_PAUSED;
8343
8344                 if ( ! MMPLAYER_IS_STREAMING(player) ||
8345                         (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked)) {
8346                         rewind = TRUE;
8347                 }
8348         }
8349
8350         if (player->es_player_push_mode)
8351         {
8352                 async = TRUE;
8353         }
8354         /* set gst state */
8355         ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, async, timeout );
8356
8357         /* disable fadeout */
8358         if (fadedown || player->sm.by_asm_cb)
8359                 __mmplayer_undo_sound_fadedown(player);
8360
8361         /* return if set_state has failed */
8362         if ( ret != MM_ERROR_NONE )
8363         {
8364                 debug_error("failed to set state.\n");
8365                 return ret;
8366         }
8367
8368         /* rewind */
8369         if ( rewind )
8370         {
8371                 if ( ! __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8372                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
8373                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE) )
8374                 {
8375                         debug_warning("failed to rewind\n");
8376                         ret = MM_ERROR_PLAYER_SEEK;
8377                 }
8378         }
8379
8380         /* initialize */
8381         player->sent_bos = FALSE;
8382
8383         if (player->es_player_push_mode) //for cloudgame
8384         {
8385                 timeout = 0;
8386         }
8387
8388         /* wait for seek to complete */
8389         change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
8390         if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL )
8391         {
8392                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
8393         }
8394         else
8395         {
8396                 debug_error("fail to stop player.\n");
8397                 ret = MM_ERROR_PLAYER_INTERNAL;
8398                 __mmplayer_dump_pipeline_state(player);
8399         }
8400
8401         /* generate dot file if enabled */
8402         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-stop" );
8403
8404         MMPLAYER_FLEAVE();
8405
8406         return ret;
8407 }
8408
8409 int __gst_pause(mm_player_t* player, gboolean async) // @
8410 {
8411         int ret = MM_ERROR_NONE;
8412
8413         MMPLAYER_FENTER();
8414
8415         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
8416         return_val_if_fail(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
8417
8418         debug_log("current state before doing transition");
8419         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
8420         MMPLAYER_PRINT_STATE(player);
8421
8422         /* set pipeline status to PAUSED */
8423         player->ignore_asyncdone = TRUE;
8424
8425         ret = __mmplayer_gst_set_state(player,
8426                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
8427
8428         player->ignore_asyncdone = FALSE;
8429
8430         if ( FALSE == async )
8431         {
8432                 if ( ret != MM_ERROR_NONE )
8433                 {
8434                         GstMessage *msg = NULL;
8435                         GTimer *timer = NULL;
8436                         gdouble MAX_TIMEOUT_SEC = 3;
8437
8438                         debug_error("failed to set state to PAUSED");
8439
8440                         timer = g_timer_new();
8441                         g_timer_start(timer);
8442
8443                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
8444                         gboolean got_msg = FALSE;
8445                         /* check if gst error posted or not */
8446                         do
8447                         {
8448                                 msg = gst_bus_timed_pop(bus, GST_SECOND /2);
8449                                 if (msg)
8450                                 {
8451                                         if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR)
8452                                         {
8453                                                 GError *error = NULL;
8454
8455                                                 /* parse error code */
8456                                                 gst_message_parse_error(msg, &error, NULL);
8457
8458                                                 if ( gst_structure_has_name ( gst_message_get_structure(msg), "streaming_error" ) )
8459                                                 {
8460                                                         /* Note : the streaming error from the streaming source is handled
8461                                                          *   using __mmplayer_handle_streaming_error.
8462                                                          */
8463                                                         __mmplayer_handle_streaming_error ( player, msg );
8464
8465                                                 }
8466                                                 else if (error)
8467                                                 {
8468                                                         debug_error("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
8469
8470                                                         if (error->domain == GST_STREAM_ERROR)
8471                                                         {
8472                                                                 ret = __gst_handle_stream_error( player, error, msg );
8473                                                         }
8474                                                         else if (error->domain == GST_RESOURCE_ERROR)
8475                                                         {
8476                                                                 ret = __gst_handle_resource_error( player, error->code );
8477                                                         }
8478                                                         else if (error->domain == GST_LIBRARY_ERROR)
8479                                                         {
8480                                                                 ret = __gst_handle_library_error( player, error->code );
8481                                                         }
8482                                                         else if (error->domain == GST_CORE_ERROR)
8483                                                         {
8484                                                                 ret = __gst_handle_core_error( player, error->code );
8485                                                         }
8486                                                 }
8487
8488                                                 got_msg = TRUE;
8489                                                 player->msg_posted = TRUE;
8490                                         }
8491                                         gst_message_unref(msg);
8492                                 }
8493                         } while (!got_msg && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
8494                         /* clean */
8495                         gst_object_unref(bus);
8496                         g_timer_stop (timer);
8497                         g_timer_destroy (timer);
8498
8499                         return ret;
8500                 }
8501                 else if ( (!player->pipeline->videobin) && (!player->pipeline->audiobin) )
8502                 {
8503                         if (MMPLAYER_IS_RTSP_STREAMING(player))
8504                                 return ret;
8505                         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
8506                 }
8507                 else if ( ret== MM_ERROR_NONE)
8508                 {
8509                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
8510                 }
8511         }
8512
8513         /* generate dot file before returning error */
8514         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-pause" );
8515
8516         MMPLAYER_FLEAVE();
8517
8518         return ret;
8519 }
8520
8521 int __gst_resume(mm_player_t* player, gboolean async) // @
8522 {
8523         int ret = MM_ERROR_NONE;
8524         gint timeout = 0;
8525
8526         MMPLAYER_FENTER();
8527
8528         return_val_if_fail(player && player->pipeline,
8529                 MM_ERROR_PLAYER_NOT_INITIALIZED);
8530
8531         debug_log("current state before doing transition");
8532         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
8533         MMPLAYER_PRINT_STATE(player);
8534
8535         /* generate dot file before returning error */
8536         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
8537
8538         __mmplayer_set_antishock( player , FALSE );
8539
8540         if ( async )
8541                 debug_log("do async state transition to PLAYING.\n");
8542
8543         /* set pipeline state to PLAYING */
8544         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8545
8546         ret = __mmplayer_gst_set_state(player,
8547                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout );
8548         if (ret != MM_ERROR_NONE)
8549         {
8550                 debug_error("failed to set state to PLAYING\n");
8551                 return ret;
8552         }
8553         else
8554         {
8555                 if (async == FALSE)
8556                 {
8557                         // MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING );
8558                         debug_log("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
8559                         ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
8560                 }
8561         }
8562
8563         /* generate dot file before returning error */
8564         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
8565
8566         MMPLAYER_FLEAVE();
8567
8568         return ret;
8569 }
8570
8571 static int
8572 __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called) // @
8573 {
8574         unsigned long dur_msec = 0;
8575         gint64 dur_nsec = 0;
8576         gint64 pos_nsec = 0;
8577         gboolean ret = TRUE;
8578         gboolean accurated = FALSE;
8579         GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
8580
8581         MMPLAYER_FENTER();
8582         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8583         return_val_if_fail ( !MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP );
8584
8585         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
8586                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED )
8587                 goto PENDING;
8588
8589         if( !MMPLAYER_IS_ES_BUFF_SRC(player) )
8590         {
8591                 /* check duration */
8592                 /* NOTE : duration cannot be zero except live streaming.
8593                  *              Since some element could have some timing problemn with quering duration, try again.
8594                  */
8595                 if ( !player->duration )
8596                 {
8597                         if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
8598                         {
8599                                 goto SEEK_ERROR;
8600                         }
8601                         player->duration = dur_nsec;
8602                 }
8603
8604                 if ( player->duration )
8605                 {
8606                         dur_msec = GST_TIME_AS_MSECONDS(player->duration);
8607                 }
8608                 else
8609                 {
8610                         debug_error("could not get the duration. fail to seek.\n");
8611                         goto SEEK_ERROR;
8612                 }
8613         }
8614         debug_log("playback rate: %f\n", player->playback_rate);
8615
8616         mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
8617         if (accurated)
8618         {
8619                 seek_flags |= GST_SEEK_FLAG_ACCURATE;
8620         }
8621         else
8622         {
8623                 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
8624         }
8625
8626         /* do seek */
8627         switch ( format )
8628         {
8629                 case MM_PLAYER_POS_FORMAT_TIME:
8630                 {
8631                         if( !MMPLAYER_IS_ES_BUFF_SRC(player) )
8632                         {
8633                                 /* check position is valid or not */
8634                                 if ( position > dur_msec )
8635                                         goto INVALID_ARGS;
8636
8637                                 debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec);
8638
8639                                 if ( player->doing_seek )
8640                                 {
8641                                         debug_log("not completed seek");
8642                                         return MM_ERROR_PLAYER_DOING_SEEK;
8643                                 }
8644                         }
8645
8646                         if ( !internal_called )
8647                                 player->doing_seek = TRUE;
8648
8649                         pos_nsec = position * G_GINT64_CONSTANT(1000000);
8650
8651                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked))
8652                         {
8653                                 gint64 cur_time = 0;
8654
8655                                 /* get current position */
8656                                 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
8657
8658                                 /* flush */
8659                                 GstEvent *event = gst_event_new_seek (1.0,
8660                                                                 GST_FORMAT_TIME,
8661                                                                 (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
8662                                                                 GST_SEEK_TYPE_SET, cur_time,
8663                                                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
8664                                 if(event) {
8665                                         __gst_send_event_to_sink(player, event);
8666                                 }
8667
8668                                 __gst_pause( player, FALSE );
8669                         }
8670
8671                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8672                                                         GST_FORMAT_TIME, seek_flags,
8673                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
8674                         if ( !ret  )
8675                         {
8676                                 debug_error("failed to set position. dur[%lu]  pos[%lu]  pos_msec[%llu]\n", dur_msec, position, pos_nsec);
8677                                 goto SEEK_ERROR;
8678                         }
8679                 }
8680                 break;
8681
8682                 case MM_PLAYER_POS_FORMAT_PERCENT:
8683                 {
8684                         debug_log("seeking to (%lu)%% \n", position);
8685
8686                         if (player->doing_seek)
8687                         {
8688                                 debug_log("not completed seek");
8689                                 return MM_ERROR_PLAYER_DOING_SEEK;
8690                         }
8691
8692                         if ( !internal_called)
8693                                 player->doing_seek = TRUE;
8694
8695                         /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
8696                         pos_nsec = (gint64) ( ( position * player->duration ) / 100 );
8697                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8698                                                         GST_FORMAT_TIME, seek_flags,
8699                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
8700                         if ( !ret  )
8701                         {
8702                                 debug_error("failed to set position. dur[%lud]  pos[%lud]  pos_msec[%llud]\n", dur_msec, position, pos_nsec);
8703                                 goto SEEK_ERROR;
8704                         }
8705                 }
8706                 break;
8707
8708                 default:
8709                         goto INVALID_ARGS;
8710
8711         }
8712
8713         /* NOTE : store last seeking point to overcome some bad operation
8714           *      ( returning zero when getting current position ) of some elements
8715           */
8716         player->last_position = pos_nsec;
8717
8718         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
8719         if ( player->playback_rate > 1.0 )
8720                 _mmplayer_set_playspeed ( (MMHandleType)player, player->playback_rate );
8721
8722         MMPLAYER_FLEAVE();
8723         return MM_ERROR_NONE;
8724
8725 PENDING:
8726         player->pending_seek.is_pending = TRUE;
8727         player->pending_seek.format = format;
8728         player->pending_seek.pos = position;
8729
8730         debug_warning("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n",
8731                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
8732
8733         return MM_ERROR_NONE;
8734
8735 INVALID_ARGS:
8736         debug_error("invalid arguments, position : %ld  dur : %ld format : %d \n", position, dur_msec, format);
8737         return MM_ERROR_INVALID_ARGUMENT;
8738
8739 SEEK_ERROR:
8740         player->doing_seek = FALSE;
8741         return MM_ERROR_PLAYER_SEEK;
8742 }
8743
8744 #define TRICKPLAY_OFFSET GST_MSECOND
8745
8746 static int
8747 __gst_get_position(mm_player_t* player, int format, unsigned long* position) // @
8748 {
8749         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
8750         signed long long pos_msec = 0;
8751         gboolean ret = TRUE;
8752
8753         return_val_if_fail( player && position && player->pipeline && player->pipeline->mainbin,
8754                 MM_ERROR_PLAYER_NOT_INITIALIZED );
8755
8756         current_state = MMPLAYER_CURRENT_STATE(player);
8757
8758         /* NOTE : query position except paused state to overcome some bad operation
8759          * please refer to below comments in details
8760          */
8761         if ( current_state != MM_PLAYER_STATE_PAUSED )
8762         {
8763                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
8764         }
8765
8766         /* NOTE : get last point to overcome some bad operation of some elements
8767          * ( returning zero when getting current position in paused state
8768          * and when failed to get postion during seeking
8769          */
8770         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
8771                 || ( ! ret ))
8772                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
8773         {
8774                 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
8775
8776                 if(player->playback_rate < 0.0)
8777                         pos_msec = player->last_position - TRICKPLAY_OFFSET;
8778                 else
8779                         pos_msec = player->last_position;
8780
8781                 if (!ret)
8782                         pos_msec = player->last_position;
8783                 else
8784                         player->last_position = pos_msec;
8785
8786                 debug_log("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
8787
8788         }
8789         else
8790         {
8791                 if (player->duration > 0 && pos_msec > player->duration) {
8792                         pos_msec = player->duration;
8793                 }
8794
8795                 if (player->sm.keep_last_pos) {
8796                         debug_log("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position));
8797                         pos_msec = player->last_position;
8798                 }
8799                 else {
8800                         player->last_position = pos_msec;
8801                 }
8802         }
8803
8804         switch (format) {
8805                 case MM_PLAYER_POS_FORMAT_TIME:
8806                         *position = GST_TIME_AS_MSECONDS(pos_msec);
8807                         break;
8808
8809                 case MM_PLAYER_POS_FORMAT_PERCENT:
8810                 {
8811                         gint64 dur = 0;
8812                         gint64 pos = 0;
8813
8814                         dur = player->duration / GST_SECOND;
8815                         if (dur <= 0)
8816                         {
8817                                 debug_log ("duration is [%d], so returning position 0\n",dur);
8818                                 *position = 0;
8819                         }
8820                         else
8821                         {
8822                                 pos = pos_msec / GST_SECOND;
8823                                 *position = pos * 100 / dur;
8824                         }
8825                         break;
8826                 }
8827                 default:
8828                         return MM_ERROR_PLAYER_INTERNAL;
8829         }
8830
8831         return MM_ERROR_NONE;
8832 }
8833
8834
8835 static int      __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
8836 {
8837 #define STREAMING_IS_FINISHED   0
8838 #define BUFFERING_MAX_PER       100
8839
8840         GstQuery *query = NULL;
8841
8842         return_val_if_fail( player &&
8843                                                 player->pipeline &&
8844                                                 player->pipeline->mainbin,
8845                                                 MM_ERROR_PLAYER_NOT_INITIALIZED );
8846
8847         return_val_if_fail( start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT );
8848
8849         if (!MMPLAYER_IS_HTTP_STREAMING ( player ))
8850         {
8851                 /* and rtsp is not ready yet. */
8852                 debug_warning ( "it's only used for http streaming case.\n" );
8853                 return MM_ERROR_NONE;
8854         }
8855
8856         *start_pos = 0;
8857         *stop_pos = 0;
8858
8859         switch ( format )
8860         {
8861                 case MM_PLAYER_POS_FORMAT_PERCENT :
8862                 {
8863                         gint start_per = -1, stop_per = -1;
8864                         gint64 buffered_total = 0;
8865
8866                         unsigned long position = 0;
8867                         guint curr_size_bytes = 0;
8868                         gint64 buffering_left = -1;
8869                         gint buffered_sec = -1;
8870
8871                         gint64 content_duration = player->duration;
8872                         guint64 content_size = player->http_content_size;
8873
8874                         if (content_duration > 0)
8875                         {
8876                                 if (!__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position))
8877                                 {
8878                                         debug_log ("[Time] pos %d ms / dur %d sec / %lld bytes", position, (guint)(content_duration/GST_SECOND), content_size);
8879                                         start_per = 100 * (position*GST_MSECOND) / content_duration;
8880
8881                                         /* buffered size info from multiqueue */
8882                                         if (player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst)
8883                                         {
8884                                                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst), "curr-size-bytes", &curr_size_bytes, NULL);
8885                                                 debug_log ("[MQ] curr_size_bytes = %d", curr_size_bytes);
8886
8887                                                 buffered_total += curr_size_bytes;
8888                                         }
8889
8890                                         /* buffered size info from queue2 */
8891                                         if (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
8892                                         {
8893                                                 query = gst_query_new_buffering ( GST_FORMAT_BYTES );
8894                                                 if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query))
8895                                                 {
8896                                                         GstBufferingMode mode;
8897                                                         gint byte_in_rate = 0, byte_out_rate = 0;
8898                                                         gint64 start_byte = 0, stop_byte = 0;
8899                                                         guint num_of_ranges = 0;
8900                                                         guint idx = 0;
8901
8902                                                         num_of_ranges = gst_query_get_n_buffering_ranges(query);
8903                                                         for ( idx=0 ; idx<num_of_ranges ; idx++ )
8904                                                         {
8905                                                                 gst_query_parse_nth_buffering_range (query, idx, &start_byte, &stop_byte);
8906                                                                 debug_log ("[Q2][range %d] %lld ~ %lld\n", idx, start_byte, stop_byte);
8907
8908                                                                 buffered_total += (stop_byte - start_byte);
8909                                                         }
8910
8911                                                         gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, &buffering_left);
8912                                                         debug_log ("[Q2] in_rate %d, out_rate %d, left %lld\n", byte_in_rate, byte_out_rate, buffering_left);
8913                                                 }
8914                                                 gst_query_unref (query);
8915                                         }
8916
8917                                         if (buffering_left == STREAMING_IS_FINISHED)
8918                                         {
8919                                                 stop_per = BUFFERING_MAX_PER;
8920                                         }
8921                                         else
8922                                         {
8923                                                 guint dur_sec = (guint)(content_duration/GST_SECOND);
8924                                                 guint avg_byterate = (dur_sec>0)?((guint)(content_size/dur_sec)):(0);
8925
8926                                                 if (avg_byterate > 0)
8927                                                         buffered_sec = (gint)(buffered_total/avg_byterate);
8928                                                 else if (player->total_maximum_bitrate > 0)
8929                                                         buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_maximum_bitrate);
8930                                                 else if (player->total_bitrate > 0)
8931                                                         buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_bitrate);
8932
8933                                                 if ((buffered_sec >= 0) && (dur_sec > 0))
8934                                                         stop_per = start_per + (100 * buffered_sec / dur_sec);
8935                                         }
8936
8937                                         debug_log ("[Buffered Total] %lld bytes, %d sec, per %d~%d\n", buffered_total, buffered_sec, start_per, stop_per);
8938                                 }
8939                         }
8940
8941                         if (((buffered_total == 0) || (start_per < 0) || (stop_per < 0)) &&
8942                                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
8943                         {
8944                                 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
8945                                 if ( gst_element_query ( player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query ) )
8946                                 {
8947                                         GstFormat format;
8948                                         gint64 range_start_per = -1, range_stop_per = -1;
8949
8950                                         gst_query_parse_buffering_range ( query, &format, &range_start_per, &range_stop_per, NULL );
8951
8952                                         debug_log ("[Q2] range start %" G_GINT64_FORMAT " ~ stop %" G_GINT64_FORMAT "\n",  range_start_per , range_stop_per);
8953
8954                                         if (range_start_per != -1)
8955                                                 start_per = (gint)(100 * range_start_per / GST_FORMAT_PERCENT_MAX);
8956
8957                                         if (range_stop_per != -1)
8958                                                 stop_per = (gint)(100 * range_stop_per / GST_FORMAT_PERCENT_MAX);
8959                                 }
8960                                 gst_query_unref (query);
8961                         }
8962
8963                         if ( start_per > 0)
8964                                 *start_pos = (start_per < 100)?(start_per):(100);
8965                         else
8966                                 *start_pos = 0;
8967
8968                         if ( stop_per > 0)
8969                                 *stop_pos = (stop_per < 100)?(stop_per):(100);
8970                         else
8971                                 *stop_pos = 0;
8972
8973                         break;
8974                 }
8975                 case MM_PLAYER_POS_FORMAT_TIME :
8976                         debug_warning ( "Time format is not supported yet.\n" );
8977                         break;
8978
8979                 default :
8980                         break;
8981         }
8982
8983         debug_log("current buffer position : %lu~%lu \n", *start_pos, *stop_pos );
8984
8985         return MM_ERROR_NONE;
8986 }
8987
8988 static int
8989 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param) // @
8990 {
8991         MMPLAYER_FENTER();
8992
8993         if ( !player )
8994         {
8995                 debug_warning("set_message_callback is called with invalid player handle\n");
8996                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
8997         }
8998
8999         player->msg_cb = callback;
9000         player->msg_cb_param = user_param;
9001
9002         debug_log("msg_cb : 0x%x     msg_cb_param : 0x%x\n", (guint)callback, (guint)user_param);
9003
9004         MMPLAYER_FLEAVE();
9005
9006         return MM_ERROR_NONE;
9007 }
9008
9009 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
9010 {
9011         int ret = MM_ERROR_PLAYER_INVALID_URI;
9012         char *path = NULL;
9013
9014         MMPLAYER_FENTER();
9015
9016         return_val_if_fail ( uri , FALSE);
9017         return_val_if_fail ( data , FALSE);
9018         return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
9019
9020         memset(data, 0, sizeof(MMPlayerParseProfile));
9021
9022         if ((path = strstr(uri, "file://")))
9023         {
9024                 int file_stat = MM_ERROR_NONE;
9025
9026                 file_stat = util_exist_file_path(path + 7);
9027
9028                 if (file_stat == MM_ERROR_NONE)
9029                 {
9030                         strncpy(data->uri, path, MM_MAX_URL_LEN-1);
9031
9032                         if ( util_is_sdp_file ( path ) )
9033                         {
9034                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
9035                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9036                         }
9037                         else
9038                         {
9039                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
9040                         }
9041                         ret = MM_ERROR_NONE;
9042                 }
9043                 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
9044                 {
9045                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
9046                 }
9047                 else
9048                 {
9049                         debug_warning("could  access %s.\n", path);
9050                 }
9051         }
9052         else if ((path = strstr(uri, "es_buff://")))
9053         {
9054                 if (strlen(path))
9055                 {
9056                         strcpy(data->uri, uri);
9057                         data->uri_type = MM_PLAYER_URI_TYPE_ES_BUFF;
9058                         ret = MM_ERROR_NONE;
9059                 }
9060         }
9061         else if ((path = strstr(uri, "buff://")))
9062         {
9063                         data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
9064                         ret = MM_ERROR_NONE;
9065         }
9066         else if ((path = strstr(uri, "rtsp://")))
9067         {
9068                 if (strlen(path)) {
9069                         if((path = strstr(uri, "/wfd1.0/"))) {
9070                                 strcpy(data->uri, uri);
9071                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_WFD;
9072                                 ret = MM_ERROR_NONE;
9073                                 debug_log("uri is actually a wfd client path. giving it to wfdrtspsrc\n");
9074                         }
9075                         else {
9076                                 strcpy(data->uri, uri);
9077                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9078                                 ret = MM_ERROR_NONE;
9079                         }
9080                 }
9081         }
9082         else if ((path = strstr(uri, "http://")))
9083         {
9084                 if (strlen(path)) {
9085                         strcpy(data->uri, uri);
9086 #ifdef MM_SMOOTH_STREAMING
9087                         if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
9088                                 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
9089                         {
9090                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
9091                         }
9092                         else
9093 #endif
9094                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
9095
9096                         ret = MM_ERROR_NONE;
9097                 }
9098         }
9099         else if ((path = strstr(uri, "https://")))
9100         {
9101                 if (strlen(path)) {
9102                         strcpy(data->uri, uri);
9103 #ifdef MM_SMOOTH_STREAMING
9104                 if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
9105                                 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
9106                         {
9107                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
9108                         }
9109 #endif
9110                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
9111
9112                         ret = MM_ERROR_NONE;
9113                 }
9114         }
9115         else if ((path = strstr(uri, "rtspu://")))
9116         {
9117                 if (strlen(path)) {
9118                         strcpy(data->uri, uri);
9119                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9120                         ret = MM_ERROR_NONE;
9121                 }
9122         }
9123         else if ((path = strstr(uri, "rtspr://")))
9124         {
9125                 strcpy(data->uri, path);
9126                 char *separater =strstr(path, "*");
9127
9128                 if (separater) {
9129                         int urgent_len = 0;
9130                         char *urgent = separater + strlen("*");
9131
9132                         if ((urgent_len = strlen(urgent))) {
9133                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
9134                                 strcpy(data->urgent, urgent);
9135                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9136                                 ret = MM_ERROR_NONE;
9137                         }
9138                 }
9139         }
9140         else if ((path = strstr(uri, "mms://")))
9141         {
9142                 if (strlen(path)) {
9143                         strcpy(data->uri, uri);
9144                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
9145                         ret = MM_ERROR_NONE;
9146                 }
9147         }
9148         else if ((path = strstr(uri, "mem://")))
9149         {
9150                 if (strlen(path)) {
9151                         int mem_size = 0;
9152                         char *buffer = NULL;
9153                         char *seperator = strchr(path, ',');
9154                         char ext[100] = {0,}, size[100] = {0,};
9155
9156                         if (seperator) {
9157                                 if ((buffer = strstr(path, "ext="))) {
9158                                         buffer += strlen("ext=");
9159
9160                                         if (strlen(buffer)) {
9161                                                 strcpy(ext, buffer);
9162
9163                                                 if ((seperator = strchr(ext, ','))
9164                                                         || (seperator = strchr(ext, ' '))
9165                                                         || (seperator = strchr(ext, '\0'))) {
9166                                                         seperator[0] = '\0';
9167                                                 }
9168                                         }
9169                                 }
9170
9171                                 if ((buffer = strstr(path, "size="))) {
9172                                         buffer += strlen("size=");
9173
9174                                         if (strlen(buffer) > 0) {
9175                                                 strcpy(size, buffer);
9176
9177                                                 if ((seperator = strchr(size, ','))
9178                                                         || (seperator = strchr(size, ' '))
9179                                                         || (seperator = strchr(size, '\0'))) {
9180                                                         seperator[0] = '\0';
9181                                                 }
9182
9183                                                 mem_size = atoi(size);
9184                                         }
9185                                 }
9186                         }
9187
9188                         debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
9189                         if ( mem_size && param)
9190                         {
9191                                 data->mem = param;
9192                                 data->mem_size = mem_size;
9193                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
9194                                 ret = MM_ERROR_NONE;
9195                         }
9196                 }
9197         }
9198         else
9199         {
9200                 int file_stat = MM_ERROR_NONE;
9201
9202                 file_stat = util_exist_file_path(uri);
9203
9204                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
9205                 if (file_stat == MM_ERROR_NONE)
9206                 {
9207                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", uri);
9208
9209                         if ( util_is_sdp_file( (char*)uri ) )
9210                         {
9211                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
9212                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9213                         }
9214                         else
9215                         {
9216                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
9217                         }
9218                         ret = MM_ERROR_NONE;
9219                 }
9220                 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
9221                 {
9222                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
9223                 }
9224                 else
9225                 {
9226                         debug_error ("invalid uri, could not play..\n");
9227                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
9228                 }
9229         }
9230
9231         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
9232                 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
9233         } else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION){
9234                 ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
9235         }
9236
9237         /* dump parse result */
9238         secure_debug_warning("incomming uri : %s\n", uri);
9239         debug_log("uri_type : %d, mem : 0x%x, mem_size : %d, urgent : %s\n",
9240                 data->uri_type, (guint)data->mem, data->mem_size, data->urgent);
9241
9242         MMPLAYER_FLEAVE();
9243
9244         return ret;
9245 }
9246
9247 gboolean _asm_postmsg(gpointer *data)
9248 {
9249         mm_player_t* player = (mm_player_t*)data;
9250         MMMessageParamType msg = {0, };
9251
9252         MMPLAYER_FENTER();
9253         return_val_if_fail ( player, FALSE );
9254         debug_warning("get notified");
9255
9256         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
9257                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
9258         {
9259                 debug_warning("dispatched");
9260                 return FALSE;
9261         }
9262
9263
9264         msg.union_type = MM_MSG_UNION_CODE;
9265         msg.code = player->sm.event_src;
9266
9267 #if 0 // should remove
9268         if (player->sm.event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
9269         {
9270                 /* fill the message with state of player */
9271                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
9272                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
9273                 player->resumable_cancel_id = 0;
9274         }
9275         else
9276 #endif
9277         {
9278                 MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
9279                 player->resume_event_id = 0;
9280         }
9281
9282         debug_warning("dispatched");
9283         return FALSE;
9284 }
9285
9286 gboolean _asm_lazy_pause(gpointer *data)
9287 {
9288         mm_player_t* player = (mm_player_t*)data;
9289         int ret = MM_ERROR_NONE;
9290
9291         MMPLAYER_FENTER();
9292
9293         return_val_if_fail ( player, FALSE );
9294
9295         if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
9296         {
9297                 debug_log ("Ready to proceed lazy pause\n");
9298                 ret = _mmplayer_pause((MMHandleType)player);
9299                 if(MM_ERROR_NONE != ret)
9300                 {
9301                         debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
9302                 }
9303         }
9304         else
9305         {
9306                 debug_log ("Invalid state to proceed lazy pause\n");
9307         }
9308
9309         /* unset mute */
9310         if (player->pipeline && player->pipeline->audiobin)
9311                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
9312
9313         player->sm.by_asm_cb = FALSE; //should be reset here
9314
9315         MMPLAYER_FLEAVE();
9316
9317         return FALSE;
9318 }
9319
9320 static gboolean
9321 __mmplayer_can_do_interrupt(mm_player_t *player)
9322 {
9323         if (!player || !player->pipeline || !player->attrs)
9324         {
9325                 debug_warning("not initialized");
9326                 goto FAILED;
9327         }
9328
9329         if ((player->sm.exit_cb) || (player->set_mode.pcm_extraction))
9330         {
9331                 debug_warning("leave from asm cb right now, %d, %d", player->sm.exit_cb, player->set_mode.pcm_extraction);
9332                 goto FAILED;
9333         }
9334
9335         /* check if seeking */
9336         if (player->doing_seek)
9337         {
9338                 MMMessageParamType msg_param;
9339                 memset (&msg_param, 0, sizeof(MMMessageParamType));
9340                 msg_param.code = MM_ERROR_PLAYER_SEEK;
9341                 player->doing_seek = FALSE;
9342                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9343                 goto FAILED;
9344         }
9345
9346         /* check other thread */
9347         if (!g_mutex_trylock(&player->cmd_lock))
9348         {
9349                 debug_warning("locked already, cmd state : %d", player->cmd);
9350
9351                 /* check application command */
9352                 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)
9353                 {
9354                         debug_warning("playing.. should wait cmd lock then, will be interrupted");
9355                         g_mutex_lock(&player->cmd_lock);
9356                         goto INTERRUPT;
9357                 }
9358                 debug_warning("nothing to do");
9359                 goto FAILED;
9360         }
9361         else
9362         {
9363                 debug_warning("can interrupt immediately");
9364                 goto INTERRUPT;
9365         }
9366
9367 FAILED:
9368         return FALSE;
9369
9370 INTERRUPT:
9371         return TRUE;
9372 }
9373
9374 ASM_cb_result_t
9375 __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
9376 {
9377         mm_player_t* player = (mm_player_t*) cb_data;
9378         ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
9379         int result = MM_ERROR_NONE;
9380         gboolean lazy_pause = FALSE;
9381
9382         debug_warning("get notified");
9383
9384         if (!__mmplayer_can_do_interrupt(player))
9385         {
9386                 debug_warning("no need to interrupt, so leave");
9387                 goto EXIT;
9388         }
9389
9390         player->sm.cb_pending = TRUE;
9391         debug_warning("asm event src type : %d, command : 0x%x", event_src, command);
9392
9393         player->sm.by_asm_cb = TRUE;
9394         player->sm.event_src = event_src;
9395
9396         /* first, check event source */
9397         if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG)
9398         {
9399                 int stop_by_asm = 0;
9400                 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
9401                 if (!stop_by_asm)
9402                         goto DONE;
9403         }
9404         else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
9405         {
9406                 if(player->pipeline->videobin)
9407                 {
9408                         debug_log("video conflict so, resource will be freed.");
9409                         result = _mmplayer_unrealize((MMHandleType)player);
9410                         cb_res = ASM_CB_RES_STOP;
9411                 }
9412                 else if (player->pipeline->audiobin)
9413                 {
9414                         debug_log("audio resource conflict");
9415                         result = _mmplayer_pause((MMHandleType)player);
9416                         if (result != MM_ERROR_NONE)
9417                         {
9418                                 debug_warning("fail to set pause by asm");
9419                         }
9420                         cb_res = ASM_CB_RES_PAUSE;
9421                 }
9422                 goto DONE;
9423         }
9424 #if 0 // should remove
9425         else if (event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
9426         {
9427                 debug_warning("Got msg from asm for resumable canceled.\n");
9428                 player->sm.antishock = TRUE;
9429                 player->sm.by_asm_cb = FALSE;
9430
9431                 player->resumable_cancel_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
9432                 cb_res = ASM_CB_RES_IGNORE;
9433                 goto DONE;
9434         }
9435 #endif
9436         /* then, check command */
9437         switch(command)
9438         {
9439                 case ASM_COMMAND_PLAY:
9440                         debug_warning ("Got unexpected asm command (%d)", command);
9441                         break;
9442
9443                 case ASM_COMMAND_STOP: // notification case
9444                         {
9445                                 debug_warning("Got msg from asm to stop");
9446
9447                                 if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &player->last_position)) {
9448                                         debug_error("failed to get position");
9449                                         player->last_position = 0;
9450                                 }
9451
9452                                 debug_log ("pos_msec = %"GST_TIME_FORMAT"", GST_TIME_ARGS(player->last_position));
9453
9454                                 result = _mmplayer_stop((MMHandleType)player);
9455                                 if (result != MM_ERROR_NONE)
9456                                 {
9457                                         debug_warning("fail to set stop state by asm");
9458                                         cb_res = ASM_CB_RES_IGNORE;
9459                                 }
9460                                 else
9461                                 {
9462                                         cb_res = ASM_CB_RES_STOP;
9463                                 }
9464                                 player->sm.by_asm_cb = FALSE; // reset because no message any more from asm
9465                                 player->sm.keep_last_pos = TRUE;
9466                         }
9467                         break;
9468
9469                 case ASM_COMMAND_PAUSE:
9470                         {
9471                                 debug_warning("Got msg from asm to Pause");
9472                                 if(event_src == ASM_EVENT_SOURCE_CALL_START ||
9473                                         event_src == ASM_EVENT_SOURCE_ALARM_START ||
9474                                         event_src == ASM_EVENT_SOURCE_MEDIA)
9475                                 {
9476                                         if ( ! MMPLAYER_IS_RTSP_STREAMING(player) ) {
9477                                                 //hold 0.7 second to excute "fadedown mute" effect
9478                                                 debug_warning ("do fade down->pause->undo fade down");
9479
9480                                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
9481
9482                                                 result = _mmplayer_pause((MMHandleType)player);
9483                                                 if (result != MM_ERROR_NONE)
9484                                                 {
9485                                                         debug_warning("fail to set Pause state by asm");
9486                                                         cb_res = ASM_CB_RES_IGNORE;
9487                                                         break;
9488                                                 }
9489                                                 __mmplayer_undo_sound_fadedown(player);
9490                                         } else {
9491                                                 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
9492                                                 _mmplayer_unrealize((MMHandleType)player);
9493                                         }
9494                                 }
9495 #ifdef USE_LAZY_PAUSE // if enabled, should consider event id and context when removed
9496                                 else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
9497                                 {
9498                                         lazy_pause = TRUE; // return as soon as possible, for fast start of other app
9499
9500                                         if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
9501                                                 g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
9502
9503                                         player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
9504                                         debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
9505                                 }
9506 #endif
9507                                 else
9508                                 {
9509                                         debug_warning ("pause immediately");
9510                                         result = _mmplayer_pause((MMHandleType)player);
9511                                 }
9512                                 cb_res = ASM_CB_RES_PAUSE;
9513                         }
9514                         break;
9515
9516                 case ASM_COMMAND_RESUME:
9517                         {
9518                                 debug_warning("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
9519                                 player->sm.antishock = TRUE;
9520                                 player->sm.by_asm_cb = FALSE;
9521
9522                                 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
9523                                 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
9524                                 cb_res = ASM_CB_RES_IGNORE;
9525                                 goto DONE;
9526                         }
9527                         break;
9528
9529                 default:
9530                         break;
9531         }
9532
9533 DONE:
9534         if ( !lazy_pause )
9535         {
9536                 player->sm.by_asm_cb = FALSE;
9537         }
9538         player->sm.cb_pending = FALSE;
9539         MMPLAYER_CMD_UNLOCK( player );
9540
9541 EXIT:
9542         debug_warning("dispatched");
9543         return cb_res;
9544 }
9545
9546 int
9547 _mmplayer_create_player(MMHandleType handle) // @
9548 {
9549         mm_player_t* player = MM_PLAYER_CAST(handle);
9550
9551         MMPLAYER_FENTER();
9552
9553         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9554
9555         /* initialize player state */
9556         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
9557         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
9558         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
9559         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
9560
9561         /* check current state */
9562         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
9563
9564         /* construct attributes */
9565         player->attrs = _mmplayer_construct_attribute(handle);
9566
9567         if ( !player->attrs )
9568         {
9569                 debug_error("Failed to construct attributes\n");
9570                 goto ERROR;
9571         }
9572
9573         /* initialize gstreamer with configured parameter */
9574         if ( ! __mmplayer_init_gstreamer(player) )
9575         {
9576                 debug_error("Initializing gstreamer failed\n");
9577                 goto ERROR;
9578         }
9579
9580         /* initialize factories if not using decodebin */
9581         if( player->factories == NULL )
9582             __mmplayer_init_factories(player);
9583
9584         /* create lock. note that g_tread_init() has already called in gst_init() */
9585         g_mutex_init(&player->fsink_lock);
9586
9587         /* create repeat mutex */
9588         g_mutex_init(&player->repeat_thread_mutex);
9589
9590         /* create repeat cond */
9591         g_cond_init(&player->repeat_thread_cond);
9592
9593         /* create repeat thread */
9594         player->repeat_thread =
9595                 g_thread_try_new ("repeat_thread", __mmplayer_repeat_thread, (gpointer)player, NULL);
9596
9597
9598         /* create next play mutex */
9599         g_mutex_init(&player->next_play_thread_mutex);
9600
9601         /* create next play cond */
9602         g_cond_init(&player->next_play_thread_cond);
9603
9604         /* create next play thread */
9605         player->next_play_thread =
9606                 g_thread_try_new ("next_play_thread", __mmplayer_next_play_thread, (gpointer)player, NULL);
9607         if ( ! player->next_play_thread )
9608         {
9609                 debug_error("failed to create next play thread");
9610                 goto ERROR;
9611         }
9612
9613         if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
9614         {
9615                 debug_error("failed to initialize video capture\n");
9616                 goto ERROR;
9617         }
9618 #if 0
9619         /* register to asm */
9620         if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
9621         {
9622                 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
9623                 debug_error("failed to register asm server\n");
9624                 return MM_ERROR_POLICY_INTERNAL;
9625         }
9626
9627         /* to add active device callback */
9628         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))
9629         {
9630                 debug_error("failed mm_sound_add_device_information_changed_callback \n");
9631         }
9632 #endif
9633
9634         if (MMPLAYER_IS_HTTP_PD(player))
9635         {
9636                 player->pd_downloader = NULL;
9637                 player->pd_file_save_path = NULL;
9638         }
9639
9640         player->streaming_type = STREAMING_SERVICE_NONE;
9641
9642         /* give default value of audio effect setting */
9643         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
9644         player->playback_rate = DEFAULT_PLAYBACK_RATE;
9645
9646         player->play_subtitle = FALSE;
9647         player->use_textoverlay = FALSE;
9648         player->play_count = 0;
9649         player->use_decodebin = TRUE;
9650         player->ignore_asyncdone = FALSE;
9651         player->use_deinterleave = FALSE;
9652         player->max_audio_channels = 0;
9653         player->video_share_api_delta = 0;
9654         player->video_share_clock_delta = 0;
9655         player->has_closed_caption = FALSE;
9656
9657         __mmplayer_post_proc_reset(player);
9658
9659         if (player->ini.dump_element_keyword[0][0] == '\0')
9660         {
9661                 player->ini.set_dump_element_flag= FALSE;
9662         }
9663         else
9664         {
9665                 player->ini.set_dump_element_flag = TRUE;
9666         }
9667
9668         /* set player state to null */
9669         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
9670         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
9671
9672         return MM_ERROR_NONE;
9673
9674 ERROR:
9675         /* free lock */
9676         g_mutex_clear(&player->fsink_lock );
9677
9678         /* free thread */
9679         if ( player->repeat_thread )
9680         {
9681                 player->repeat_thread_exit = TRUE;
9682                 g_cond_signal( &player->repeat_thread_cond );
9683
9684                 g_thread_join( player->repeat_thread );
9685                 player->repeat_thread = NULL;
9686
9687                 g_mutex_clear(&player->repeat_thread_mutex );
9688
9689                 g_cond_clear (&player->repeat_thread_cond );
9690         }
9691         /* clear repeat thread mutex/cond if still alive
9692          * this can happen if only thread creating has failed
9693          */
9694         g_mutex_clear(&player->repeat_thread_mutex );
9695         g_cond_clear ( &player->repeat_thread_cond );
9696
9697         /* free next play thread */
9698         if ( player->next_play_thread )
9699         {
9700                 player->next_play_thread_exit = TRUE;
9701                 g_cond_signal( &player->next_play_thread_cond );
9702
9703                 g_thread_join( player->next_play_thread );
9704                 player->next_play_thread = NULL;
9705
9706                 g_mutex_clear(&player->next_play_thread_mutex );
9707
9708                 g_cond_clear ( &player->next_play_thread_cond );
9709         }
9710         /* clear next play thread mutex/cond if still alive
9711          * this can happen if only thread creating has failed
9712          */
9713         g_mutex_clear(&player->next_play_thread_mutex );
9714
9715         g_cond_clear ( &player->next_play_thread_cond );
9716
9717         /* release attributes */
9718         _mmplayer_deconstruct_attribute(handle);
9719
9720         MMPLAYER_FLEAVE();
9721
9722         return MM_ERROR_PLAYER_INTERNAL;
9723 }
9724
9725 static gboolean
9726 __mmplayer_init_gstreamer(mm_player_t* player) // @
9727 {
9728         static gboolean initialized = FALSE;
9729         static const int max_argc = 50;
9730         gint* argc = NULL;
9731         gchar** argv = NULL;
9732         gchar** argv2 = NULL;
9733         GError *err = NULL;
9734         int i = 0;
9735         int arg_count = 0;
9736
9737         if ( initialized )
9738         {
9739                 debug_log("gstreamer already initialized.\n");
9740                 return TRUE;
9741         }
9742
9743         /* alloc */
9744         argc = malloc( sizeof(int) );
9745         argv = malloc( sizeof(gchar*) * max_argc );
9746         argv2 = malloc( sizeof(gchar*) * max_argc );
9747
9748         if ( !argc || !argv )
9749                 goto ERROR;
9750
9751         memset( argv, 0, sizeof(gchar*) * max_argc );
9752         memset( argv2, 0, sizeof(gchar*) * max_argc );
9753
9754         /* add initial */
9755         *argc = 1;
9756         argv[0] = g_strdup( "mmplayer" );
9757
9758         /* add gst_param */
9759         for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
9760         {
9761                 if ( strlen( player->ini.gst_param[i] ) > 0 )
9762                 {
9763                         argv[*argc] = g_strdup( player->ini.gst_param[i] );
9764                         (*argc)++;
9765                 }
9766         }
9767
9768         /* we would not do fork for scanning plugins */
9769         argv[*argc] = g_strdup("--gst-disable-registry-fork");
9770         (*argc)++;
9771
9772         /* check disable registry scan */
9773         if ( player->ini.skip_rescan )
9774         {
9775                 argv[*argc] = g_strdup("--gst-disable-registry-update");
9776                 (*argc)++;
9777         }
9778
9779         /* check disable segtrap */
9780         if ( player->ini.disable_segtrap )
9781         {
9782                 argv[*argc] = g_strdup("--gst-disable-segtrap");
9783                 (*argc)++;
9784         }
9785
9786         debug_log("initializing gstreamer with following parameter\n");
9787         debug_log("argc : %d\n", *argc);
9788         arg_count = *argc;
9789
9790         for ( i = 0; i < arg_count; i++ )
9791         {
9792                 argv2[i] = argv[i];
9793                 debug_log("argv[%d] : %s\n", i, argv2[i]);
9794         }
9795
9796
9797         /* initializing gstreamer */
9798         if ( ! gst_init_check (argc, &argv, &err))
9799         {
9800                 debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
9801                 if (err)
9802                 {
9803                         g_error_free (err);
9804                 }
9805
9806                 goto ERROR;
9807         }
9808         /* release */
9809         for ( i = 0; i < arg_count; i++ )
9810         {
9811                 //debug_log("release - argv[%d] : %s\n", i, argv2[i]);
9812                 MMPLAYER_FREEIF( argv2[i] );
9813         }
9814
9815         MMPLAYER_FREEIF( argv );
9816         MMPLAYER_FREEIF( argv2 );
9817         MMPLAYER_FREEIF( argc );
9818
9819         /* done */
9820         initialized = TRUE;
9821
9822         return TRUE;
9823
9824 ERROR:
9825
9826         /* release */
9827         for ( i = 0; i < arg_count; i++ )
9828         {
9829                 debug_log("free[%d] : %s\n", i, argv2[i]);
9830                 MMPLAYER_FREEIF( argv2[i] );
9831         }
9832
9833         MMPLAYER_FREEIF( argv );
9834         MMPLAYER_FREEIF( argv2 );
9835         MMPLAYER_FREEIF( argc );
9836
9837         return FALSE;
9838 }
9839
9840 int
9841 __mmplayer_destroy_streaming_ext(mm_player_t* player)
9842 {
9843         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9844
9845         if (player->pd_downloader)
9846         {
9847                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
9848                 MMPLAYER_FREEIF(player->pd_downloader);
9849         }
9850
9851         if (MMPLAYER_IS_HTTP_PD(player))
9852         {
9853                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
9854                 MMPLAYER_FREEIF(player->pd_file_save_path);
9855         }
9856
9857         return MM_ERROR_NONE;
9858 }
9859
9860 int
9861 _mmplayer_destroy(MMHandleType handle) // @
9862 {
9863         mm_player_t* player = MM_PLAYER_CAST(handle);
9864
9865         MMPLAYER_FENTER();
9866
9867         /* check player handle */
9868         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9869
9870         /* destroy can called at anytime */
9871         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
9872
9873         __mmplayer_destroy_streaming_ext(player);
9874
9875         /* release repeat thread */
9876         if ( player->repeat_thread )
9877         {
9878                 player->repeat_thread_exit = TRUE;
9879                 g_cond_signal( &player->repeat_thread_cond );
9880
9881                 debug_log("waitting for repeat thread exit\n");
9882                 g_thread_join ( player->repeat_thread );
9883                 g_mutex_clear(&player->repeat_thread_mutex );
9884                 g_cond_clear (&player->repeat_thread_cond );
9885                 debug_log("repeat thread released\n");
9886         }
9887
9888         /* release next play thread */
9889         if ( player->next_play_thread )
9890         {
9891                 player->next_play_thread_exit = TRUE;
9892                 g_cond_signal( &player->next_play_thread_cond );
9893
9894                 debug_log("waitting for next play thread exit\n");
9895                 g_thread_join ( player->next_play_thread );
9896                 g_mutex_clear(&player->next_play_thread_mutex );
9897                 g_cond_clear(&player->next_play_thread_cond );
9898                 debug_log("next play thread released\n");
9899         }
9900
9901         _mmplayer_release_video_capture(player);
9902
9903         /* flush any pending asm_cb */
9904         if (player->sm.cb_pending)
9905         {
9906                 /* set a flag for make sure asm_cb to be returned immediately */
9907                 debug_warning("asm cb has pending state");
9908                 player->sm.exit_cb = TRUE;
9909
9910                 /* make sure to release any pending asm_cb which locked by cmd_lock */
9911                 MMPLAYER_CMD_UNLOCK(player);
9912                 sched_yield();
9913                 MMPLAYER_CMD_LOCK(player);
9914         }
9915 #if 0
9916         /* withdraw asm */
9917         if ( MM_ERROR_NONE != _mmplayer_asm_unregister(&player->sm) )
9918         {
9919                 debug_error("failed to deregister asm server\n");
9920         }
9921 #endif
9922 #ifdef USE_LAZY_PAUSE
9923         if (player->lazy_pause_event_id)
9924         {
9925                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->lazy_pause_event_id);
9926                 player->lazy_pause_event_id = 0;
9927         }
9928 #endif
9929
9930         if (player->resume_event_id)
9931         {
9932                 g_source_remove (player->resume_event_id);
9933                 player->resume_event_id = 0;
9934         }
9935
9936         if (player->resumable_cancel_id)
9937         {
9938                 g_source_remove (player->resumable_cancel_id);
9939                 player->resumable_cancel_id = 0;
9940         }
9941
9942         /* release pipeline */
9943         if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
9944         {
9945                 debug_error("failed to destory pipeline\n");
9946                 return MM_ERROR_PLAYER_INTERNAL;
9947         }
9948
9949         if (player->is_external_subtitle_present && player->subtitle_language_list)
9950         {
9951           g_list_free (player->subtitle_language_list);
9952           player->subtitle_language_list = NULL;
9953         }
9954
9955         __mmplayer_release_dump_list (player->dump_list);
9956
9957         /* release miscellaneous information.
9958            these info needs to be released after pipeline is destroyed. */
9959         __mmplayer_release_misc_post( player );
9960
9961         /* release attributes */
9962         _mmplayer_deconstruct_attribute( handle );
9963
9964         /* release factories */
9965         __mmplayer_release_factories( player );
9966
9967         /* release lock */
9968         g_mutex_clear(&player->fsink_lock );
9969
9970         g_mutex_clear(&player->msg_cb_lock );
9971
9972         MMPLAYER_FLEAVE();
9973
9974         return MM_ERROR_NONE;
9975 }
9976
9977 int
9978 __mmplayer_realize_streaming_ext(mm_player_t* player)
9979 {
9980         int ret = MM_ERROR_NONE;
9981
9982         MMPLAYER_FENTER();
9983         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9984
9985         if (MMPLAYER_IS_HTTP_PD(player))
9986         {
9987                 gboolean bret = FALSE;
9988
9989                 player->pd_downloader = _mmplayer_create_pd_downloader();
9990                 if ( !player->pd_downloader )
9991                 {
9992                         debug_error ("Unable to create PD Downloader...");
9993                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
9994                 }
9995
9996                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
9997
9998                 if (FALSE == bret)
9999                 {
10000                         debug_error ("Unable to create PD Downloader...");
10001                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
10002                 }
10003         }
10004
10005         MMPLAYER_FLEAVE();
10006         return ret;
10007 }
10008
10009 int
10010 _mmplayer_realize(MMHandleType hplayer) // @
10011 {
10012         mm_player_t* player =  (mm_player_t*)hplayer;
10013         char *uri =NULL;
10014         void *param = NULL;
10015         int application_pid = -1;
10016         gboolean update_registry = FALSE;
10017         MMHandleType attrs = 0;
10018         int ret = MM_ERROR_NONE;
10019
10020         MMPLAYER_FENTER();
10021
10022         /* check player handle */
10023         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
10024
10025         /* check current state */
10026         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
10027
10028         attrs = MMPLAYER_GET_ATTRS(player);
10029         if ( !attrs )
10030         {
10031                 debug_error("fail to get attributes.\n");
10032                 return MM_ERROR_PLAYER_INTERNAL;
10033         }
10034
10035         mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
10036         player->sm.pid = application_pid;
10037
10038         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
10039         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
10040
10041         ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
10042
10043         if (ret != MM_ERROR_NONE)
10044         {
10045                 debug_error("failed to parse profile\n");
10046                 return ret;
10047         }
10048
10049         /* FIXIT : we can use thouse in player->profile directly */
10050         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
10051         {
10052                 player->mem_buf.buf = (char *)player->profile.mem;
10053                 player->mem_buf.len = player->profile.mem_size;
10054                 player->mem_buf.offset = 0;
10055         }
10056
10057         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF)
10058         {
10059                 if (strstr(uri, "es_buff://push_mode"))
10060                 {
10061                         player->es_player_push_mode = TRUE;
10062                 }
10063                 else
10064                 {
10065                         player->es_player_push_mode = FALSE;
10066                 }
10067         }
10068
10069         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
10070         {
10071                 debug_warning("mms protocol is not supported format.\n");
10072                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
10073         }
10074
10075         if (MMPLAYER_IS_STREAMING(player))
10076                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
10077         else
10078                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
10079
10080         player->smooth_streaming = FALSE;
10081         player->videodec_linked  = 0;
10082         player->videosink_linked = 0;
10083         player->audiodec_linked  = 0;
10084         player->audiosink_linked = 0;
10085         player->textsink_linked = 0;
10086         player->is_external_subtitle_present = FALSE;
10087         /* set the subtitle ON default */
10088         player->is_subtitle_off = FALSE;
10089
10090         /* registry should be updated for downloadable codec */
10091         mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
10092
10093         if ( update_registry )
10094         {
10095                 debug_log("updating registry...\n");
10096                 gst_update_registry();
10097
10098                 /* then we have to rebuild factories */
10099                 __mmplayer_release_factories( player );
10100                 __mmplayer_init_factories(player);
10101         }
10102
10103         /* realize pipeline */
10104         ret = __gst_realize( player );
10105         if ( ret != MM_ERROR_NONE )
10106         {
10107                 debug_error("fail to realize the player.\n");
10108         }
10109         else
10110         {
10111                 ret = __mmplayer_realize_streaming_ext(player);
10112         }
10113
10114         MMPLAYER_FLEAVE();
10115
10116         return ret;
10117 }
10118
10119 int
10120 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
10121 {
10122         MMPLAYER_FENTER();
10123         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10124
10125         /* destroy can called at anytime */
10126         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
10127         {
10128                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
10129                 MMPLAYER_FREEIF(player->pd_downloader);
10130         }
10131
10132         MMPLAYER_FLEAVE();
10133         return MM_ERROR_NONE;
10134 }
10135
10136 int
10137 _mmplayer_unrealize(MMHandleType hplayer)
10138 {
10139         mm_player_t* player = (mm_player_t*)hplayer;
10140         int ret = MM_ERROR_NONE;
10141
10142         MMPLAYER_FENTER();
10143
10144         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
10145
10146         /* check current state */
10147         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
10148
10149         __mmplayer_unrealize_streaming_ext(player);
10150
10151         /* unrealize pipeline */
10152         ret = __gst_unrealize( player );
10153
10154         /* set asm stop if success */
10155         if (MM_ERROR_NONE == ret)
10156         {
10157                 if (player->sm.state != ASM_STATE_STOP)
10158                 {
10159                         /* NOTE : Stop asm after pipeline unrealize. Keep this sequence. */
10160                         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP, FALSE);
10161                         if ( ret )
10162                         {
10163                                 debug_error("failed to set asm state to STOP");
10164                                 return ret;
10165                         }
10166                 }
10167         }
10168         else
10169         {
10170                 debug_error("failed and don't change asm state to stop");
10171         }
10172
10173         MMPLAYER_FLEAVE();
10174
10175         return ret;
10176 }
10177
10178 int
10179 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
10180 {
10181         mm_player_t* player = (mm_player_t*)hplayer;
10182
10183         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10184
10185         return __gst_set_message_callback(player, callback, user_param);
10186 }
10187
10188 int
10189 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
10190 {
10191         mm_player_t *player = (mm_player_t*)hplayer;
10192
10193         return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
10194
10195         *state = MMPLAYER_CURRENT_STATE(player);
10196
10197         return MM_ERROR_NONE;
10198 }
10199
10200
10201 int
10202 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
10203 {
10204         mm_player_t* player = (mm_player_t*) hplayer;
10205         GstElement* vol_element = NULL;
10206         int i = 0;
10207
10208         MMPLAYER_FENTER();
10209
10210         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10211
10212         debug_log("volume [L]=%f:[R]=%f\n",
10213                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
10214
10215         /* invalid factor range or not */
10216         for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
10217         {
10218                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
10219                         debug_error("Invalid factor! (valid factor:0~1.0)\n");
10220                         return MM_ERROR_INVALID_ARGUMENT;
10221                 }
10222         }
10223
10224         /* not support to set other value into each channel */
10225         if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
10226                 return MM_ERROR_INVALID_ARGUMENT;
10227
10228         /* Save volume to handle. Currently the first array element will be saved. */
10229         player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
10230
10231         /* check pipeline handle */
10232         if ( ! player->pipeline || ! player->pipeline->audiobin )
10233         {
10234                 debug_log("audiobin is not created yet\n");
10235                 debug_log("but, current stored volume will be set when it's created.\n");
10236
10237                 /* NOTE : stored volume will be used in create_audiobin
10238                  * returning MM_ERROR_NONE here makes application to able to
10239                  * set volume at anytime.
10240                  */
10241                 return MM_ERROR_NONE;
10242         }
10243
10244         /* setting volume to volume element */
10245         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
10246
10247         if ( vol_element )
10248         {
10249                 debug_log("volume is set [%f]\n", player->sound.volume);
10250                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
10251         }
10252
10253         MMPLAYER_FLEAVE();
10254
10255         return MM_ERROR_NONE;
10256 }
10257
10258
10259 int
10260 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
10261 {
10262         mm_player_t* player = (mm_player_t*) hplayer;
10263         int i = 0;
10264
10265         MMPLAYER_FENTER();
10266
10267         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10268         return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
10269
10270         /* returning stored volume */
10271         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
10272                 volume->level[i] = player->sound.volume;
10273
10274         MMPLAYER_FLEAVE();
10275
10276         return MM_ERROR_NONE;
10277 }
10278
10279
10280
10281 int
10282 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
10283 {
10284         mm_player_t* player = (mm_player_t*) hplayer;
10285         GstElement* vol_element = NULL;
10286
10287         MMPLAYER_FENTER();
10288
10289         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10290
10291         /* mute value shoud 0 or 1 */
10292         if ( mute != 0 && mute != 1 )
10293         {
10294                 debug_error("bad mute value\n");
10295
10296                 /* FIXIT : definitly, we need _BAD_PARAM error code */
10297                 return MM_ERROR_INVALID_ARGUMENT;
10298         }
10299
10300         player->sound.mute = mute;
10301
10302         /* just hold mute value if pipeline is not ready */
10303         if ( !player->pipeline || !player->pipeline->audiobin )
10304         {
10305                 debug_log("pipeline is not ready. holding mute value\n");
10306                 return MM_ERROR_NONE;
10307         }
10308
10309         vol_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
10310
10311         /* NOTE : volume will only created when the bt is enabled */
10312         if ( vol_element )
10313         {
10314                 debug_log("mute : %d\n", mute);
10315                 g_object_set(vol_element, "mute", mute, NULL);
10316         }
10317         else
10318         {
10319                 debug_log("volume elemnet is not created. using volume in audiosink\n");
10320         }
10321
10322         MMPLAYER_FLEAVE();
10323
10324         return MM_ERROR_NONE;
10325 }
10326
10327 int
10328 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
10329 {
10330         mm_player_t* player = (mm_player_t*) hplayer;
10331
10332         MMPLAYER_FENTER();
10333
10334         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10335         return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
10336
10337         /* just hold mute value if pipeline is not ready */
10338         if ( !player->pipeline || !player->pipeline->audiobin )
10339         {
10340                 debug_log("pipeline is not ready. returning stored value\n");
10341                 *pmute = player->sound.mute;
10342                 return MM_ERROR_NONE;
10343         }
10344
10345         *pmute = player->sound.mute;
10346
10347         MMPLAYER_FLEAVE();
10348
10349         return MM_ERROR_NONE;
10350 }
10351
10352 int
10353 _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
10354 {
10355         mm_player_t* player = (mm_player_t*) hplayer;
10356
10357         MMPLAYER_FENTER();
10358
10359         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10360
10361         player->video_stream_changed_cb = callback;
10362         player->video_stream_changed_cb_user_param = user_param;
10363         debug_log("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
10364
10365         MMPLAYER_FLEAVE();
10366
10367         return MM_ERROR_NONE;
10368 }
10369
10370 int
10371 _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
10372 {
10373         mm_player_t* player = (mm_player_t*) hplayer;
10374
10375         MMPLAYER_FENTER();
10376
10377         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10378
10379         player->audio_stream_changed_cb = callback;
10380         player->audio_stream_changed_cb_user_param = user_param;
10381         debug_log("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
10382
10383         MMPLAYER_FLEAVE();
10384
10385         return MM_ERROR_NONE;
10386 }
10387
10388 int
10389 _mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param) // @
10390 {
10391         mm_player_t* player = (mm_player_t*) hplayer;
10392
10393         MMPLAYER_FENTER();
10394
10395         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10396
10397         player->audio_stream_render_cb_ex = callback;
10398         player->audio_stream_cb_user_param = user_param;
10399         player->audio_stream_sink_sync = sync;
10400         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);
10401
10402         MMPLAYER_FLEAVE();
10403
10404         return MM_ERROR_NONE;
10405 }
10406
10407 int
10408 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
10409 {
10410         mm_player_t* player = (mm_player_t*) hplayer;
10411
10412         MMPLAYER_FENTER();
10413
10414         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10415
10416         player->video_stream_cb = callback;
10417         player->video_stream_cb_user_param = user_param;
10418         player->use_video_stream = TRUE;
10419         debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
10420
10421         MMPLAYER_FLEAVE();
10422
10423         return MM_ERROR_NONE;
10424 }
10425
10426 int
10427 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
10428 {
10429         mm_player_t* player = (mm_player_t*) hplayer;
10430
10431         MMPLAYER_FENTER();
10432
10433         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10434
10435         player->audio_stream_cb = callback;
10436         player->audio_stream_cb_user_param = user_param;
10437         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
10438
10439         MMPLAYER_FLEAVE();
10440
10441         return MM_ERROR_NONE;
10442 }
10443
10444 // set prepare size
10445 int
10446 _mmplayer_set_prepare_buffering_time(MMHandleType hplayer, int second)
10447 {
10448         mm_player_t* player = (mm_player_t*) hplayer;
10449
10450         MMPLAYER_FENTER();
10451
10452         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10453
10454         if (MMPLAYER_CURRENT_STATE(player) !=  MM_PLAYER_STATE_NULL)
10455                 return MM_ERROR_PLAYER_INVALID_STATE;
10456
10457         debug_log("pre buffer size : %d sec\n", second);
10458
10459         if ( second <= 0 )
10460         {
10461                 debug_error("bad size value\n");
10462                 return MM_ERROR_INVALID_ARGUMENT;
10463         }
10464
10465         if (player->streamer == NULL)
10466         {
10467                 player->streamer = __mm_player_streaming_create();
10468                 __mm_player_streaming_initialize(player->streamer);
10469         }
10470
10471         player->streamer->buffering_req.initial_second = second;
10472
10473         MMPLAYER_FLEAVE();
10474
10475         return MM_ERROR_NONE;
10476 }
10477
10478 // set runtime mode
10479 int
10480 _mmplayer_set_runtime_buffering_mode(MMHandleType hplayer, MMPlayerBufferingMode mode, int second)
10481 {
10482         mm_player_t* player = (mm_player_t*) hplayer;
10483
10484         MMPLAYER_FENTER();
10485
10486         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10487
10488         debug_log("mode %d\n", mode);
10489
10490         if ((mode < 0) || (mode > MM_PLAYER_BUFFERING_MODE_MAX) ||
10491                 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) && (second <= 0)))
10492                 return MM_ERROR_INVALID_ARGUMENT;
10493
10494         if (player->streamer == NULL)
10495         {
10496                 player->streamer = __mm_player_streaming_create();
10497                 __mm_player_streaming_initialize(player->streamer);
10498         }
10499
10500         player->streamer->buffering_req.mode = mode;
10501
10502         if ((second > 0) &&
10503                 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) ||
10504                  (mode == MM_PLAYER_BUFFERING_MODE_ADAPTIVE)))
10505                 player->streamer->buffering_req.runtime_second = second;
10506
10507         MMPLAYER_FLEAVE();
10508
10509         return MM_ERROR_NONE;
10510 }
10511
10512 int
10513 _mmplayer_set_videoframe_render_error_cb(MMHandleType hplayer, mm_player_video_frame_render_error_callback callback, void *user_param) // @
10514 {
10515         mm_player_t* player = (mm_player_t*) hplayer;
10516
10517         MMPLAYER_FENTER();
10518
10519         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10520         return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
10521
10522         player->video_frame_render_error_cb = callback;
10523         player->video_frame_render_error_cb_user_param = user_param;
10524
10525         debug_log("Video frame render error cb Handle value is %p : %p\n", player, player->video_frame_render_error_cb);
10526
10527         MMPLAYER_FLEAVE();
10528
10529         return MM_ERROR_NONE;
10530 }
10531
10532 int
10533 __mmplayer_start_streaming_ext(mm_player_t *player)
10534 {
10535         gint ret = MM_ERROR_NONE;
10536
10537         MMPLAYER_FENTER();
10538         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10539
10540         if (MMPLAYER_IS_HTTP_PD(player))
10541         {
10542                 if ( !player->pd_downloader )
10543                 {
10544                         ret = __mmplayer_realize_streaming_ext(player);
10545
10546                         if ( ret != MM_ERROR_NONE)
10547                         {
10548                                 debug_error ("failed to realize streaming ext\n");
10549                                 return ret;
10550                         }
10551                 }
10552
10553                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
10554                 {
10555                         ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
10556                         if ( !ret )
10557                         {
10558                                 debug_error ("ERROR while starting PD...\n");
10559                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
10560                         }
10561                         ret = MM_ERROR_NONE;
10562                 }
10563         }
10564
10565         MMPLAYER_FLEAVE();
10566         return ret;
10567 }
10568
10569 int
10570 _mmplayer_start(MMHandleType hplayer) // @
10571 {
10572         mm_player_t* player = (mm_player_t*) hplayer;
10573         gint ret = MM_ERROR_NONE;
10574
10575         MMPLAYER_FENTER();
10576
10577         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10578
10579         /* check current state */
10580         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
10581
10582         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
10583         if ( ret != MM_ERROR_NONE )
10584         {
10585                 debug_error("failed to set asm state to PLAYING\n");
10586                 return ret;
10587         }
10588
10589         /* NOTE : we should check and create pipeline again if not created as we destroy
10590          * whole pipeline when stopping in streamming playback
10591          */
10592         if ( ! player->pipeline )
10593         {
10594                 ret = __gst_realize( player );
10595                 if ( MM_ERROR_NONE != ret )
10596                 {
10597                         debug_error("failed to realize before starting. only in streamming\n");
10598                         /* unlock */
10599                         return ret;
10600                 }
10601         }
10602
10603         ret = __mmplayer_start_streaming_ext(player);
10604         if ( ret != MM_ERROR_NONE )
10605         {
10606                 debug_error("failed to start streaming ext \n");
10607         }
10608
10609         /* start pipeline */
10610         ret = __gst_start( player );
10611         if ( ret != MM_ERROR_NONE )
10612         {
10613                 debug_error("failed to start player.\n");
10614         }
10615
10616         MMPLAYER_FLEAVE();
10617
10618         return ret;
10619 }
10620
10621 /* NOTE: post "not supported codec message" to application
10622  * when one codec is not found during AUTOPLUGGING in MSL.
10623  * So, it's separated with error of __mmplayer_gst_callback().
10624  * And, if any codec is not found, don't send message here.
10625  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
10626  */
10627 int
10628 __mmplayer_handle_missed_plugin(mm_player_t* player)
10629 {
10630         MMMessageParamType msg_param;
10631         memset (&msg_param, 0, sizeof(MMMessageParamType));
10632         gboolean post_msg_direct = FALSE;
10633
10634         MMPLAYER_FENTER();
10635
10636         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10637
10638         debug_log("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
10639                         player->not_supported_codec, player->can_support_codec);
10640
10641         if( player->not_found_demuxer )
10642         {
10643                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
10644                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
10645
10646                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10647                 MMPLAYER_FREEIF(msg_param.data);
10648
10649                 return MM_ERROR_NONE;
10650         }
10651
10652         if (player->not_supported_codec)
10653         {
10654                 if ( player->can_support_codec ) // There is one codec to play
10655                 {
10656                         post_msg_direct = TRUE;
10657                 }
10658                 else
10659                 {
10660                         if ( player->pipeline->audiobin ) // Some content has only PCM data in container.
10661                                 post_msg_direct = TRUE;
10662                 }
10663
10664                 if ( post_msg_direct )
10665                 {
10666                         MMMessageParamType msg_param;
10667                         memset (&msg_param, 0, sizeof(MMMessageParamType));
10668
10669                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
10670                         {
10671                                 debug_warning("not found AUDIO codec, posting error code to application.\n");
10672
10673                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
10674                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
10675                         }
10676                         else if ( player->not_supported_codec ==  MISSING_PLUGIN_VIDEO )
10677                         {
10678                                 debug_warning("not found VIDEO codec, posting error code to application.\n");
10679
10680                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
10681                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
10682                         }
10683
10684                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10685
10686                         MMPLAYER_FREEIF(msg_param.data);
10687
10688                         return MM_ERROR_NONE;
10689                 }
10690                 else // no any supported codec case
10691                 {
10692                         debug_warning("not found any codec, posting error code to application.\n");
10693
10694                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
10695                         {
10696                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
10697                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
10698                         }
10699                         else
10700                         {
10701                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
10702                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
10703                         }
10704
10705                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10706
10707                         MMPLAYER_FREEIF(msg_param.data);
10708                 }
10709         }
10710
10711         MMPLAYER_FLEAVE();
10712
10713         return MM_ERROR_NONE;
10714 }
10715
10716 static void __mmplayer_check_pipeline(mm_player_t* player)
10717 {
10718         GstState element_state = GST_STATE_VOID_PENDING;
10719         GstState element_pending_state = GST_STATE_VOID_PENDING;
10720         gint timeout = 0;
10721         int ret = MM_ERROR_NONE;
10722
10723         if (player->gapless.reconfigure)
10724         {
10725                 debug_warning("pipeline is under construction.\n");
10726
10727                 MMPLAYER_PLAYBACK_LOCK(player);
10728                 MMPLAYER_PLAYBACK_UNLOCK(player);
10729
10730                 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
10731
10732                 /* wait for state transition */
10733                 ret = gst_element_get_state( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND );
10734
10735                 if ( ret == GST_STATE_CHANGE_FAILURE )
10736                 {
10737                         debug_error("failed to change pipeline state within %d sec\n", timeout );
10738                 }
10739         }
10740 }
10741
10742 /* NOTE : it should be able to call 'stop' anytime*/
10743 int
10744 _mmplayer_stop(MMHandleType hplayer) // @
10745 {
10746         mm_player_t* player = (mm_player_t*)hplayer;
10747         int ret = MM_ERROR_NONE;
10748
10749         MMPLAYER_FENTER();
10750
10751         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10752
10753         /* check current state */
10754         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
10755
10756         /* check pipline building state */
10757         __mmplayer_check_pipeline(player);
10758         player->gapless.start_time = 0;
10759
10760         /* NOTE : application should not wait for EOS after calling STOP */
10761         __mmplayer_cancel_eos_timer( player );
10762
10763         __mmplayer_unrealize_streaming_ext(player);
10764
10765         /* reset */
10766         player->doing_seek = FALSE;
10767
10768         /* stop pipeline */
10769         ret = __gst_stop( player );
10770
10771         if ( ret != MM_ERROR_NONE )
10772         {
10773                 debug_error("failed to stop player.\n");
10774         }
10775
10776         MMPLAYER_FLEAVE();
10777
10778         return ret;
10779 }
10780
10781 int
10782 _mmplayer_pause(MMHandleType hplayer) // @
10783 {
10784         mm_player_t* player = (mm_player_t*)hplayer;
10785         gint64 pos_msec = 0;
10786         gboolean async = FALSE;
10787         gint ret = MM_ERROR_NONE;
10788
10789         MMPLAYER_FENTER();
10790
10791         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10792
10793         /* check current state */
10794         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
10795
10796         /* check pipline building state */
10797         __mmplayer_check_pipeline(player);
10798
10799         switch (MMPLAYER_CURRENT_STATE(player))
10800         {
10801                 case MM_PLAYER_STATE_READY:
10802                 {
10803                         /* check prepare async or not.
10804                          * In the case of streaming playback, it's recommned to avoid blocking wait.
10805                          */
10806                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10807                         debug_log("prepare working mode : %s", (async ? "async" : "sync"));
10808                 }
10809                 break;
10810
10811                 case MM_PLAYER_STATE_PLAYING:
10812                 {
10813                         /* NOTE : store current point to overcome some bad operation
10814                         * ( returning zero when getting current position in paused state) of some
10815                         * elements
10816                         */
10817                         if ( !gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec))
10818                                 debug_warning("getting current position failed in paused\n");
10819
10820                         player->last_position = pos_msec;
10821                 }
10822                 break;
10823         }
10824
10825         /* pause pipeline */
10826         ret = __gst_pause( player, async );
10827
10828         if ( ret != MM_ERROR_NONE )
10829         {
10830                 debug_error("failed to pause player. ret : 0x%x\n", ret);
10831         }
10832
10833         MMPLAYER_FLEAVE();
10834
10835         return ret;
10836 }
10837
10838 int
10839 _mmplayer_resume(MMHandleType hplayer)
10840 {
10841         mm_player_t* player = (mm_player_t*)hplayer;
10842         int ret = MM_ERROR_NONE;
10843         gboolean async = FALSE;
10844
10845         MMPLAYER_FENTER();
10846
10847         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10848
10849         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
10850         if ( ret )
10851         {
10852                 debug_error("failed to set asm state to PLAYING\n");
10853                 return ret;
10854         }
10855
10856         /* check current state */
10857         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
10858
10859         ret = __gst_resume( player, async );
10860
10861         if ( ret != MM_ERROR_NONE )
10862         {
10863                 debug_error("failed to resume player.\n");
10864         }
10865
10866         MMPLAYER_FLEAVE();
10867
10868         return ret;
10869 }
10870
10871 int
10872 __mmplayer_set_play_count(mm_player_t* player, gint count)
10873 {
10874         MMHandleType attrs = 0;
10875
10876         MMPLAYER_FENTER();
10877
10878         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10879
10880         attrs =  MMPLAYER_GET_ATTRS(player);
10881         if ( !attrs )
10882         {
10883                 debug_error("fail to get attributes.\n");
10884                 return MM_ERROR_PLAYER_INTERNAL;
10885         }
10886
10887         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
10888         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
10889                 debug_error("failed to commit\n");
10890
10891         MMPLAYER_FLEAVE();
10892
10893         return  MM_ERROR_NONE;
10894 }
10895
10896 int
10897 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
10898 {
10899         mm_player_t* player = (mm_player_t*)hplayer;
10900         gint64 start_pos = 0;
10901         gint64 end_pos = 0;
10902         gint infinity = -1;
10903
10904         MMPLAYER_FENTER();
10905
10906         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10907         return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
10908
10909         player->section_repeat = TRUE;
10910         player->section_repeat_start = start;
10911         player->section_repeat_end = end;
10912
10913         start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
10914         end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
10915
10916         __mmplayer_set_play_count( player, infinity );
10917
10918         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10919                                         player->playback_rate,
10920                                         GST_FORMAT_TIME,
10921                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10922                                         GST_SEEK_TYPE_SET, start_pos,
10923                                         GST_SEEK_TYPE_SET, end_pos)))
10924         {
10925                 debug_error("failed to activate section repeat\n");
10926
10927                 return MM_ERROR_PLAYER_SEEK;
10928         }
10929
10930         debug_log("succeeded to set section repeat from %d to %d\n",
10931                 player->section_repeat_start, player->section_repeat_end);
10932
10933         MMPLAYER_FLEAVE();
10934
10935         return  MM_ERROR_NONE;
10936 }
10937
10938 static int
10939 __mmplayer_set_pcm_extraction(mm_player_t* player)
10940 {
10941         gint64 start_nsec = 0;
10942         gint64 end_nsec = 0;
10943         gint64 dur_nsec = 0;
10944         gint64 dur_msec = 0;
10945         int required_start = 0;
10946         int required_end = 0;
10947         int ret = 0;
10948
10949         MMPLAYER_FENTER();
10950
10951         return_val_if_fail( player, FALSE );
10952
10953         mm_attrs_multiple_get(player->attrs,
10954                 NULL,
10955                 "pcm_extraction_start_msec", &required_start,
10956                 "pcm_extraction_end_msec", &required_end,
10957                 NULL);
10958
10959         debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
10960
10961         if (required_start == 0 && required_end == 0)
10962         {
10963                 debug_log("extracting entire stream");
10964                 return MM_ERROR_NONE;
10965         }
10966         else if (required_start < 0 || required_start > required_end || required_end < 0 )
10967         {
10968                 debug_log("invalid range for pcm extraction");
10969                 return MM_ERROR_INVALID_ARGUMENT;
10970         }
10971
10972         /* get duration */
10973         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
10974         if ( !ret )
10975         {
10976                 debug_error("failed to get duration");
10977                 return MM_ERROR_PLAYER_INTERNAL;
10978         }
10979         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
10980
10981         if (dur_msec < required_end) // FIXME
10982         {
10983                 debug_log("invalid end pos for pcm extraction");
10984                 return MM_ERROR_INVALID_ARGUMENT;
10985         }
10986
10987         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
10988         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
10989
10990         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10991                                         1.0,
10992                                         GST_FORMAT_TIME,
10993                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10994                                         GST_SEEK_TYPE_SET, start_nsec,
10995                                         GST_SEEK_TYPE_SET, end_nsec)))
10996         {
10997                 debug_error("failed to seek for pcm extraction\n");
10998
10999                 return MM_ERROR_PLAYER_SEEK;
11000         }
11001
11002         debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
11003
11004         MMPLAYER_FLEAVE();
11005
11006         return MM_ERROR_NONE;
11007 }
11008
11009 int
11010 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
11011 {
11012         mm_player_t* player = (mm_player_t*)hplayer;
11013         gint64 cur_pos = 0;
11014         gint onetime = 1;
11015
11016         MMPLAYER_FENTER();
11017
11018         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11019
11020         player->section_repeat = FALSE;
11021
11022         __mmplayer_set_play_count( player, onetime );
11023
11024         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_pos);
11025
11026         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
11027                                         1.0,
11028                                         GST_FORMAT_TIME,
11029                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
11030                                         GST_SEEK_TYPE_SET, cur_pos,
11031                                         GST_SEEK_TYPE_SET, player->duration )))
11032         {
11033                 debug_error("failed to deactivate section repeat\n");
11034
11035                 return MM_ERROR_PLAYER_SEEK;
11036         }
11037
11038         MMPLAYER_FENTER();
11039
11040         return MM_ERROR_NONE;
11041 }
11042
11043 int
11044 _mmplayer_set_playspeed(MMHandleType hplayer, float rate)
11045 {
11046         mm_player_t* player = (mm_player_t*)hplayer;
11047         signed long long pos_msec = 0;
11048         int ret = MM_ERROR_NONE;
11049         int mute = FALSE;
11050         signed long long start = 0, stop = 0;
11051         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
11052         MMPLAYER_FENTER();
11053
11054         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
11055         return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
11056
11057         /* The sound of video is not supported under 0.0 and over 2.0. */
11058         if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
11059         {
11060                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
11061                         mute = TRUE;
11062         }
11063         _mmplayer_set_mute(hplayer, mute);
11064
11065         if (player->playback_rate == rate)
11066                 return MM_ERROR_NONE;
11067
11068         /* If the position is reached at start potion during fast backward, EOS is posted.
11069          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
11070          * */
11071         player->playback_rate = rate;
11072
11073         current_state = MMPLAYER_CURRENT_STATE(player);
11074
11075         if ( current_state != MM_PLAYER_STATE_PAUSED )
11076                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
11077
11078         debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
11079
11080         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
11081                 || ( ! ret ))
11082                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
11083         {
11084                 debug_warning("returning last point : %lld\n", player->last_position );
11085                 pos_msec = player->last_position;
11086         }
11087
11088
11089         if(rate >= 0)
11090         {
11091                 start = pos_msec;
11092                 stop = GST_CLOCK_TIME_NONE;
11093         }
11094         else
11095         {
11096                 start = GST_CLOCK_TIME_NONE;
11097                 stop = pos_msec;
11098         }
11099         if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
11100                                 rate,
11101                                 GST_FORMAT_TIME,
11102                                 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
11103                                 GST_SEEK_TYPE_SET, start,
11104                                 GST_SEEK_TYPE_SET, stop)))
11105         {
11106                 debug_error("failed to set speed playback\n");
11107                 return MM_ERROR_PLAYER_SEEK;
11108         }
11109
11110         debug_log("succeeded to set speed playback as %0.1f\n", rate);
11111
11112         MMPLAYER_FLEAVE();
11113
11114         return MM_ERROR_NONE;;
11115 }
11116
11117 int
11118 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
11119 {
11120         mm_player_t* player = (mm_player_t*)hplayer;
11121         int ret = MM_ERROR_NONE;
11122
11123         MMPLAYER_FENTER();
11124
11125         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11126
11127         ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
11128
11129         MMPLAYER_FLEAVE();
11130
11131         return ret;
11132 }
11133
11134 int
11135 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
11136 {
11137         mm_player_t* player = (mm_player_t*)hplayer;
11138         int ret = MM_ERROR_NONE;
11139
11140         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11141
11142         ret = __gst_get_position ( player, format, position );
11143
11144         return ret;
11145 }
11146
11147 int
11148 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
11149 {
11150         mm_player_t* player = (mm_player_t*)hplayer;
11151         int ret = MM_ERROR_NONE;
11152
11153         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11154
11155         ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
11156
11157         return ret;
11158 }
11159
11160 int
11161 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
11162 {
11163         mm_player_t* player = (mm_player_t*)hplayer;
11164         int ret = MM_ERROR_NONE;
11165
11166         MMPLAYER_FENTER();
11167
11168         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11169
11170         ret = __gst_adjust_subtitle_position(player, format, position);
11171
11172         MMPLAYER_FLEAVE();
11173
11174         return ret;
11175 }
11176 int
11177 _mmplayer_adjust_video_postion(MMHandleType hplayer, int offset) // @
11178 {
11179         mm_player_t* player = (mm_player_t*)hplayer;
11180         int ret = MM_ERROR_NONE;
11181
11182         MMPLAYER_FENTER();
11183
11184         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11185
11186         ret = __gst_adjust_video_position(player, offset);
11187
11188         MMPLAYER_FLEAVE();
11189
11190         return ret;
11191 }
11192
11193 static gboolean
11194 __mmplayer_is_midi_type( gchar* str_caps)
11195 {
11196         if ( ( g_strrstr(str_caps, "audio/midi") ) ||
11197                 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
11198                 ( g_strrstr(str_caps, "application/x-smaf") ) ||
11199                 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
11200                 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
11201                 ( g_strrstr(str_caps, "audio/xmf") ) ||
11202                 ( g_strrstr(str_caps, "audio/mxmf") ) )
11203         {
11204                 debug_log("midi\n");
11205
11206                 return TRUE;
11207         }
11208
11209         return FALSE;
11210 }
11211
11212 static gboolean
11213 __mmplayer_is_only_mp3_type (gchar *str_caps)
11214 {
11215         if (g_strrstr(str_caps, "application/x-id3") ||
11216                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
11217         {
11218                 return TRUE;
11219         }
11220         return FALSE;
11221 }
11222
11223 static void
11224 __mmplayer_set_audio_attrs (mm_player_t* player, GstCaps* caps)
11225 {
11226         GstStructure* caps_structure = NULL;
11227         gint samplerate = 0;
11228         gint channels = 0;
11229
11230         MMPLAYER_FENTER();
11231         return_if_fail (player && caps);
11232
11233         caps_structure = gst_caps_get_structure(caps, 0);
11234
11235         /* set stream information */
11236         gst_structure_get_int (caps_structure, "rate", &samplerate);
11237         mm_attrs_set_int_by_name (player->attrs, "content_audio_samplerate", samplerate);
11238
11239         gst_structure_get_int (caps_structure, "channels", &channels);
11240         mm_attrs_set_int_by_name (player->attrs, "content_audio_channels", channels);
11241
11242         debug_log ("audio samplerate : %d       channels : %d\n", samplerate, channels);
11243 }
11244
11245 static void
11246 __mmplayer_update_content_type_info(mm_player_t* player)
11247 {
11248         MMPLAYER_FENTER();
11249         return_if_fail( player && player->type);
11250
11251         if (__mmplayer_is_midi_type(player->type))
11252         {
11253                 player->bypass_audio_effect = TRUE;
11254         }
11255         else if (g_strrstr(player->type, "application/x-hls"))
11256         {
11257                 /* If it can't know exact type when it parses uri because of redirection case,
11258                  * it will be fixed by typefinder or when doing autoplugging.
11259                  */
11260                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
11261                 if (player->streamer)
11262                 {
11263                         player->streamer->is_adaptive_streaming = TRUE;
11264                         player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
11265                         player->streamer->buffering_req.runtime_second = 5;
11266                 }
11267         }
11268         else if (g_strrstr(player->type, "application/dash+xml"))
11269         {
11270                 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
11271         }
11272
11273         MMPLAYER_FLEAVE();
11274 }
11275
11276 static void
11277 __mmplayer_typefind_have_type(  GstElement *tf, guint probability,  // @
11278 GstCaps *caps, gpointer data)
11279 {
11280         mm_player_t* player = (mm_player_t*)data;
11281         GstPad* pad = NULL;
11282
11283         MMPLAYER_FENTER();
11284
11285         return_if_fail( player && tf && caps );
11286
11287         /* store type string */
11288         MMPLAYER_FREEIF(player->type);
11289         player->type = gst_caps_to_string(caps);
11290         if (player->type)
11291                 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
11292
11293         if ( (!MMPLAYER_IS_WFD_STREAMING( player )) &&
11294                  (!MMPLAYER_IS_RTSP_STREAMING( player )) &&
11295                  (g_strrstr(player->type, "audio/x-raw-int")))
11296         {
11297                 debug_error("not support media format\n");
11298
11299                 if (player->msg_posted == FALSE)
11300                 {
11301                         MMMessageParamType msg_param;
11302                         memset (&msg_param, 0, sizeof(MMMessageParamType));
11303
11304                         msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
11305                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
11306
11307                         /* don't post more if one was sent already */
11308                         player->msg_posted = TRUE;
11309                 }
11310                 return;
11311         }
11312
11313         __mmplayer_update_content_type_info(player);
11314
11315         pad = gst_element_get_static_pad(tf, "src");
11316         if ( !pad )
11317         {
11318                 debug_error("fail to get typefind src pad.\n");
11319                 return;
11320         }
11321
11322         if (player->use_decodebin)
11323         {
11324                 if(!__mmplayer_try_to_plug_decodebin( player, pad, caps ))
11325                 {
11326                         gboolean async = FALSE;
11327                         debug_error("failed to autoplug %s\n", player->type);
11328
11329                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
11330
11331                         if ( async && player->msg_posted == FALSE )
11332                         {
11333                                 __mmplayer_handle_missed_plugin( player );
11334                         }
11335
11336                         goto DONE;
11337                 }
11338         }
11339         else
11340         {
11341                 /* try to plug */
11342                 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
11343                 {
11344                         gboolean async = FALSE;
11345                         debug_error("failed to autoplug %s\n", player->type);
11346
11347                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
11348
11349                         if ( async && player->msg_posted == FALSE )
11350                         {
11351                                 __mmplayer_handle_missed_plugin( player );
11352                         }
11353
11354                         goto DONE;
11355                 }
11356
11357                 /* finish autopluging if no dynamic pad waiting */
11358                 if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
11359                 {
11360                         if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
11361                         {
11362                                 __mmplayer_pipeline_complete( NULL, (gpointer)player );
11363                         }
11364                 }
11365         }
11366
11367 DONE:
11368         gst_object_unref( GST_OBJECT(pad) );
11369
11370         MMPLAYER_FLEAVE();
11371
11372         return;
11373 }
11374
11375 #ifdef _MM_PLAYER_ALP_PARSER
11376 void check_name (void *data, void *user_data)
11377 {
11378         mm_player_t* player = user_data;
11379
11380         if (g_strrstr((gchar*)data, "mpegaudioparse"))
11381         {
11382                 debug_log("mpegaudioparse - set alp-mp3dec\n");
11383                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "alp-mp3dec", TRUE, NULL);
11384         }
11385 }
11386 #endif
11387
11388 static GstElement *
11389 __mmplayer_create_decodebin (mm_player_t* player)
11390 {
11391         GstElement *decodebin = NULL;
11392
11393         MMPLAYER_FENTER();
11394
11395         /* create decodebin */
11396         decodebin = gst_element_factory_make("decodebin", NULL);
11397
11398         if (!decodebin)
11399         {
11400                 debug_error("fail to create decodebin\n");
11401                 goto ERROR;
11402         }
11403
11404         /* raw pad handling signal */
11405         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
11406                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
11407
11408         /* no-more-pad pad handling signal */
11409         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
11410                                                 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
11411
11412         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
11413                                                 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
11414
11415         /* This signal is emitted when a pad for which there is no further possible
11416            decoding is added to the decodebin.*/
11417         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
11418                                                 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player );
11419
11420         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
11421            before looking for any elements that can handle that stream.*/
11422         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
11423                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
11424
11425         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
11426            before looking for any elements that can handle that stream.*/
11427         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
11428                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
11429
11430         /* This signal is emitted once decodebin has finished decoding all the data.*/
11431         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
11432                                                 G_CALLBACK(__mmplayer_gst_decode_drained), player);
11433
11434         /* This signal is emitted when a element is added to the bin.*/
11435         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
11436                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
11437
11438 ERROR:
11439         return decodebin;
11440 }
11441
11442 static gboolean
11443 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
11444 {
11445         MMPlayerGstElement* mainbin = NULL;
11446         GstElement* decodebin = NULL;
11447         GstElement* queue2 = NULL;
11448         GstPad* sinkpad = NULL;
11449         GstPad* qsrcpad= NULL;
11450         gchar *caps_str = NULL;
11451         gint64 dur_bytes = 0L;
11452         gchar* file_buffering_path = NULL;
11453         gboolean use_file_buffer = FALSE;
11454
11455         guint max_buffer_size_bytes = 0;
11456         gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
11457
11458         MMPLAYER_FENTER();
11459         return_val_if_fail (player && player->pipeline && player->pipeline->mainbin, FALSE);
11460
11461         mainbin = player->pipeline->mainbin;
11462
11463         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
11464                 (MMPLAYER_IS_HTTP_STREAMING(player)))
11465         {
11466                 debug_log ("creating http streaming buffering queue (queue2)\n");
11467
11468                 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
11469                 {
11470                         debug_error ("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
11471                 }
11472                 else
11473             {
11474                         queue2 = gst_element_factory_make ("queue2", "queue2");
11475                         if (!queue2)
11476                         {
11477                                 debug_error ("failed to create buffering queue element\n");
11478                                 goto ERROR;
11479                         }
11480
11481                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2))
11482                         {
11483                                 debug_error("failed to add buffering queue\n");
11484                                 goto ERROR;
11485                         }
11486
11487                         sinkpad = gst_element_get_static_pad(queue2, "sink");
11488                         qsrcpad = gst_element_get_static_pad(queue2, "src");
11489
11490                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11491                         {
11492                                 debug_error("failed to link buffering queue\n");
11493                                 goto ERROR;
11494                         }
11495
11496                         // if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
11497                         {
11498                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
11499                                         debug_error("fail to get duration.\n");
11500
11501                                 debug_log("dur_bytes = %lld\n", dur_bytes);
11502
11503                                 if (dur_bytes > 0)
11504                                 {
11505                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
11506                                         file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
11507                                 }
11508                                 else
11509                                 {
11510                                         dur_bytes = 0;
11511                                 }
11512                         }
11513
11514                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
11515                         // if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
11516                         if(!g_strrstr(player->type, "video/mpegts"))
11517                         {
11518                                 max_buffer_size_bytes = (use_file_buffer)?(player->ini.http_max_size_bytes):(5*1024*1024);
11519                                 debug_log("max_buffer_size_bytes = %d\n", max_buffer_size_bytes);
11520
11521                                 __mm_player_streaming_set_queue2(player->streamer,
11522                                                                                                 queue2,
11523                                                                                                 FALSE,
11524                                                                                                 max_buffer_size_bytes,
11525                                                                                                 player->ini.http_buffering_time,
11526                                                                                                 1.0,                                                            // no meaning
11527                                                                                                 player->ini.http_buffering_limit,       // no meaning
11528                                                                                                 use_file_buffer,
11529                                                                                                 file_buffering_path,
11530                                                                                                 (guint64)dur_bytes);
11531                         }
11532
11533                         MMPLAYER_FREEIF(file_buffering_path);
11534                         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (queue2))
11535                         {
11536                                 debug_error("failed to sync queue2 state with parent\n");
11537                                 goto ERROR;
11538                         }
11539
11540                         srcpad = qsrcpad;
11541
11542                         gst_object_unref(GST_OBJECT(sinkpad));
11543
11544                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
11545                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
11546                 }
11547         }
11548
11549         /* create decodebin */
11550         decodebin = __mmplayer_create_decodebin(player);
11551
11552         if (!decodebin)
11553         {
11554                 debug_error("can not create autoplug element\n");
11555                 goto ERROR;
11556         }
11557
11558         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin))
11559         {
11560                 debug_error("failed to add decodebin\n");
11561                 goto ERROR;
11562         }
11563
11564         /* to force caps on the decodebin element and avoid reparsing stuff by
11565         * typefind. It also avoids a deadlock in the way typefind activates pads in
11566         * the state change */
11567         g_object_set (decodebin, "sink-caps", caps, NULL);
11568
11569         sinkpad = gst_element_get_static_pad(decodebin, "sink");
11570
11571         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11572         {
11573                 debug_error("failed to link decodebin\n");
11574                 goto ERROR;
11575         }
11576
11577         gst_object_unref(GST_OBJECT(sinkpad));
11578
11579         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
11580         mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin;
11581
11582         /* set decodebin property about buffer in streaming playback. *
11583          * in case of hls, it does not need to have big buffer        *
11584          * because it is kind of adaptive streaming.                  */
11585         if ( ((!MMPLAYER_IS_HTTP_PD(player)) &&
11586             (MMPLAYER_IS_HTTP_STREAMING(player))) || MMPLAYER_IS_DASH_STREAMING (player))
11587         {
11588                 guint max_size_bytes = MAX_DECODEBIN_BUFFER_BYTES;
11589                 guint64 max_size_time = MAX_DECODEBIN_BUFFER_TIME;
11590                 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
11591
11592                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {
11593                         max_size_bytes = MAX_DECODEBIN_ADAPTIVE_BUFFER_BYTES;
11594                         max_size_time = MAX_DECODEBIN_ADAPTIVE_BUFFER_TIME;
11595                 }
11596
11597                 g_object_set (G_OBJECT(decodebin), "use-buffering", TRUE,
11598                                                                                         "high-percent", (gint)player->ini.http_buffering_limit,
11599                                                                                         "low-percent", 1,   // 1%
11600                                                                                         "max-size-bytes", max_size_bytes,
11601                                                                                         "max-size-time", (guint64)(max_size_time * GST_SECOND),
11602                                                                                         "max-size-buffers", 0, NULL);  // disable or automatic
11603         }
11604
11605         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin))
11606         {
11607                 debug_error("failed to sync decodebin state with parent\n");
11608                 goto ERROR;
11609         }
11610
11611         MMPLAYER_FLEAVE();
11612
11613         return TRUE;
11614
11615 ERROR:
11616
11617         MMPLAYER_FREEIF( caps_str );
11618
11619         if (sinkpad)
11620                 gst_object_unref(GST_OBJECT(sinkpad));
11621
11622         if (queue2)
11623         {
11624                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
11625                  * You need to explicitly set elements to the NULL state before
11626                  * dropping the final reference, to allow them to clean up.
11627                  */
11628                 gst_element_set_state(queue2, GST_STATE_NULL);
11629
11630                 /* And, it still has a parent "player".
11631                  * You need to let the parent manage the object instead of unreffing the object directly.
11632                  */
11633                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
11634                 gst_object_unref (queue2);
11635                 queue2 = NULL;
11636         }
11637
11638         if (decodebin)
11639         {
11640                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
11641                  * You need to explicitly set elements to the NULL state before
11642                  * dropping the final reference, to allow them to clean up.
11643                  */
11644                 gst_element_set_state(decodebin, GST_STATE_NULL);
11645
11646                 /* And, it still has a parent "player".
11647                  * You need to let the parent manage the object instead of unreffing the object directly.
11648                  */
11649
11650                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
11651                 gst_object_unref (decodebin);
11652                 decodebin = NULL;
11653         }
11654
11655         return FALSE;
11656 }
11657
11658 /* it will return first created element */
11659 static gboolean
11660 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
11661 {
11662         MMPlayerGstElement* mainbin = NULL;
11663         const char* mime = NULL;
11664         const GList* item = NULL;
11665         const gchar* klass = NULL;
11666         GstCaps* res = NULL;
11667         gboolean skip = FALSE;
11668         GstPad* queue_pad = NULL;
11669         GstElement* queue = NULL;
11670         GstElement *element = NULL;
11671
11672         MMPLAYER_FENTER();
11673
11674         return_val_if_fail( player && player->pipeline && player->pipeline->mainbin, FALSE );
11675
11676         mainbin = player->pipeline->mainbin;
11677
11678         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
11679
11680         /* return if we got raw output */
11681         if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
11682                 || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup"))
11683         {
11684
11685                 element = (GstElement*)gst_pad_get_parent(pad);
11686 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
11687  * No queue will be added. I think it can caused breaking sound when playing raw audio
11688  * frames but there's no different. Decodebin also doesn't add with those wav fils.
11689  * Anyway, currentely raw-queue seems not necessary.
11690  */
11691 #if 1
11692                 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
11693                  * has linked. if so, we need to add queue for quality of output. note that
11694                  * decodebin also has same problem.
11695                  */
11696                 klass = gst_element_factory_get_klass( gst_element_get_factory(element) );
11697
11698                 /* add queue if needed */
11699                 if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
11700                         || g_strrstr(klass, "Parse")) &&  !g_str_has_prefix(mime, "text"))
11701                 {
11702                         debug_log("adding raw queue\n");
11703
11704                         queue = gst_element_factory_make("queue", NULL);
11705                         if ( ! queue )
11706                         {
11707                                 debug_warning("failed to create queue\n");
11708                                 goto ERROR;
11709                         }
11710
11711                         /* warmup */
11712                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
11713                         {
11714                                 debug_warning("failed to set state READY to queue\n");
11715                                 goto ERROR;
11716                         }
11717
11718                         /* add to pipeline */
11719                         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
11720                         {
11721                                 debug_warning("failed to add queue\n");
11722                                 goto ERROR;
11723                         }
11724
11725                         /* link queue */
11726                         queue_pad = gst_element_get_static_pad(queue, "sink");
11727
11728                         if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
11729                         {
11730                                 debug_warning("failed to link queue\n");
11731                                 goto ERROR;
11732                         }
11733                         gst_object_unref ( GST_OBJECT(queue_pad) );
11734                         queue_pad = NULL;
11735
11736                         /* running */
11737                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
11738                         {
11739                                 debug_warning("failed to set state READY to queue\n");
11740                                 goto ERROR;
11741                         }
11742
11743                         /* replace given pad to queue:src */
11744                         pad = gst_element_get_static_pad(queue, "src");
11745                         if ( ! pad )
11746                         {
11747                                 debug_warning("failed to get pad from queue\n");
11748                                 goto ERROR;
11749                         }
11750                 }
11751 #endif
11752                 /* check if player can do start continually */
11753                 MMPLAYER_CHECK_CMD_IF_EXIT(player);
11754
11755                 if(__mmplayer_link_sink(player,pad))
11756                         __mmplayer_gst_decode_callback(element, pad, player);
11757
11758                 gst_object_unref( GST_OBJECT(element));
11759                 element = NULL;
11760
11761                 return TRUE;
11762         }
11763
11764         item = player->factories;
11765         for(; item != NULL ; item = item->next)
11766         {
11767                 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
11768                 const GList *pads;
11769                 gint idx = 0;
11770
11771                 skip = FALSE;
11772
11773                 /* filtering exclude keyword */
11774                 for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
11775                 {
11776                         if ( g_strrstr(GST_OBJECT_NAME (factory),
11777                                         player->ini.exclude_element_keyword[idx] ) )
11778                         {
11779                                 debug_warning("skipping [%s] by exculde keyword [%s]\n",
11780                                         GST_OBJECT_NAME (factory),
11781                                         player->ini.exclude_element_keyword[idx] );
11782
11783                                 skip = TRUE;
11784                                 break;
11785                         }
11786                 }
11787
11788                 if ( MMPLAYER_IS_RTSP_STREAMING(player) && g_strrstr(GST_OBJECT_NAME (factory), "omx_mpeg4dec"))
11789                 {
11790                         // omx decoder can not support mpeg4video data partitioned
11791                         // rtsp streaming didn't know mpeg4video data partitioned format
11792                         // so, if rtsp playback, player will skip omx_mpeg4dec.
11793                         debug_warning("skipping [%s] when rtsp streaming \n",
11794                                         GST_OBJECT_NAME (factory));
11795
11796                         skip = TRUE;
11797                 }
11798
11799                 if ( skip ) continue;
11800
11801                 /* check factory class for filtering */
11802                 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory));
11803
11804                 /*parsers are not required in case of external feeder*/
11805                 if (g_strrstr(klass, "Codec/Parser") && MMPLAYER_IS_ES_BUFF_SRC(player))
11806                         continue;
11807
11808                 /* NOTE : msl don't need to use image plugins.
11809                  * So, those plugins should be skipped for error handling.
11810                  */
11811                 if ( g_strrstr(klass, "Codec/Decoder/Image") )
11812                 {
11813                         debug_log("skipping [%s] by not required\n", GST_OBJECT_NAME (factory));
11814                         continue;
11815                 }
11816
11817                 /* check pad compatability */
11818                 for(pads = gst_element_factory_get_static_pad_templates(factory);
11819                                         pads != NULL; pads=pads->next)
11820                 {
11821                         GstStaticPadTemplate *temp1 = pads->data;
11822                         GstCaps* static_caps = NULL;
11823
11824                         if( temp1->direction != GST_PAD_SINK
11825                                 || temp1->presence != GST_PAD_ALWAYS)
11826                                 continue;
11827
11828                         if ( GST_IS_CAPS( &temp1->static_caps.caps) )
11829                         {
11830                                 /* using existing caps */
11831                                 static_caps = gst_caps_ref(temp1->static_caps.caps );
11832                         }
11833                         else
11834                         {
11835                                 /* create one */
11836                                 static_caps = gst_caps_from_string ( temp1->static_caps.string );
11837                         }
11838
11839                         res = gst_caps_intersect((GstCaps*)caps, static_caps);
11840                         gst_caps_unref( static_caps );
11841                         static_caps = NULL;
11842
11843                         if( res && !gst_caps_is_empty(res) )
11844                         {
11845                                 GstElement *new_element;
11846                                 GList *elements = player->parsers;
11847                                 char *name_template = g_strdup(temp1->name_template);
11848                                 gchar *name_to_plug = GST_OBJECT_NAME(factory);
11849                                 gst_caps_unref(res);
11850
11851                                 /* check ALP Codec can be used or not */
11852                                 if ((g_strrstr(klass, "Codec/Decoder/Audio")))
11853                                 {
11854                                         /* consider mp3 audio only */
11855                                         if ( !MMPLAYER_IS_STREAMING(player) && __mmplayer_is_only_mp3_type(player->type) )
11856                                         {
11857                                                 /* try to use ALP decoder first instead of selected decoder */
11858                                                 GstElement *element = NULL;
11859                                                 GstElementFactory * element_facory;
11860                                                 gchar *path = NULL;
11861                                                 guint64 data_size = 0;
11862                                                 #define MIN_THRESHOLD_SIZE  320 * 1024 // 320K
11863                                                 struct stat sb;
11864
11865                                                 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
11866
11867                                                 if (stat(path, &sb) == 0)
11868                                                 {
11869                                                         data_size = (guint64)sb.st_size;
11870                                                 }
11871                                                 debug_log("file size : %u", data_size);
11872
11873                                                 if (data_size > MIN_THRESHOLD_SIZE)
11874                                                 {
11875                                                         debug_log("checking if ALP can be used or not");
11876                                                         element = gst_element_factory_make("omx_mp3dec", "omx mp3 decoder");
11877                                                         if ( element )
11878                                                         {
11879                                                                 /* check availability because multi-instance is not supported */
11880                                                                 GstStateChangeReturn ret = gst_element_set_state(element, GST_STATE_READY);
11881
11882                                                                 if (ret != GST_STATE_CHANGE_SUCCESS) // use just selected decoder
11883                                                                 {
11884                                                                         gst_object_unref (element);
11885                                                                 }
11886                                                                 else if (ret == GST_STATE_CHANGE_SUCCESS) // replace facotry to use omx
11887                                                                 {
11888                                                                         /* clean  */
11889                                                                         gst_element_set_state(element, GST_STATE_NULL);
11890                                                                         gst_object_unref (element);
11891
11892                                                                         element_facory = gst_element_factory_find("omx_mp3dec");
11893                                                                         /* replace, otherwise use selected thing instead */
11894                                                                         if (element_facory)
11895                                                                         {
11896                                                                                 factory = element_facory;
11897                                                                                 name_to_plug = GST_OBJECT_NAME(factory);
11898                                                                         }
11899
11900                                                                         /* make parser alp mode */
11901                                                                         #ifdef _MM_PLAYER_ALP_PARSER
11902                                                                         g_list_foreach (player->parsers, check_name, player);
11903                                                                         #endif
11904                                                                 }
11905                                                         }
11906                                                 }
11907                                         }
11908                                 }
11909                                 else if ((g_strrstr(klass, "Codec/Decoder/Video")))
11910                                 {
11911                                         if ( g_strrstr(GST_OBJECT_NAME(factory), "omx_") )
11912                                         {
11913                                                 char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
11914                                                 if (env != NULL)
11915                                                 {
11916                                                         if (strncasecmp(env, "yes", 3) == 0)
11917                                                         {
11918                                                                 debug_log("skipping [%s] by disabled\n", name_to_plug);
11919                                                                 MMPLAYER_FREEIF(name_template);
11920                                                                 continue;
11921                                                         }
11922                                                 }
11923                                         }
11924                                 }
11925
11926                                 debug_log("found %s to plug\n", name_to_plug);
11927
11928                                 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
11929                                 if ( ! new_element )
11930                                 {
11931                                         debug_error("failed to create element [%s]. continue with next.\n",
11932                                                 GST_OBJECT_NAME (factory));
11933
11934                                         MMPLAYER_FREEIF(name_template);
11935
11936                                         continue;
11937                                 }
11938
11939                                 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
11940                                  * because parser can accept its own output as input.
11941                                  */
11942                                 if (g_strrstr(klass, "Parser"))
11943                                 {
11944                                         gchar *selected = NULL;
11945
11946                                         for ( ; elements; elements = g_list_next(elements))
11947                                         {
11948                                                 gchar *element_name = elements->data;
11949
11950                                                 if (g_strrstr(element_name, name_to_plug))
11951                                                 {
11952                                                         debug_log("but, %s already linked, so skipping it\n", name_to_plug);
11953                                                         skip = TRUE;
11954                                                 }
11955                                         }
11956
11957                                         if (skip)
11958                                         {
11959                                                 MMPLAYER_FREEIF(name_template);
11960                                                 continue;
11961                                         }
11962
11963                                         selected = g_strdup(name_to_plug);
11964                                         player->parsers = g_list_append(player->parsers, selected);
11965                                 }
11966
11967                                 /* store specific handles for futher control */
11968                                 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
11969                                 {
11970                                         /* FIXIT : first value will be overwritten if there's more
11971                                          * than 1 demuxer/parser
11972                                          */
11973                                         debug_log("plugged element is demuxer. take it\n");
11974                                         mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
11975                                         mainbin[MMPLAYER_M_DEMUX].gst = new_element;
11976
11977                                         /*Added for multi audio support */
11978                                         if(g_strrstr(klass, "Demux"))
11979                                         {
11980                                                 mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
11981                                                 mainbin[MMPLAYER_M_DEMUX_EX].gst = new_element;
11982
11983                                                 /* NOTE : workaround for bug in mpegtsdemux since doesn't emit
11984                                                 no-more-pad signal. this may cause wrong content attributes at PAUSED state
11985                                                 this code should be removed after mpegtsdemux is fixed */
11986                                                 if ( g_strrstr(GST_OBJECT_NAME(factory), "mpegtsdemux") )
11987                                                 {
11988                                                         debug_warning("force no-more-pad to TRUE since mpegtsdemux os not giving no-more-pad signal. content attributes may wrong");
11989                                                         player->no_more_pad = TRUE;
11990                                                 }
11991                                         }
11992                                         if (g_strrstr(name_to_plug, "asfdemux")) // to support trust-zone only
11993                                         {
11994                                                 g_object_set(mainbin[MMPLAYER_M_DEMUX_EX].gst, "file-location", player->profile.uri,NULL);
11995                                         }
11996                                 }
11997                                 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
11998                                 {
11999                                         if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
12000                                         {
12001                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
12002                                                 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
12003                                                 mainbin[MMPLAYER_M_DEC1].gst = new_element;
12004                                         }
12005                                         else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
12006                                         {
12007                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
12008                                                 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
12009                                                 mainbin[MMPLAYER_M_DEC2].gst = new_element;
12010                                         }
12011                                         /* NOTE : IF one codec is found, add it to supported_codec and remove from
12012                                          * missing plugin. Both of them are used to check what's supported codec
12013                                          * before returning result of play start. And, missing plugin should be
12014                                          * updated here for multi track files.
12015                                          */
12016                                         if(g_str_has_prefix(mime, "video"))
12017                                         {
12018                                                 GstPad *src_pad = NULL;
12019                                                 GstPadTemplate *pad_templ = NULL;
12020                                                 GstCaps *caps = NULL;
12021                                                 gchar *caps_str = NULL;
12022
12023                                                 debug_log("found VIDEO decoder\n");
12024                                                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
12025                                                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
12026
12027                                                 src_pad = gst_element_get_static_pad (new_element, "src");
12028                                                 pad_templ = gst_pad_get_pad_template (src_pad);
12029                                                 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
12030
12031                                                 caps_str = gst_caps_to_string(caps);
12032
12033                                                 /* clean */
12034                                                 MMPLAYER_FREEIF( caps_str );
12035                                                 gst_object_unref (src_pad);
12036                                         }
12037                                         else if (g_str_has_prefix(mime, "audio"))
12038                                         {
12039                                                 debug_log("found AUDIO decoder\n");
12040                                                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
12041                                                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
12042                                         }
12043                                 }
12044
12045                                 if ( ! __mmplayer_close_link(player, pad, new_element,
12046                                                         name_template,gst_element_factory_get_static_pad_templates(factory)) )
12047                                 {
12048                                         MMPLAYER_FREEIF(name_template);
12049                                         if (player->keep_detecting_vcodec)
12050                                         continue;
12051
12052                                         /* Link is failed even though a supportable codec is found. */
12053                                         __mmplayer_check_not_supported_codec(player, klass, mime);
12054
12055                                         debug_error("failed to call _close_link\n");
12056                                         return FALSE;
12057                                 }
12058
12059                                 MMPLAYER_FREEIF(name_template);
12060                                 return TRUE;
12061                         }
12062
12063                         gst_caps_unref(res);
12064                         break;
12065                 }
12066         }
12067
12068         /* There is no available codec. */
12069         __mmplayer_check_not_supported_codec(player, klass, mime);
12070
12071         MMPLAYER_FLEAVE();
12072         return FALSE;
12073
12074 ERROR:
12075         /* release */
12076         if ( queue )
12077                 gst_object_unref( queue );
12078
12079         if ( queue_pad )
12080                 gst_object_unref( queue_pad );
12081
12082         if ( element )
12083                 gst_object_unref ( element );
12084
12085         return FALSE;
12086 }
12087
12088
12089 static int
12090 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
12091 {
12092         MMPLAYER_FENTER();
12093
12094         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
12095         return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
12096
12097         debug_log("class : %s, mime : %s \n", factory_class, mime );
12098
12099         /* add missing plugin */
12100         /* NOTE : msl should check missing plugin for image mime type.
12101          * Some motion jpeg clips can have playable audio track.
12102          * So, msl have to play audio after displaying popup written video format not supported.
12103          */
12104         if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
12105         {
12106                 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
12107                 {
12108                         debug_log("not found demuxer\n");
12109                         player->not_found_demuxer = TRUE;
12110                         player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
12111
12112                         goto DONE;
12113                 }
12114         }
12115
12116         if( !g_strrstr(factory_class, "Demuxer"))
12117         {
12118                 if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
12119                 {
12120                         debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
12121                                 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
12122
12123                         /* check that clip have multi tracks or not */
12124                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
12125                         {
12126                                 debug_log("video plugin is already linked\n");
12127                         }
12128                         else
12129                         {
12130                                 debug_warning("add VIDEO to missing plugin\n");
12131                                 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
12132                         }
12133                 }
12134                 else if ( g_str_has_prefix(mime, "audio") )
12135                 {
12136                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
12137                         {
12138                                 debug_log("audio plugin is already linked\n");
12139                         }
12140                         else
12141                         {
12142                                 debug_warning("add AUDIO to missing plugin\n");
12143                                 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
12144                         }
12145                 }
12146         }
12147
12148 DONE:
12149         MMPLAYER_FLEAVE();
12150
12151         return MM_ERROR_NONE;
12152 }
12153
12154
12155 static void
12156 __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
12157 {
12158     mm_player_t* player = (mm_player_t*)data;
12159
12160         MMPLAYER_FENTER();
12161
12162         return_if_fail( player );
12163
12164         /* remove fakesink. */
12165         if ( !__mmplayer_gst_remove_fakesink( player,
12166                                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
12167         {
12168                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
12169                  * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
12170                  * source element are not same. To overcome this situation, this function will called
12171                  * several places and several times. Therefore, this is not an error case.
12172                  */
12173                 return;
12174         }
12175
12176         debug_log("pipeline has completely constructed\n");
12177
12178         if (( player->ini.async_start ) &&
12179                 ( player->msg_posted == FALSE ) &&
12180                 ( player->cmd >= MMPLAYER_COMMAND_START ))
12181         {
12182                 __mmplayer_handle_missed_plugin( player );
12183         }
12184
12185         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complete" );
12186 }
12187
12188 static gboolean
12189 __mmplayer_verify_next_play_path(mm_player_t *player)
12190 {
12191         MMHandleType attrs = 0;
12192         MMPlayerParseProfile profile;
12193         gint uri_idx = 0, check_cnt = 0;
12194         char *uri = NULL;
12195         gint mode = MM_PLAYER_PD_MODE_NONE;
12196         gint count = 0;
12197         guint num_of_list = 0;
12198
12199         MMPLAYER_FENTER();
12200
12201         debug_log("checking for gapless play");
12202
12203         if (player->pipeline->textbin)
12204         {
12205                 debug_error("subtitle path is enabled. gapless play is not supported.\n");
12206                 goto ERROR;
12207         }
12208
12209         attrs = MMPLAYER_GET_ATTRS(player);
12210         if ( !attrs )
12211         {
12212                 debug_error("fail to get attributes.\n");
12213                 goto ERROR;
12214         }
12215
12216         /* seamless playback is supported in case of audio only */
12217         mm_attrs_get_int_by_name(attrs, "content_video_found", &mode);
12218         if (mode)
12219         {
12220                 debug_log("video found");
12221                 goto ERROR;
12222         }
12223
12224         if (mm_attrs_get_int_by_name (attrs, "pd_mode", &mode) == MM_ERROR_NONE)
12225         {
12226                 if (mode == TRUE)
12227                 {
12228                         debug_warning("pd mode\n");
12229                         goto ERROR;
12230                 }
12231         }
12232
12233         if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
12234         {
12235                 debug_error("can not get play count\n");
12236         }
12237
12238         num_of_list = g_list_length(player->uri_info.uri_list);
12239
12240         debug_log("repeat count = %d, num_of_list = %d\n", count, num_of_list);
12241
12242         if ( num_of_list == 0 )
12243         {
12244                 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE)
12245                 {
12246                         debug_error("can not get profile_uri\n");
12247                         goto ERROR;
12248                 }
12249
12250                 if (!uri)
12251                 {
12252                         debug_error("uri list is empty.\n");
12253                         goto ERROR;
12254                 }
12255
12256                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12257                 debug_log("add original path : %s ", uri);
12258
12259                 num_of_list = 1;
12260                 uri= NULL;
12261         }
12262
12263         uri_idx = player->uri_info.uri_idx;
12264
12265         while(TRUE)
12266         {
12267                 check_cnt++;
12268
12269                 if (check_cnt > num_of_list)
12270                 {
12271                         debug_error("there is no valid uri.");
12272                         goto ERROR;
12273                 }
12274
12275                 debug_log("uri idx : %d / %d\n", uri_idx, num_of_list);
12276
12277                 if ( uri_idx < num_of_list-1 )
12278                 {
12279                         uri_idx++;
12280                 }
12281                 else
12282                 {
12283                         if ((count <= 1) && (count != -1))
12284                         {
12285                                 debug_log("no repeat.");
12286                                 goto ERROR;
12287                         }
12288                         else if ( count > 1 )   /* decrease play count */
12289                         {
12290                                 /* we successeded to rewind. update play count and then wait for next EOS */
12291                                 count--;
12292
12293                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
12294
12295                                 /* commit attribute */
12296                                 if ( mmf_attrs_commit ( attrs ) )
12297                                 {
12298                                         debug_error("failed to commit attribute\n");
12299                                 }
12300                         }
12301
12302                         /* count < 0 : repeat continually */
12303                         uri_idx = 0;
12304                 }
12305
12306                 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12307                 debug_log("uri idx : %d, uri = %s\n", uri_idx, uri);
12308
12309                 if (uri == NULL)
12310                 {
12311                         debug_warning("next uri does not exist\n");
12312                         continue;
12313                 }
12314
12315                 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE)
12316                 {
12317                         debug_error("failed to parse profile\n");
12318                         continue;
12319                 }
12320
12321                 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
12322                         (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP))
12323                 {
12324                         debug_warning("uri type is not supported (%d).", profile.uri_type);
12325                         continue;
12326                 }
12327
12328                 break;
12329         }
12330
12331         player->uri_info.uri_idx = uri_idx;
12332         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
12333
12334
12335         if (mmf_attrs_commit(player->attrs))
12336         {
12337                 debug_error("failed to commit.\n");
12338                 goto ERROR;
12339         }
12340
12341         debug_log("next uri %s (%d)\n", uri, uri_idx);
12342
12343         return TRUE;
12344
12345 ERROR:
12346
12347         debug_error("unable to play next path. EOS will be posted soon.\n");
12348         return FALSE;
12349 }
12350
12351 static void
12352 __mmplayer_initialize_next_play(mm_player_t *player)
12353 {
12354         int i;
12355
12356         MMPLAYER_FENTER();
12357
12358         player->smooth_streaming = FALSE;
12359         player->videodec_linked = 0;
12360         player->audiodec_linked = 0;
12361         player->videosink_linked = 0;
12362         player->audiosink_linked = 0;
12363         player->textsink_linked = 0;
12364         player->is_external_subtitle_present = FALSE;
12365         player->not_supported_codec = MISSING_PLUGIN_NONE;
12366         player->can_support_codec = FOUND_PLUGIN_NONE;
12367         player->pending_seek.is_pending = FALSE;
12368         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
12369         player->pending_seek.pos = 0;
12370         player->msg_posted = FALSE;
12371         player->has_many_types = FALSE;
12372         player->no_more_pad = FALSE;
12373         player->is_drm_file = FALSE;
12374         player->not_found_demuxer = 0;
12375         player->doing_seek = FALSE;
12376         player->max_audio_channels = 0;
12377         player->is_subtitle_force_drop = FALSE;
12378         player->play_subtitle = FALSE;
12379         player->use_textoverlay = FALSE;
12380         player->adjust_subtitle_pos = 0;
12381
12382         player->updated_bitrate_count = 0;
12383         player->total_bitrate = 0;
12384         player->updated_maximum_bitrate_count = 0;
12385         player->total_maximum_bitrate = 0;
12386
12387         _mmplayer_track_initialize(player);
12388
12389         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
12390         {
12391                 player->bitrate[i] = 0;
12392                 player->maximum_bitrate[i] = 0;
12393         }
12394
12395         if (player->v_stream_caps)
12396         {
12397                 gst_caps_unref(player->v_stream_caps);
12398                 player->v_stream_caps = NULL;
12399         }
12400
12401         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
12402         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
12403
12404         /* clean found parsers */
12405         if (player->parsers)
12406         {
12407                 GList *parsers = player->parsers;
12408                 for ( ;parsers ; parsers = g_list_next(parsers))
12409                 {
12410                         gchar *name = parsers->data;
12411                         MMPLAYER_FREEIF(name);
12412                 }
12413                 g_list_free(player->parsers);
12414                 player->parsers = NULL;
12415         }
12416
12417         /* clean found audio decoders */
12418         if (player->audio_decoders)
12419         {
12420                 GList *a_dec = player->audio_decoders;
12421                 for ( ;a_dec ; a_dec = g_list_next(a_dec))
12422                 {
12423                         gchar *name = a_dec->data;
12424                         MMPLAYER_FREEIF(name);
12425                 }
12426                 g_list_free(player->audio_decoders);
12427                 player->audio_decoders = NULL;
12428         }
12429
12430         MMPLAYER_FLEAVE();
12431 }
12432
12433 static void
12434 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
12435 {
12436         MMPlayerGstElement *mainbin = NULL;
12437         MMMessageParamType msg_param = {0,};
12438         GstElement *element = NULL;
12439         MMHandleType attrs = 0;
12440         char *uri = NULL;
12441         enum MainElementID elemId = MMPLAYER_M_NUM;
12442
12443         MMPLAYER_FENTER();
12444
12445         if ((player == NULL) ||
12446                 (player->pipeline == NULL) ||
12447                 (player->pipeline->mainbin == NULL))
12448         {
12449                 debug_error("player is null.\n");
12450                 goto ERROR;
12451         }
12452
12453         mainbin = player->pipeline->mainbin;
12454         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
12455
12456         attrs = MMPLAYER_GET_ATTRS(player);
12457         if ( !attrs )
12458         {
12459                 debug_error("fail to get attributes.\n");
12460                 goto ERROR;
12461         }
12462
12463         /* Initialize Player values */
12464         __mmplayer_initialize_next_play(player);
12465
12466         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
12467
12468         if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE)
12469         {
12470                 debug_error("failed to parse profile\n");
12471                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
12472                 goto ERROR;
12473         }
12474
12475         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
12476                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player)))
12477         {
12478                 debug_error("it's dash or hls. not support.");
12479                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
12480                 goto ERROR;
12481         }
12482
12483         /* setup source */
12484         switch ( player->profile.uri_type )
12485         {
12486                 /* file source */
12487                 case MM_PLAYER_URI_TYPE_FILE:
12488                 {
12489                         debug_log("using filesrc for 'file://' handler.\n");
12490
12491                         element = gst_element_factory_make("filesrc", "source");
12492
12493                         if ( !element )
12494                         {
12495                                 debug_error("failed to create filesrc\n");
12496                                 break;
12497                         }
12498
12499                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
12500                         break;
12501                 }
12502                 case MM_PLAYER_URI_TYPE_URL_HTTP:
12503                 {
12504                         gchar *user_agent, *proxy, *cookies, **cookie_list;
12505                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
12506                         user_agent = proxy = cookies = NULL;
12507                         cookie_list = NULL;
12508
12509                         element = gst_element_factory_make(player->ini.name_of_httpsrc, "http_streaming_source");
12510                         if ( !element )
12511                         {
12512                                 debug_error("failed to create http streaming source element[%s].\n", player->ini.name_of_httpsrc);
12513                                 break;
12514                         }
12515                         debug_log("using http streamming source [%s].\n", player->ini.name_of_httpsrc);
12516
12517                         /* get attribute */
12518                         mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
12519                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
12520                         mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
12521                         mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
12522
12523                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
12524                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
12525                         {
12526                                 debug_log("get timeout from ini\n");
12527                                 http_timeout = player->ini.http_timeout;
12528                         }
12529
12530                         /* get attribute */
12531                         secure_debug_log("location : %s\n", player->profile.uri);
12532                         secure_debug_log("cookies : %s\n", cookies);
12533                         secure_debug_log("proxy : %s\n", proxy);
12534                         secure_debug_log("user_agent :  %s\n", user_agent);
12535                         debug_log("timeout : %d\n", http_timeout);
12536
12537                         /* setting property to streaming source */
12538                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
12539                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
12540                         g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
12541
12542                         /* check if prosy is vailid or not */
12543                         if ( util_check_valid_url ( proxy ) )
12544                                 g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
12545                         /* parsing cookies */
12546                         if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
12547                                 g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
12548                         if ( user_agent )
12549                                 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
12550                         break;
12551                 }
12552                 default:
12553                         debug_error("not support uri type %d\n", player->profile.uri_type);
12554                         break;
12555         }
12556
12557         if ( !element )
12558         {
12559                 debug_error("no source element was created.\n");
12560                 goto ERROR;
12561         }
12562
12563         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
12564         {
12565                 debug_error("failed to add source element to pipeline\n");
12566                 gst_object_unref(GST_OBJECT(element));
12567                 element = NULL;
12568                 goto ERROR;
12569         }
12570
12571         /* take source element */
12572         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
12573         mainbin[MMPLAYER_M_SRC].gst = element;
12574
12575         element = NULL;
12576
12577         if (MMPLAYER_IS_HTTP_STREAMING(player))
12578         {
12579                 if (player->streamer == NULL)
12580                 {
12581                         player->streamer = __mm_player_streaming_create();
12582                         __mm_player_streaming_initialize(player->streamer);
12583                 }
12584
12585                 elemId = MMPLAYER_M_TYPEFIND;
12586                 element = gst_element_factory_make("typefind", "typefinder");
12587                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
12588                         G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
12589         }
12590         else
12591         {
12592                 elemId = MMPLAYER_M_AUTOPLUG;
12593                 element = __mmplayer_create_decodebin(player);
12594         }
12595
12596         /* check autoplug element is OK */
12597         if ( ! element )
12598         {
12599                 debug_error("can not create element (%d)\n", elemId);
12600                 goto ERROR;
12601         }
12602
12603         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
12604         {
12605                 debug_error("failed to add sinkbin to pipeline\n");
12606                 gst_object_unref(GST_OBJECT(element));
12607                 element = NULL;
12608                 goto ERROR;
12609         }
12610
12611         mainbin[elemId].id = elemId;
12612         mainbin[elemId].gst = element;
12613
12614         if ( gst_element_link (mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE )
12615         {
12616                 debug_error("Failed to link src - autoplug (or typefind)\n");
12617                 goto ERROR;
12618         }
12619
12620         if (gst_element_set_state (mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE)
12621         {
12622                 debug_error("Failed to change state of src element\n");
12623                 goto ERROR;
12624         }
12625
12626         if (!MMPLAYER_IS_HTTP_STREAMING(player))
12627         {
12628                 if (gst_element_set_state (mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE)
12629                 {
12630                         debug_error("Failed to change state of decodebin\n");
12631                         goto ERROR;
12632                 }
12633         }
12634         else
12635         {
12636                 if (gst_element_set_state (mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE)
12637                 {
12638                         debug_error("Failed to change state of src element\n");
12639                         goto ERROR;
12640                 }
12641         }
12642
12643         player->gapless.stream_changed = TRUE;
12644         player->gapless.running = TRUE;
12645         MMPLAYER_FLEAVE();
12646         return;
12647
12648 ERROR:
12649         MMPLAYER_PLAYBACK_UNLOCK(player);
12650
12651         if (!player->msg_posted)
12652         {
12653                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
12654                 player->msg_posted = TRUE;
12655         }
12656         return;
12657 }
12658
12659 static gboolean
12660 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
12661 {
12662         mm_player_selector_t *selector = &player->selector[type];
12663         MMPlayerGstElement *sinkbin = NULL;
12664         enum MainElementID selectorId = MMPLAYER_M_NUM;
12665         enum MainElementID sinkId = MMPLAYER_M_NUM;
12666         GstPad *srcpad = NULL;
12667         GstPad *sinkpad = NULL;
12668
12669         MMPLAYER_FENTER();
12670         return_val_if_fail (player, FALSE);
12671
12672         debug_log("type %d", type);
12673
12674         switch (type)
12675         {
12676                 case MM_PLAYER_TRACK_TYPE_AUDIO:
12677                         selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
12678                         sinkId = MMPLAYER_A_BIN;
12679                         sinkbin = player->pipeline->audiobin;
12680                 break;
12681                 case MM_PLAYER_TRACK_TYPE_TEXT:
12682                         selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
12683                         sinkId = MMPLAYER_T_BIN;
12684                         sinkbin = player->pipeline->textbin;
12685                 break;
12686                 default:
12687                         debug_error("requested type is not supportable");
12688                         return FALSE;
12689                 break;
12690         }
12691
12692         if (player->pipeline->mainbin[selectorId].gst)
12693         {
12694                 gint n;
12695
12696                 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
12697
12698                 if (selector->event_probe_id != 0)
12699                         gst_pad_remove_probe (srcpad, selector->event_probe_id);
12700                 selector->event_probe_id = 0;
12701
12702                 if ((sinkbin) && (sinkbin[sinkId].gst))
12703                 {
12704                         sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
12705
12706                         if (srcpad && sinkpad)
12707                         {
12708                                 /* after getting drained signal there is no data flows, so no need to do pad_block */
12709                                 debug_log("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
12710                                 gst_pad_unlink (srcpad, sinkpad);
12711                         }
12712
12713                         gst_object_unref (sinkpad);
12714                         sinkpad = NULL;
12715                 }
12716                 gst_object_unref (srcpad);
12717                 srcpad = NULL;
12718
12719                 debug_log("selector release");
12720
12721                 /* release and unref requests pad from the selector */
12722                 for (n = 0; n < selector->channels->len; n++)
12723                 {
12724                         GstPad *sinkpad = g_ptr_array_index (selector->channels, n);
12725                         gst_element_release_request_pad ((player->pipeline->mainbin[selectorId].gst), sinkpad);
12726                 }
12727                 g_ptr_array_set_size (selector->channels, 0);
12728
12729                 gst_element_set_state (player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
12730                 gst_bin_remove (GST_BIN_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
12731
12732                 player->pipeline->mainbin[selectorId].gst = NULL;
12733                 selector = NULL;
12734         }
12735
12736         return TRUE;
12737 }
12738
12739 static void
12740 __mmplayer_deactivate_old_path(mm_player_t *player)
12741 {
12742         MMPLAYER_FENTER();
12743         return_if_fail ( player );
12744
12745         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
12746                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT)))
12747         {
12748                 debug_error("deactivate selector error");
12749                 goto ERROR;
12750         }
12751
12752         _mmplayer_track_destroy(player);
12753         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG );
12754
12755         if (player->streamer)
12756         {
12757                 __mm_player_streaming_deinitialize (player->streamer);
12758                 __mm_player_streaming_destroy(player->streamer);
12759                 player->streamer = NULL;
12760         }
12761
12762         MMPLAYER_PLAYBACK_LOCK(player);
12763         g_cond_signal( &player->next_play_thread_cond );
12764
12765         MMPLAYER_FLEAVE();
12766         return;
12767
12768 ERROR:
12769
12770         if (!player->msg_posted)
12771         {
12772                 MMMessageParamType msg = {0,};
12773
12774                 /*post error*/
12775                 msg.code = MM_ERROR_PLAYER_INTERNAL;
12776                 debug_error("next_uri_play> deactivate error");
12777
12778                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
12779                 player->msg_posted = TRUE;
12780         }
12781         return;
12782 }
12783
12784 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
12785 {
12786         int result = MM_ERROR_NONE;
12787         mm_player_t* player = (mm_player_t*) hplayer;
12788         MMPLAYER_FENTER();
12789
12790         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12791
12792         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
12793         if (mmf_attrs_commit(player->attrs))
12794         {
12795                 debug_error("failed to commit the original uri.\n");
12796                 result = MM_ERROR_PLAYER_INTERNAL;
12797         }
12798         else
12799         {
12800                 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
12801                 {
12802                         debug_error("failed to add the original uri in the uri list.\n");
12803                 }
12804         }
12805
12806         MMPLAYER_FLEAVE();
12807         return result;
12808 }
12809
12810 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
12811 {
12812         mm_player_t* player = (mm_player_t*) hplayer;
12813         guint num_of_list = 0;
12814
12815         MMPLAYER_FENTER();
12816
12817         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12818         return_val_if_fail (uri, MM_ERROR_INVALID_ARGUMENT);
12819
12820         if (player->pipeline && player->pipeline->textbin)
12821         {
12822                 debug_error("subtitle path is enabled.\n");
12823                 return MM_ERROR_PLAYER_INVALID_STATE;
12824         }
12825
12826         num_of_list = g_list_length(player->uri_info.uri_list);
12827
12828         if (is_first_path == TRUE)
12829         {
12830                 if (num_of_list == 0)
12831                 {
12832                         player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12833                         debug_log("add original path : %s", uri);
12834                 }
12835                 else
12836                 {
12837                         player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
12838                         player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
12839
12840                         debug_log("change original path : %s", uri);
12841                 }
12842         }
12843         else
12844         {
12845                 if (num_of_list == 0)
12846                 {
12847                         MMHandleType attrs = 0;
12848                         char *original_uri = NULL;
12849
12850                         attrs = MMPLAYER_GET_ATTRS(player);
12851                         if ( attrs )
12852                         {
12853                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
12854
12855                                 if (!original_uri)
12856                                 {
12857                                         debug_error("there is no original uri.");
12858                                         return MM_ERROR_PLAYER_INVALID_STATE;
12859                                 }
12860
12861                                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
12862                                 player->uri_info.uri_idx = 0;
12863
12864                                 debug_log("add original path at first : %s (%d)", original_uri);
12865                         }
12866                 }
12867
12868                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12869                 debug_log("add new path : %s (total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
12870         }
12871
12872         MMPLAYER_FLEAVE();
12873         return MM_ERROR_NONE;
12874 }
12875
12876 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
12877 {
12878         mm_player_t* player = (mm_player_t*) hplayer;
12879         char *next_uri = NULL;
12880         guint num_of_list = 0;
12881
12882         MMPLAYER_FENTER();
12883         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12884
12885         num_of_list = g_list_length(player->uri_info.uri_list);
12886
12887         if (num_of_list > 0)
12888         {
12889                 gint uri_idx = player->uri_info.uri_idx;
12890
12891                 if ( uri_idx < num_of_list-1 )
12892                         uri_idx++;
12893                 else
12894                         uri_idx = 0;
12895
12896                 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12897                 debug_error("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
12898
12899                 *uri = g_strdup(next_uri);
12900         }
12901
12902         MMPLAYER_FLEAVE();
12903         return MM_ERROR_NONE;
12904 }
12905
12906 static void
12907 __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad,
12908 GstCaps *caps, gpointer data)
12909 {
12910         mm_player_t* player = (mm_player_t*)data;
12911         const gchar* klass = NULL;
12912         const gchar* mime = NULL;
12913         gchar* caps_str = NULL;
12914
12915         klass = gst_element_factory_get_klass (gst_element_get_factory(elem));
12916         mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12917         caps_str = gst_caps_to_string(caps);
12918
12919         debug_warning("unknown type of caps : %s from %s",
12920                                         caps_str, GST_ELEMENT_NAME (elem));
12921
12922         MMPLAYER_FREEIF(caps_str);
12923
12924         /* There is no available codec. */
12925         __mmplayer_check_not_supported_codec (player, klass, mime);
12926 }
12927
12928 static gboolean
12929 __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad,
12930 GstCaps * caps,  gpointer data)
12931 {
12932         mm_player_t* player = (mm_player_t*)data;
12933         const char* mime = NULL;
12934         gboolean ret = TRUE;
12935
12936         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
12937         mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12938
12939         if (g_str_has_prefix(mime, "audio")) {
12940                 GstStructure* caps_structure = NULL;
12941                 gint samplerate = 0;
12942                 gint channels = 0;
12943                 gchar *caps_str = NULL;
12944
12945                 caps_structure = gst_caps_get_structure(caps, 0);
12946                 gst_structure_get_int (caps_structure, "rate", &samplerate);
12947                 gst_structure_get_int (caps_structure, "channels", &channels);
12948
12949                 if ( (channels > 0 && samplerate == 0)) {
12950                         debug_log("exclude audio...");
12951                         ret = FALSE;
12952                 }
12953
12954                 caps_str = gst_caps_to_string(caps);
12955                 /* set it directly because not sent by TAG */
12956                 if (g_strrstr(caps_str, "mobile-xmf")) {
12957                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
12958                 }
12959                 MMPLAYER_FREEIF (caps_str);
12960         } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
12961                 debug_log("already video linked");
12962                 ret = FALSE;
12963         } else {
12964                 debug_log("found new stream");
12965         }
12966
12967         return ret;
12968 }
12969
12970 static gint
12971 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad,
12972 GstCaps* caps, GstElementFactory* factory, gpointer data)
12973 {
12974         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
12975          We are defining our own and will be removed when it actually exposed */
12976         typedef enum {
12977                 GST_AUTOPLUG_SELECT_TRY,
12978                 GST_AUTOPLUG_SELECT_EXPOSE,
12979                 GST_AUTOPLUG_SELECT_SKIP
12980         } GstAutoplugSelectResult;
12981
12982         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
12983         mm_player_t* player = (mm_player_t*)data;
12984
12985         gchar* factory_name = NULL;
12986         gchar* caps_str = NULL;
12987         const gchar* klass = NULL;
12988         gint idx = 0;
12989
12990         factory_name = GST_OBJECT_NAME (factory);
12991         klass = gst_element_factory_get_klass(factory);
12992         caps_str = gst_caps_to_string(caps);
12993
12994 //      debug_log("found new element [%s] to link for caps [%s]", factory_name, caps_str);
12995         debug_log("found new element [%s] to link", factory_name);
12996
12997         /* store type string */
12998         if (player->type == NULL)
12999         {
13000                 player->type = gst_caps_to_string(caps);
13001                 __mmplayer_update_content_type_info(player);
13002         }
13003
13004         /* filtering exclude keyword */
13005         for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
13006         {
13007                 if ( strstr(factory_name, player->ini.exclude_element_keyword[idx] ) )
13008                 {
13009                         debug_warning("skipping [%s] by exculde keyword [%s]\n",
13010                         factory_name, player->ini.exclude_element_keyword[idx] );
13011
13012                         // NOTE : does we need to check n_value against the number of item selected?
13013                         result = GST_AUTOPLUG_SELECT_SKIP;
13014                         goto DONE;
13015                 }
13016         }
13017
13018         /* check factory class for filtering */
13019         /* NOTE : msl don't need to use image plugins.
13020          * So, those plugins should be skipped for error handling.
13021          */
13022         if (g_strrstr(klass, "Codec/Decoder/Image"))
13023         {
13024                 debug_log("skipping [%s] by not required\n", factory_name);
13025                 result = GST_AUTOPLUG_SELECT_SKIP;
13026                 goto DONE;
13027         }
13028
13029         if ((MMPLAYER_IS_ES_BUFF_SRC(player)) &&
13030                 (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser"))))
13031         {
13032                 // TO CHECK : subtitle if needed, add subparse exception.
13033                 debug_log("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
13034                 result = GST_AUTOPLUG_SELECT_SKIP;
13035                 goto DONE;
13036         }
13037
13038         if (g_strrstr(factory_name, "mpegpsdemux"))
13039         {
13040                 debug_log("skipping PS container - not support\n");
13041                 result = GST_AUTOPLUG_SELECT_SKIP;
13042                 goto DONE;
13043         }
13044
13045         if (g_strrstr(factory_name, SMOOTH_STREAMING_DEMUX))
13046                 player->smooth_streaming = TRUE;
13047
13048         /* check ALP Codec can be used or not */
13049         if ((g_strrstr(klass, "Codec/Decoder/Audio")))
13050         {
13051                 GstStructure* str = NULL;
13052                 gint channels = 0;
13053
13054                 str = gst_caps_get_structure( caps, 0 );
13055                 if ( str )
13056                 {
13057                         gst_structure_get_int (str, "channels", &channels);
13058
13059                         debug_log ("check audio ch : %d %d\n", player->max_audio_channels, channels);
13060                         if (player->max_audio_channels < channels)
13061                         {
13062                                 player->max_audio_channels = channels;
13063                         }
13064                 }
13065
13066                 if (!player->audiodec_linked)
13067                 {
13068                         /* set stream information */
13069                         __mmplayer_set_audio_attrs (player, caps);
13070                 }
13071         }
13072         else if ((g_strrstr(klass, "Codec/Decoder/Video")))
13073         {
13074                 if (g_strrstr(factory_name, "omx_"))
13075                 {
13076                         char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
13077                         if (env != NULL)
13078                         {
13079                                 if (strncasecmp(env, "yes", 3) == 0)
13080                                 {
13081                                         debug_log ("skipping [%s] by disabled\n", factory_name);
13082                                         result = GST_AUTOPLUG_SELECT_SKIP;
13083                                         goto DONE;
13084                                 }
13085                         }
13086                 }
13087         }
13088
13089         if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
13090                 (g_strrstr(klass, "Codec/Decoder/Video")))
13091         {
13092                 gint stype = 0;
13093                 gint width = 0;
13094                 GstStructure *str = NULL;
13095                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
13096
13097                 /* don't make video because of not required */
13098                 if (stype == MM_DISPLAY_SURFACE_NULL)
13099                 {
13100                         debug_log ("no video because it's not required. -> return expose");
13101                         if (player->set_mode.media_packet_video_stream == FALSE)
13102                         {
13103                                 result = GST_AUTOPLUG_SELECT_EXPOSE;
13104                                 goto DONE;
13105                         }
13106                 }
13107
13108                 /* get w/h for omx state-tune */
13109                 str = gst_caps_get_structure (caps, 0);
13110                 gst_structure_get_int (str, "width", &width);
13111
13112                 if (width != 0) {
13113                         if (player->v_stream_caps) {
13114                                 gst_caps_unref(player->v_stream_caps);
13115                                 player->v_stream_caps = NULL;
13116                         }
13117
13118                         player->v_stream_caps = gst_caps_copy(caps);
13119                         debug_log ("take caps for video state tune");
13120                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
13121                 }
13122         }
13123
13124         if (g_strrstr(klass, "Decoder"))
13125         {
13126                 const char* mime = NULL;
13127                 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
13128
13129                 if (g_str_has_prefix(mime, "video"))
13130                 {
13131                         // __mmplayer_check_video_zero_cpoy(player, factory);
13132
13133                         player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
13134                         player->can_support_codec |= FOUND_PLUGIN_VIDEO;
13135
13136                         player->videodec_linked = 1;
13137                 }
13138                 else if(g_str_has_prefix(mime, "audio"))
13139                 {
13140                         player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
13141                         player->can_support_codec |= FOUND_PLUGIN_AUDIO;
13142
13143                         player->audiodec_linked = 1;
13144                 }
13145         }
13146
13147 DONE:
13148         MMPLAYER_FREEIF(caps_str);
13149
13150         return result;
13151 }
13152
13153
13154 #if 0
13155 static GValueArray*
13156 __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad,
13157 GstCaps * caps,  gpointer data)
13158 {
13159         //mm_player_t* player = (mm_player_t*)data;
13160
13161         debug_log("decodebin is requesting factories for caps [%s] from element[%s]",
13162                 gst_caps_to_string(caps),
13163                 GST_ELEMENT_NAME(GST_PAD_PARENT(pad)));
13164
13165         return NULL;
13166 }
13167 #endif
13168
13169 static void
13170 __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad,
13171 gpointer data) // @
13172 {
13173         //mm_player_t* player = (mm_player_t*)data;
13174         GstCaps* caps = NULL;
13175
13176         debug_log("[Decodebin2] pad-removed signal\n");
13177
13178         caps = gst_pad_query_caps(new_pad, NULL);
13179         if (caps)
13180         {
13181                 gchar* caps_str = NULL;
13182                 caps_str = gst_caps_to_string(caps);
13183
13184                 debug_log("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem) );
13185
13186                 MMPLAYER_FREEIF(caps_str);
13187         }
13188 }
13189
13190 static void
13191 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
13192 {
13193         mm_player_t* player = (mm_player_t*)data;
13194
13195         MMPLAYER_FENTER();
13196         return_if_fail ( player );
13197
13198         debug_log("__mmplayer_gst_decode_drained");
13199
13200         if (player->use_deinterleave == TRUE)
13201         {
13202                 debug_log("group playing mode.");
13203                 return;
13204         }
13205
13206         if (!g_mutex_trylock(&player->cmd_lock))
13207         {
13208                 debug_warning("Fail to get cmd lock");
13209                 return;
13210         }
13211
13212         if (!__mmplayer_verify_next_play_path(player))
13213         {
13214                 debug_log("decoding is finished.");
13215                 player->gapless.running = FALSE;
13216                 player->gapless.start_time = 0;
13217                 g_mutex_unlock(&player->cmd_lock);
13218                 return;
13219         }
13220
13221         player->gapless.reconfigure = TRUE;
13222
13223         /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
13224         __mmplayer_deactivate_old_path(player);
13225
13226         g_mutex_unlock(&player->cmd_lock);
13227
13228         MMPLAYER_FLEAVE();
13229 }
13230
13231 static void
13232 __mmplayer_gst_element_added (GstElement *bin, GstElement *element, gpointer data)
13233 {
13234         mm_player_t* player = (mm_player_t*)data;
13235         const gchar* klass = NULL;
13236         gchar* factory_name = NULL;
13237
13238         klass = gst_element_factory_get_klass (gst_element_get_factory(element));
13239         factory_name = GST_OBJECT_NAME (gst_element_get_factory(element));
13240
13241         debug_log("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
13242
13243         if (__mmplayer_add_dump_buffer_probe(player, element))
13244                 debug_log("add buffer probe");
13245
13246         //<-
13247         if (g_strrstr(klass, "Codec/Decoder/Audio"))
13248         {
13249                 gchar* selected = NULL;
13250                 selected = g_strdup( GST_ELEMENT_NAME(element));
13251                 player->audio_decoders = g_list_append (player->audio_decoders, selected);
13252         }
13253         //-> temp code
13254
13255         if (g_strrstr(klass, "Parser"))
13256         {
13257                 gchar* selected = NULL;
13258
13259                 selected = g_strdup (factory_name);
13260                 player->parsers = g_list_append (player->parsers, selected);
13261         }
13262
13263         if ((g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) && !(g_strrstr(klass, "Adaptive")))
13264         {
13265                 /* FIXIT : first value will be overwritten if there's more
13266                  * than 1 demuxer/parser
13267                  */
13268
13269                 //debug_log ("plugged element is demuxer. take it\n");
13270                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
13271                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
13272
13273                 /*Added for multi audio support */ // Q. del?
13274                 if (g_strrstr(klass, "Demux"))
13275                 {
13276                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
13277                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
13278                 }
13279         }
13280
13281         if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux"))
13282         {
13283                 int surface_type = 0;
13284
13285                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
13286
13287 #if 0   // this is for 0.10 plugin with downstream modification
13288                 /* playback protection if drm file */
13289                 if (player->use_video_stream || surface_type == MM_DISPLAY_SURFACE_EVAS || surface_type == MM_DISPLAY_SURFACE_X_EXT)
13290                 {
13291                         debug_log("playback can be protected if playready drm");
13292                         g_object_set (G_OBJECT(element), "playback-protection", TRUE, NULL);
13293                 }
13294 #endif
13295         }
13296
13297         // to support trust-zone only
13298         if (g_strrstr(factory_name, "asfdemux"))
13299         {
13300                 debug_log ("set file-location %s\n", player->profile.uri);
13301                 g_object_set (G_OBJECT(element), "file-location", player->profile.uri, NULL);
13302
13303                 if (player->video_hub_download_mode == TRUE)
13304                 {
13305                         g_object_set (G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
13306                 }
13307         }
13308         else if (g_strrstr(factory_name, "legacyh264parse"))    // SMOOTH_STREAMING_DEMUX
13309         {
13310                 debug_log ("[%s] output-format to legacyh264parse\n", SMOOTH_STREAMING_DEMUX);
13311                 g_object_set (G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
13312         }
13313         else if (g_strrstr(factory_name, "mpegaudioparse"))
13314         {
13315                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
13316                         (__mmplayer_is_only_mp3_type(player->type)))
13317                 {
13318                         debug_log ("[mpegaudioparse] set streaming pull mode.");
13319                         g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
13320                 }
13321         }
13322         else if (g_strrstr(factory_name, "omx"))
13323         {
13324                 if (g_strrstr(klass, "Codec/Decoder/Video"))
13325                 {
13326                         gboolean ret = FALSE;
13327
13328                         if (player->v_stream_caps != NULL)
13329                         {
13330                                 GstPad *pad = gst_element_get_static_pad(element, "sink");
13331
13332                                 if (pad)
13333                                 {
13334                                         ret = gst_pad_set_caps(pad, player->v_stream_caps);
13335                                         debug_log("found omx decoder, setting gst_pad_set_caps for omx (ret:%d)", ret);
13336                                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
13337                                         gst_object_unref (pad);
13338                                 }
13339                         }
13340                         g_object_set (G_OBJECT(element), "state-tuning", TRUE, NULL);
13341                 }
13342 #ifdef _MM_PLAYER_ALP_PARSER
13343                 if (g_strrstr(factory_name, "omx_mp3dec"))
13344                 {
13345                         g_list_foreach (player->parsers, check_name, player);
13346                 }
13347 #endif
13348                 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
13349         }
13350
13351         if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
13352                 (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue")))
13353         {
13354                 debug_log ("plugged element is multiqueue. take it\n");
13355
13356                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
13357                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
13358
13359                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
13360                         (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)))
13361                 {
13362                         /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
13363                         __mm_player_streaming_set_multiqueue(player->streamer,
13364                                 element,
13365                                 TRUE,
13366                                 player->ini.http_buffering_time,
13367                                 1.0,
13368                                 player->ini.http_buffering_limit);
13369
13370                         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
13371                 }
13372         }
13373
13374         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-added" );
13375         return;
13376 }
13377
13378 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
13379 {
13380         MMPLAYER_FENTER();
13381         return_val_if_fail ( player, FALSE );
13382
13383         if ( MMPLAYER_IS_STREAMING(player) )
13384                 return FALSE;
13385
13386         /* This callback can be set to music player only. */
13387         if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
13388         {
13389                 debug_warning("audio callback is not supported for video");
13390                 return FALSE;
13391         }
13392
13393         if (player->audio_stream_cb)
13394         {
13395                 {
13396                         GstPad *pad = NULL;
13397
13398                         pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
13399
13400                         if ( !pad )
13401                         {
13402                                 debug_error("failed to get sink pad from audiosink to probe data\n");
13403                                 return FALSE;
13404                         }
13405                         player->audio_cb_probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
13406                                 __mmplayer_audio_stream_probe, player, NULL);
13407
13408                         gst_object_unref (pad);
13409
13410                         pad = NULL;
13411                }
13412         }
13413         else
13414         {
13415                 debug_error("There is no audio callback to configure.\n");
13416                 return FALSE;
13417         }
13418
13419         MMPLAYER_FLEAVE();
13420
13421         return TRUE;
13422 }
13423
13424 static void
13425 __mmplayer_init_factories(mm_player_t* player) // @
13426 {
13427         return_if_fail ( player );
13428
13429         player->factories = gst_registry_feature_filter(gst_registry_get(),
13430                                         (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
13431         player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
13432 }
13433
13434 static void
13435 __mmplayer_release_factories(mm_player_t* player) // @
13436 {
13437         MMPLAYER_FENTER();
13438         return_if_fail ( player );
13439
13440         if (player->factories)
13441         {
13442                 gst_plugin_feature_list_free (player->factories);
13443                 player->factories = NULL;
13444         }
13445
13446         MMPLAYER_FLEAVE();
13447 }
13448
13449 static void
13450 __mmplayer_release_misc(mm_player_t* player)
13451 {
13452         int i;
13453         gboolean cur_mode = player->set_mode.rich_audio;
13454         MMPLAYER_FENTER();
13455
13456         return_if_fail ( player );
13457
13458         player->use_video_stream = FALSE;
13459         player->video_stream_cb = NULL;
13460         player->video_stream_cb_user_param = NULL;
13461
13462         player->audio_stream_cb = NULL;
13463         player->audio_stream_render_cb_ex = NULL;
13464         player->audio_stream_cb_user_param = NULL;
13465         player->audio_stream_sink_sync = false;
13466
13467         player->video_stream_changed_cb = NULL;
13468         player->video_stream_changed_cb_user_param = NULL;
13469
13470         player->audio_stream_changed_cb = NULL;
13471         player->audio_stream_changed_cb_user_param = NULL;
13472
13473         player->sent_bos = FALSE;
13474         player->playback_rate = DEFAULT_PLAYBACK_RATE;
13475
13476         player->doing_seek = FALSE;
13477
13478         player->updated_bitrate_count = 0;
13479         player->total_bitrate = 0;
13480         player->updated_maximum_bitrate_count = 0;
13481         player->total_maximum_bitrate = 0;
13482
13483         player->not_found_demuxer = 0;
13484
13485         player->last_position = 0;
13486         player->duration = 0;
13487         player->http_content_size = 0;
13488         player->not_supported_codec = MISSING_PLUGIN_NONE;
13489         player->can_support_codec = FOUND_PLUGIN_NONE;
13490         player->pending_seek.is_pending = FALSE;
13491         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
13492         player->pending_seek.pos = 0;
13493         player->msg_posted = FALSE;
13494         player->has_many_types = FALSE;
13495         player->is_drm_file = FALSE;
13496         player->max_audio_channels = 0;
13497         player->video_share_api_delta = 0;
13498         player->video_share_clock_delta = 0;
13499         player->sm.keep_last_pos = FALSE;
13500         player->is_subtitle_force_drop = FALSE;
13501         player->play_subtitle = FALSE;
13502         player->use_textoverlay = FALSE;
13503         player->adjust_subtitle_pos = 0;
13504         player->last_multiwin_status = FALSE;
13505         player->has_closed_caption = FALSE;
13506         player->set_mode.media_packet_video_stream = FALSE;
13507         memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
13508         /* recover mode */
13509         player->set_mode.rich_audio = cur_mode;
13510
13511         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
13512         {
13513                 player->bitrate[i] = 0;
13514                 player->maximum_bitrate[i] = 0;
13515         }
13516
13517         /* remove media stream cb (appsrc cb) */
13518         for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++)
13519         {
13520                 player->media_stream_buffer_status_cb[i] = NULL;
13521                 player->media_stream_seek_data_cb[i] = NULL;
13522         }
13523
13524         /* free memory related to audio effect */
13525         MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
13526
13527         if (player->state_tune_caps)
13528         {
13529                 gst_caps_unref(player->state_tune_caps);
13530                 player->state_tune_caps = NULL;
13531         }
13532
13533         if (player->video_cb_probe_id)
13534         {
13535                 GstPad *pad = NULL;
13536
13537                 pad = gst_element_get_static_pad (player->video_fakesink, "sink");
13538
13539                 if (pad) {
13540                         debug_log("release video probe\n");
13541
13542                         /* release audio callback */
13543                         gst_pad_remove_probe (pad, player->video_cb_probe_id);
13544                         player->video_cb_probe_id = 0;
13545                         player->video_stream_cb = NULL;
13546                         player->video_stream_cb_user_param = NULL;
13547                 }
13548         }
13549
13550         MMPLAYER_FLEAVE();
13551 }
13552
13553 static void
13554 __mmplayer_release_misc_post(mm_player_t* player)
13555 {
13556         char *original_uri = NULL;
13557         MMPLAYER_FENTER();
13558
13559         /* player->pipeline is already released before. */
13560
13561         return_if_fail ( player );
13562
13563         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
13564         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
13565
13566         /* clean found parsers */
13567         if (player->parsers)
13568         {
13569                 GList *parsers = player->parsers;
13570                 for ( ;parsers ; parsers = g_list_next(parsers))
13571                 {
13572                         gchar *name = parsers->data;
13573                         MMPLAYER_FREEIF(name);
13574                 }
13575                 g_list_free(player->parsers);
13576                 player->parsers = NULL;
13577         }
13578
13579         /* clean found audio decoders */
13580         if (player->audio_decoders)
13581         {
13582                 GList *a_dec = player->audio_decoders;
13583                 for ( ;a_dec ; a_dec = g_list_next(a_dec))
13584                 {
13585                         gchar *name = a_dec->data;
13586                         MMPLAYER_FREEIF(name);
13587                 }
13588                 g_list_free(player->audio_decoders);
13589                 player->audio_decoders = NULL;
13590         }
13591
13592         /* clean the uri list except original uri */
13593         if (player->uri_info.uri_list)
13594         {
13595                 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
13596
13597                 if (player->attrs)
13598                 {
13599                         mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
13600                         debug_log("restore original uri = %s\n", original_uri);
13601
13602                         if (mmf_attrs_commit(player->attrs))
13603                         {
13604                                 debug_error("failed to commit the original uri.\n");
13605                         }
13606                 }
13607
13608                 GList *uri_list = player->uri_info.uri_list;
13609                 for ( ;uri_list ; uri_list = g_list_next(uri_list))
13610                 {
13611                         gchar *uri = uri_list->data;
13612                         MMPLAYER_FREEIF(uri);
13613                 }
13614                 g_list_free(player->uri_info.uri_list);
13615                 player->uri_info.uri_list = NULL;
13616         }
13617
13618         player->uri_info.uri_idx = 0;
13619         MMPLAYER_FLEAVE();
13620 }
13621
13622 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
13623 {
13624         GstElement *element = NULL;
13625         GstPad *sinkpad;
13626
13627         debug_log("creating %s to plug\n", name);
13628
13629         element = gst_element_factory_make(name, NULL);
13630         if ( ! element )
13631         {
13632                 debug_error("failed to create queue\n");
13633                 return NULL;
13634         }
13635
13636         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
13637         {
13638                 debug_error("failed to set state READY to %s\n", name);
13639                 gst_object_unref (element);
13640                 return NULL;
13641         }
13642
13643         if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
13644         {
13645                 debug_error("failed to add %s\n", name);
13646                 gst_object_unref (element);
13647                 return NULL;
13648         }
13649
13650         sinkpad = gst_element_get_static_pad(element, "sink");
13651
13652         if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
13653         {
13654                 debug_error("failed to link %s\n", name);
13655                 gst_object_unref (sinkpad);
13656                 gst_object_unref (element);
13657                 return NULL;
13658         }
13659
13660         debug_log("linked %s to pipeline successfully\n", name);
13661
13662         gst_object_unref (sinkpad);
13663
13664         return element;
13665 }
13666
13667 static gboolean
13668 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
13669 const char *padname, const GList *templlist)
13670 {
13671         GstPad *pad = NULL;
13672         gboolean has_dynamic_pads = FALSE;
13673         gboolean has_many_types = FALSE;
13674         const char *klass = NULL;
13675         GstStaticPadTemplate *padtemplate = NULL;
13676         GstElementFactory *factory = NULL;
13677         GstElement* queue = NULL;
13678         GstElement* parser = NULL;
13679         GstPad *pssrcpad = NULL;
13680         GstPad *qsrcpad = NULL, *qsinkpad = NULL;
13681         MMPlayerGstElement *mainbin = NULL;
13682         GstStructure* str = NULL;
13683         GstCaps* srccaps = NULL;
13684         GstState target_state = GST_STATE_READY;
13685         gboolean isvideo_decoder = FALSE;
13686         guint q_max_size_time = 0;
13687
13688         MMPLAYER_FENTER();
13689
13690         return_val_if_fail ( player &&
13691                 player->pipeline &&
13692                 player->pipeline->mainbin,
13693                 FALSE );
13694
13695         mainbin = player->pipeline->mainbin;
13696
13697         debug_log("plugging pad %s:%s to newly create %s:%s\n",
13698                         GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
13699                         GST_PAD_NAME( srcpad ),
13700                         GST_ELEMENT_NAME( sinkelement ),
13701                         padname);
13702
13703         factory = gst_element_get_factory(sinkelement);
13704         klass = gst_element_factory_get_klass(factory);
13705
13706         /* check if player can do start continually */
13707         MMPLAYER_CHECK_CMD_IF_EXIT(player);
13708
13709         /* need it to warm up omx before linking to pipeline */
13710         if (g_strrstr(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ), "demux"))
13711         {
13712                 debug_log("get demux caps.\n");
13713                 if (player->state_tune_caps)
13714                 {
13715                         gst_caps_unref(player->state_tune_caps);
13716                         player->state_tune_caps = NULL;
13717                 }
13718                 player->state_tune_caps = gst_caps_copy(gst_pad_get_current_caps(srcpad));
13719         }
13720
13721         /* NOTE : OMX Codec can check if resource is available or not at this state. */
13722         if (g_strrstr(GST_ELEMENT_NAME(sinkelement), "omx"))
13723         {
13724                 if (player->state_tune_caps != NULL)
13725                 {
13726                         debug_log("set demux's caps to omx codec if resource is available");
13727                         if (gst_pad_set_caps(gst_element_get_static_pad(sinkelement, "sink"), player->state_tune_caps))
13728                         {
13729                                 target_state = GST_STATE_PAUSED;
13730                                 isvideo_decoder = TRUE;
13731                                 g_object_set(G_OBJECT(sinkelement), "state-tuning", TRUE, NULL);
13732                         }
13733                         else
13734                         {
13735                                 debug_warning("failed to set caps for state tuning");
13736                         }
13737                 }
13738                 gst_caps_unref(player->state_tune_caps);
13739                 player->state_tune_caps = NULL;
13740         }
13741
13742         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, target_state) )
13743         {
13744                 debug_error("failed to set %d state to %s\n", target_state, GST_ELEMENT_NAME( sinkelement ));
13745                 if (isvideo_decoder)
13746                 {
13747                         gst_element_set_state(sinkelement, GST_STATE_NULL);
13748                         gst_object_unref(G_OBJECT(sinkelement));
13749                         player->keep_detecting_vcodec = TRUE;
13750                 }
13751                 goto ERROR;
13752         }
13753
13754         /* add to pipeline */
13755         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
13756         {
13757                 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
13758                 goto ERROR;
13759         }
13760
13761         debug_log("element klass : %s\n", klass);
13762
13763         /* added to support multi track files */
13764         /* only decoder case and any of the video/audio still need to link*/
13765         if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
13766         {
13767                 gchar *name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
13768
13769                 if (g_strrstr(name, "mpegtsdemux")|| g_strrstr(name, SMOOTH_STREAMING_DEMUX))
13770                 {
13771                         gchar *src_demux_caps_str = NULL;
13772                         gchar *needed_parser = NULL;
13773                         GstCaps *src_demux_caps = NULL;
13774                         gboolean smooth_streaming = FALSE;
13775
13776                         src_demux_caps = gst_pad_query_caps(srcpad, NULL);
13777                         src_demux_caps_str = gst_caps_to_string(src_demux_caps);
13778
13779                         gst_caps_unref(src_demux_caps);
13780
13781                         if (g_strrstr(src_demux_caps_str, "video/x-h264"))
13782                         {
13783                                 if (g_strrstr(name, SMOOTH_STREAMING_DEMUX))
13784                                 {
13785                                         needed_parser = g_strdup("legacyh264parse");
13786                                         smooth_streaming = TRUE;
13787                                 }
13788                                 else
13789                                 {
13790                                         needed_parser = g_strdup("h264parse");
13791                                 }
13792                         }
13793                         else if (g_strrstr(src_demux_caps_str, "video/mpeg"))
13794                         {
13795                                 needed_parser = g_strdup("mpeg4videoparse");
13796                         }
13797                         MMPLAYER_FREEIF(src_demux_caps_str);
13798
13799                         if (needed_parser)
13800                         {
13801                                 parser = __mmplayer_element_create_and_link(player, srcpad, needed_parser);
13802                                 MMPLAYER_FREEIF(needed_parser);
13803
13804                                 if ( !parser )
13805                                 {
13806                                         debug_error("failed to create parser\n");
13807                                 }
13808                                 else
13809                                 {
13810                                         if (smooth_streaming)
13811                                         {
13812                                                 g_object_set (parser, "output-format", 1, NULL); /* NALU/Byte Stream format */
13813                                         }
13814
13815                                         /* update srcpad if parser is created */
13816                                         pssrcpad = gst_element_get_static_pad(parser, "src");
13817                                         srcpad = pssrcpad;
13818                                 }
13819                         }
13820                 }
13821                 MMPLAYER_FREEIF(name);
13822
13823                 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
13824                 if ( ! queue )
13825                 {
13826                         debug_error("failed to create queue\n");
13827                         goto ERROR;
13828                 }
13829
13830                 /* update srcpad to link with decoder */
13831                 qsrcpad = gst_element_get_static_pad(queue, "src");
13832                 srcpad = qsrcpad;
13833
13834                 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
13835
13836                 /* assigning queue handle for futher manipulation purpose */
13837                 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
13838                 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
13839                 {
13840                         mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
13841                         mainbin[MMPLAYER_M_Q1].gst = queue;
13842
13843                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
13844                         {
13845                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", 0 , NULL);
13846                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-buffers", 2, NULL);
13847                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-bytes", 0, NULL);
13848                         }
13849                         else
13850                         {
13851                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
13852                                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
13853                         }
13854                 }
13855                 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
13856                 {
13857                         mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
13858                         mainbin[MMPLAYER_M_Q2].gst = queue;
13859
13860                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
13861                         {
13862                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", 0 , NULL);
13863                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-buffers", 2, NULL);
13864                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-bytes", 0, NULL);
13865                         }
13866                         else
13867                         {
13868                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
13869                                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
13870                         }
13871                 }
13872                 else
13873                 {
13874                         debug_error("Not supporting more then two elementary stream\n");
13875                         g_assert(1);
13876                 }
13877
13878                 pad = gst_element_get_static_pad(sinkelement, padname);
13879
13880                 if ( ! pad )
13881                 {
13882                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
13883                                 padname, GST_ELEMENT_NAME(sinkelement) );
13884
13885                         pad = gst_element_get_static_pad(sinkelement, "sink");
13886                         if ( ! pad )
13887                         {
13888                                 debug_error("failed to get pad(sink) from %s. \n",
13889                                 GST_ELEMENT_NAME(sinkelement) );
13890                                 goto ERROR;
13891                         }
13892                 }
13893
13894                 /*  to check the video/audio type set the proper flag*/
13895                 const gchar *mime_type = NULL;
13896                 {
13897                         srccaps = gst_pad_query_caps(srcpad, NULL);
13898                         if ( !srccaps )
13899                                 goto ERROR;
13900
13901                         str = gst_caps_get_structure( srccaps, 0 );
13902                         if ( ! str )
13903                                 goto ERROR;
13904
13905                         mime_type = gst_structure_get_name(str);
13906                         if ( ! mime_type )
13907                                 goto ERROR;
13908                 }
13909
13910                 /* link queue and decoder. so, it will be queue - decoder. */
13911                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
13912                 {
13913                         gst_object_unref(GST_OBJECT(pad));
13914                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
13915
13916                         /* reconstitute supportable codec */
13917                         if (strstr(mime_type, "video"))
13918                         {
13919                                 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
13920                         }
13921                         else if (strstr(mime_type, "audio"))
13922                         {
13923                                 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
13924                         }
13925                         goto ERROR;
13926                 }
13927
13928                 if (strstr(mime_type, "video"))
13929                 {
13930                         player->videodec_linked = 1;
13931                         debug_msg("player->videodec_linked set to 1\n");
13932
13933                 }
13934                 else if (strstr(mime_type, "audio"))
13935                 {
13936                         player->audiodec_linked = 1;
13937                         debug_msg("player->auddiodec_linked set to 1\n");
13938                 }
13939
13940                 gst_object_unref(GST_OBJECT(pad));
13941                 gst_caps_unref(GST_CAPS(srccaps));
13942                 srccaps = NULL;
13943         }
13944
13945         if ( !MMPLAYER_IS_HTTP_PD(player) )
13946         {
13947                 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
13948                 {
13949                         if (MMPLAYER_IS_HTTP_STREAMING(player))
13950                         {
13951                                 gint64 dur_bytes = 0L;
13952                                 gchar *file_buffering_path = NULL;
13953                                 gboolean use_file_buffer = FALSE;
13954
13955                                 if ( !mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
13956                                 {
13957                                         debug_log("creating http streaming buffering queue\n");
13958
13959                                         queue = gst_element_factory_make("queue2", "queue2");
13960                                         if ( ! queue )
13961                                         {
13962                                                 debug_error ( "failed to create buffering queue element\n" );
13963                                                 goto ERROR;
13964                                         }
13965
13966                                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
13967                                         {
13968                                                 debug_error("failed to set state READY to buffering queue\n");
13969                                                 goto ERROR;
13970                                         }
13971
13972                                         if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
13973                                         {
13974                                                 debug_error("failed to add buffering queue\n");
13975                                                 goto ERROR;
13976                                         }
13977
13978                                         qsinkpad = gst_element_get_static_pad(queue, "sink");
13979                                         qsrcpad = gst_element_get_static_pad(queue, "src");
13980
13981                                         if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
13982                                         {
13983                                                 debug_error("failed to link buffering queue\n");
13984                                                 goto ERROR;
13985                                         }
13986                                         srcpad = qsrcpad;
13987
13988
13989                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
13990                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue;
13991
13992                                         if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
13993                                         {
13994                                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
13995                                                         debug_error("fail to get duration.\n");
13996
13997                                                 if (dur_bytes > 0)
13998                                                 {
13999                                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
14000                                                         file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
14001                                                 }
14002                                                 else
14003                                                 {
14004                                                         dur_bytes = 0;
14005                                                 }
14006                                         }
14007
14008                                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
14009                                         if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
14010                                         {
14011                                                 __mm_player_streaming_set_queue2(player->streamer,
14012                                                         queue,
14013                                                         TRUE,
14014                                                         player->ini.http_max_size_bytes,
14015                                                         player->ini.http_buffering_time,
14016                                                         1.0,
14017                                                         player->ini.http_buffering_limit,
14018                                                         use_file_buffer,
14019                                                         file_buffering_path,
14020                                                         (guint64)dur_bytes);
14021                                         }
14022
14023                                         MMPLAYER_FREEIF(file_buffering_path);
14024                                 }
14025                         }
14026                 }
14027         }
14028         /* if it is not decoder or */
14029         /* in decoder case any of the video/audio still need to link*/
14030         if(!g_strrstr(klass, "Decoder"))
14031         {
14032
14033                 pad = gst_element_get_static_pad(sinkelement, padname);
14034                 if ( ! pad )
14035                 {
14036                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
14037                                         padname, GST_ELEMENT_NAME(sinkelement) );
14038
14039                         pad = gst_element_get_static_pad(sinkelement, "sink");
14040
14041                         if ( ! pad )
14042                         {
14043                                 debug_error("failed to get pad(sink) from %s. \n",
14044                                         GST_ELEMENT_NAME(sinkelement) );
14045                                 goto ERROR;
14046                         }
14047                 }
14048
14049                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
14050                 {
14051                         gst_object_unref(GST_OBJECT(pad));
14052                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
14053                         goto ERROR;
14054                 }
14055
14056                 gst_object_unref(GST_OBJECT(pad));
14057         }
14058
14059         for(;templlist != NULL; templlist = templlist->next)
14060         {
14061                 padtemplate = templlist->data;
14062
14063                 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
14064
14065                 if(     padtemplate->direction != GST_PAD_SRC ||
14066                         padtemplate->presence == GST_PAD_REQUEST        )
14067                         continue;
14068
14069                 switch(padtemplate->presence)
14070                 {
14071                         case GST_PAD_ALWAYS:
14072                         {
14073                                 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
14074                                 GstCaps *caps = gst_pad_query_caps(srcpad, NULL);
14075
14076                                 /* Check whether caps has many types */
14077                                 if ( !gst_caps_is_fixed(caps))
14078                                 {
14079                                         debug_log ("always pad but, caps has many types");
14080                                         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
14081                                         has_many_types = TRUE;
14082                                         break;
14083                                 }
14084
14085                                 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
14086                                 {
14087                                         gst_object_unref(GST_OBJECT(srcpad));
14088                                         gst_caps_unref(GST_CAPS(caps));
14089
14090                                         debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
14091                                         goto ERROR;
14092                                 }
14093
14094                                 gst_caps_unref(GST_CAPS(caps));
14095                                 gst_object_unref(GST_OBJECT(srcpad));
14096
14097                         }
14098                         break;
14099
14100
14101                         case GST_PAD_SOMETIMES:
14102                                 has_dynamic_pads = TRUE;
14103                         break;
14104
14105                         default:
14106                                 break;
14107                 }
14108         }
14109
14110         /* check if player can do start continually */
14111         MMPLAYER_CHECK_CMD_IF_EXIT(player);
14112
14113         if( has_dynamic_pads )
14114         {
14115                 player->have_dynamic_pad = TRUE;
14116                 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
14117                         G_CALLBACK(__mmplayer_add_new_pad), player);
14118
14119                 /* for streaming, more then one typefind will used for each elementary stream
14120                  * so this doesn't mean the whole pipeline completion
14121                  */
14122                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
14123                 {
14124                         MMPLAYER_SIGNAL_CONNECT( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
14125                                 G_CALLBACK(__mmplayer_pipeline_complete), player);
14126                 }
14127         }
14128
14129         if (has_many_types)
14130         {
14131                 GstPad *pad = NULL;
14132
14133                 player->has_many_types = has_many_types;
14134
14135                 pad = gst_element_get_static_pad(sinkelement, "src");
14136                 MMPLAYER_SIGNAL_CONNECT (player, pad, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
14137                 gst_object_unref (GST_OBJECT(pad));
14138         }
14139
14140
14141         /* check if player can do start continually */
14142         MMPLAYER_CHECK_CMD_IF_EXIT(player);
14143
14144         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
14145         {
14146                 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
14147                 goto ERROR;
14148         }
14149
14150         if ( queue )
14151         {
14152                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
14153                 {
14154                         debug_error("failed to set state PAUSED to queue\n");
14155                         goto ERROR;
14156                 }
14157
14158                 queue = NULL;
14159
14160                 gst_object_unref (GST_OBJECT(qsrcpad));
14161                 qsrcpad = NULL;
14162         }
14163
14164         if ( parser )
14165         {
14166                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
14167                 {
14168                         debug_error("failed to set state PAUSED to queue\n");
14169                         goto ERROR;
14170                 }
14171
14172                 parser = NULL;
14173
14174                 gst_object_unref (GST_OBJECT(pssrcpad));
14175                 pssrcpad = NULL;
14176         }
14177
14178         MMPLAYER_FLEAVE();
14179
14180         return TRUE;
14181
14182 ERROR:
14183
14184         if ( queue )
14185         {
14186                 gst_object_unref(GST_OBJECT(qsrcpad));
14187
14188                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
14189                  * You need to explicitly set elements to the NULL state before
14190                  * dropping the final reference, to allow them to clean up.
14191                  */
14192                 gst_element_set_state(queue, GST_STATE_NULL);
14193                 /* And, it still has a parent "player".
14194                  * You need to let the parent manage the object instead of unreffing the object directly.
14195                  */
14196
14197                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
14198                 //gst_object_unref( queue );
14199         }
14200
14201         if ( srccaps )
14202                 gst_caps_unref(GST_CAPS(srccaps));
14203
14204     return FALSE;
14205 }
14206
14207 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
14208 {
14209         const gchar *klass;
14210         //const gchar *name;
14211
14212         /* we only care about element factories */
14213         if (!GST_IS_ELEMENT_FACTORY(feature))
14214                 return FALSE;
14215
14216         /* only parsers, demuxers and decoders */
14217         klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
14218         //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
14219
14220         if( g_strrstr(klass, "Demux") == NULL &&
14221                 g_strrstr(klass, "Codec/Decoder") == NULL &&
14222                 g_strrstr(klass, "Depayloader") == NULL &&
14223                 g_strrstr(klass, "Parse") == NULL)
14224         {
14225                 return FALSE;
14226         }
14227     return TRUE;
14228 }
14229
14230
14231 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
14232 {
14233         mm_player_t* player = (mm_player_t*) data;
14234         GstCaps *caps = NULL;
14235         GstStructure *str = NULL;
14236         const char *name;
14237
14238         MMPLAYER_FENTER();
14239
14240         return_if_fail ( pad )
14241         return_if_fail ( unused )
14242         return_if_fail ( data )
14243
14244         caps = gst_pad_query_caps(pad, NULL);
14245         if ( !caps )
14246                 return;
14247
14248         str = gst_caps_get_structure(caps, 0);
14249         if ( !str )
14250                 return;
14251
14252         name = gst_structure_get_name(str);
14253         if ( !name )
14254                 return;
14255         debug_log("name=%s\n", name);
14256
14257         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
14258         {
14259                 debug_error("failed to autoplug for type (%s)\n", name);
14260                 gst_caps_unref(caps);
14261                 return;
14262         }
14263
14264         gst_caps_unref(caps);
14265
14266         __mmplayer_pipeline_complete( NULL, (gpointer)player );
14267
14268         MMPLAYER_FLEAVE();
14269
14270         return;
14271 }
14272
14273 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
14274 {
14275         GstStructure *str;
14276         gint version = 0;
14277         const char *stream_type;
14278         gchar *version_field = NULL;
14279
14280         MMPLAYER_FENTER();
14281
14282         return_if_fail ( player );
14283         return_if_fail ( caps );
14284
14285         str = gst_caps_get_structure(caps, 0);
14286         if ( !str )
14287                 return;
14288
14289         stream_type = gst_structure_get_name(str);
14290         if ( !stream_type )
14291                 return;
14292
14293
14294         /* set unlinked mime type for downloadable codec */
14295         if (g_str_has_prefix(stream_type, "video/"))
14296         {
14297                 if (g_str_has_prefix(stream_type, "video/mpeg"))
14298                 {
14299                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
14300                         version_field = MM_PLAYER_MPEG_VNAME;
14301                 }
14302                 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
14303                 {
14304                         gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
14305                         version_field = MM_PLAYER_WMV_VNAME;
14306
14307                 }
14308                 else if (g_str_has_prefix(stream_type, "video/x-divx"))
14309                 {
14310                         gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
14311                         version_field = MM_PLAYER_DIVX_VNAME;
14312                 }
14313
14314                 if (version)
14315                 {
14316                         player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
14317                 }
14318                 else
14319                 {
14320                         player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
14321                 }
14322         }
14323         else if (g_str_has_prefix(stream_type, "audio/"))
14324         {
14325                 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
14326                 {
14327                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
14328                         version_field = MM_PLAYER_MPEG_VNAME;
14329                 }
14330                 else if (g_str_has_prefix(stream_type, "audio/x-wma"))
14331                 {
14332                         gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
14333                         version_field = MM_PLAYER_WMA_VNAME;
14334                 }
14335
14336                 if (version)
14337                 {
14338                         player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
14339                 }
14340                 else
14341                 {
14342                         player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
14343                 }
14344         }
14345
14346         MMPLAYER_FLEAVE();
14347 }
14348
14349 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
14350 {
14351         mm_player_t* player = (mm_player_t*) data;
14352         GstCaps *caps = NULL;
14353         GstStructure *str = NULL;
14354         const char *name;
14355
14356         MMPLAYER_FENTER();
14357         return_if_fail ( player );
14358         return_if_fail ( pad );
14359
14360         GST_OBJECT_LOCK (pad);
14361         if ((caps = gst_pad_get_current_caps(pad)))
14362                 gst_caps_ref(caps);
14363         GST_OBJECT_UNLOCK (pad);
14364
14365         if ( NULL == caps )
14366         {
14367                 caps = gst_pad_query_caps(pad, NULL);
14368                 if ( !caps ) return;
14369         }
14370
14371         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
14372
14373         str = gst_caps_get_structure(caps, 0);
14374         if ( !str )
14375                 return;
14376
14377         name = gst_structure_get_name(str);
14378         if ( !name )
14379                 return;
14380
14381         player->num_dynamic_pad++;
14382         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
14383
14384         /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
14385           *     If want to play it, remove this code.
14386           */
14387         if (g_strrstr(name, "application"))
14388         {
14389                 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
14390                 {
14391                         /* If id3/ape tag comes, keep going */
14392                         debug_log("application mime exception : id3/ape tag");
14393                 }
14394                 else
14395                 {
14396                         /* Otherwise, we assume that this stream is subtile. */
14397                         debug_log(" application mime type pad is closed.");
14398                         return;
14399                 }
14400         }
14401         else if (g_strrstr(name, "audio"))
14402         {
14403                 gint samplerate = 0, channels = 0;
14404
14405                 if (player->audiodec_linked)
14406                 {
14407                         gst_caps_unref(caps);
14408                         debug_log("multi tracks. skip to plug");
14409                         return;
14410                 }
14411
14412                 /* set stream information */
14413                 /* if possible, set it here because the caps is not distrubed by resampler. */
14414                 gst_structure_get_int (str, "rate", &samplerate);
14415                 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
14416
14417                 gst_structure_get_int (str, "channels", &channels);
14418                 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
14419
14420                 debug_log("audio samplerate : %d        channels : %d", samplerate, channels);
14421         }
14422         else if (g_strrstr(name, "video"))
14423         {
14424                 gint stype;
14425                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
14426
14427                 /* don't make video because of not required */
14428                 if (stype == MM_DISPLAY_SURFACE_NULL)
14429                 {
14430                         debug_log("no video because it's not required");
14431                         return;
14432                 }
14433
14434                 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
14435         }
14436
14437         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
14438         {
14439                 debug_error("failed to autoplug for type (%s)", name);
14440
14441                 __mmplayer_set_unlinked_mime_type(player, caps);
14442         }
14443
14444         gst_caps_unref(caps);
14445
14446         MMPLAYER_FLEAVE();
14447         return;
14448 }
14449
14450 gboolean
14451 __mmplayer_dump_pipeline_state( mm_player_t* player )
14452 {
14453         GstIterator*iter = NULL;
14454         gboolean done = FALSE;
14455
14456         GValue item = {0, };
14457         GstElement *element = NULL;
14458         GstElementFactory *factory = NULL;
14459
14460         GstState state = GST_STATE_VOID_PENDING;
14461         GstState pending = GST_STATE_VOID_PENDING;
14462         GstClockTime time = 200*GST_MSECOND;
14463
14464         MMPLAYER_FENTER();
14465
14466         return_val_if_fail ( player &&
14467                 player->pipeline &&
14468                 player->pipeline->mainbin,
14469                 FALSE );
14470
14471         iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) );
14472
14473         if ( iter != NULL )
14474         {
14475                 while (!done) {
14476                          switch ( gst_iterator_next (iter, &item) )
14477                          {
14478                            case GST_ITERATOR_OK:
14479                                 element = g_value_get_object(&item);
14480                                 gst_element_get_state(element,&state, &pending,time);
14481
14482                                 factory = gst_element_get_factory (element) ;
14483                                 if (factory)
14484                                 {
14485                                         debug_error("%s:%s : From:%s To:%s   refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(element) ,
14486                                                 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(element));
14487                                 }
14488                                  g_value_reset (&item);
14489                                  break;
14490                            case GST_ITERATOR_RESYNC:
14491                                  gst_iterator_resync (iter);
14492                                  break;
14493                            case GST_ITERATOR_ERROR:
14494                                  done = TRUE;
14495                                  break;
14496                            case GST_ITERATOR_DONE:
14497                                  done = TRUE;
14498                                  break;
14499                          }
14500                 }
14501         }
14502
14503         element = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
14504
14505         gst_element_get_state(element,&state, &pending,time);
14506
14507         factory = gst_element_get_factory (element) ;
14508
14509         if (factory)
14510         {
14511                 debug_error("%s:%s : From:%s To:%s  refcount : %d\n",
14512                         GST_OBJECT_NAME(factory),
14513                         GST_ELEMENT_NAME(element),
14514                         gst_element_state_get_name(state),
14515                         gst_element_state_get_name(pending),
14516                         GST_OBJECT_REFCOUNT_VALUE(element) );
14517         }
14518
14519         g_value_unset(&item);
14520
14521         if ( iter )
14522                 gst_iterator_free (iter);
14523
14524         MMPLAYER_FLEAVE();
14525
14526         return FALSE;
14527 }
14528
14529
14530 gboolean
14531 __mmplayer_check_subtitle( mm_player_t* player )
14532 {
14533         MMHandleType attrs = 0;
14534         char *subtitle_uri = NULL;
14535
14536         MMPLAYER_FENTER();
14537
14538         return_val_if_fail( player, FALSE );
14539
14540         /* get subtitle attribute */
14541         attrs = MMPLAYER_GET_ATTRS(player);
14542         if ( !attrs )
14543                 return FALSE;
14544
14545         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
14546         if ( !subtitle_uri || !strlen(subtitle_uri))
14547                 return FALSE;
14548
14549         debug_log ("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
14550         player->is_external_subtitle_present = TRUE;
14551
14552         MMPLAYER_FLEAVE();
14553
14554         return TRUE;
14555 }
14556
14557 static gboolean
14558 __mmplayer_can_extract_pcm( mm_player_t* player )
14559 {
14560         MMHandleType attrs = 0;
14561         gboolean is_drm = FALSE;
14562         gboolean sound_extraction = FALSE;
14563
14564         return_val_if_fail ( player, FALSE );
14565
14566         attrs = MMPLAYER_GET_ATTRS(player);
14567         if ( !attrs )
14568         {
14569                 debug_error("fail to get attributes.");
14570                 return FALSE;
14571         }
14572
14573         /* check file is drm or not */
14574         if (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm"))
14575                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
14576
14577         /* get sound_extraction property */
14578         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
14579
14580         if ( ! sound_extraction || is_drm )
14581         {
14582                 debug_log("checking pcm extraction mode : %d, drm : %d", sound_extraction, is_drm);
14583                 return FALSE;
14584         }
14585
14586         return TRUE;
14587 }
14588
14589 static gboolean
14590 __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error )
14591 {
14592         MMMessageParamType msg_param;
14593         gchar *msg_src_element;
14594
14595         MMPLAYER_FENTER();
14596
14597         return_val_if_fail( player, FALSE );
14598         return_val_if_fail( error, FALSE );
14599
14600         /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
14601
14602         memset (&msg_param, 0, sizeof(MMMessageParamType));
14603
14604         if ( error->domain == GST_CORE_ERROR )
14605         {
14606                 msg_param.code = __gst_handle_core_error( player, error->code );
14607         }
14608         else if ( error->domain == GST_LIBRARY_ERROR )
14609         {
14610                 msg_param.code = __gst_handle_library_error( player, error->code );
14611         }
14612         else if ( error->domain == GST_RESOURCE_ERROR )
14613         {
14614                 msg_param.code = __gst_handle_resource_error( player, error->code );
14615         }
14616         else if ( error->domain == GST_STREAM_ERROR )
14617         {
14618                 msg_param.code = __gst_handle_stream_error( player, error, message );
14619         }
14620         else
14621         {
14622                 debug_warning("This error domain is not defined.\n");
14623
14624                 /* we treat system error as an internal error */
14625                 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
14626         }
14627
14628         if ( message->src )
14629         {
14630                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
14631
14632                 msg_param.data = (void *) error->message;
14633
14634                 debug_error("-Msg src : [%s]    Domain : [%s]   Error : [%s]  Code : [%d] is tranlated to error code : [0x%x]\n",
14635                         msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg_param.code);
14636         }
14637
14638         /* no error */
14639         if (msg_param.code == MM_ERROR_NONE)
14640                 return TRUE;
14641
14642         /* post error to application */
14643         if ( ! player->msg_posted )
14644         {
14645                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
14646                 /* don't post more if one was sent already */
14647                 player->msg_posted = TRUE;
14648         }
14649         else
14650         {
14651                 debug_log("skip error post because it's sent already.\n");
14652         }
14653
14654         MMPLAYER_FLEAVE();
14655
14656         return TRUE;
14657 }
14658
14659 static gboolean
14660 __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message )
14661 {
14662         debug_log("\n");
14663         MMMessageParamType msg_param;
14664         gchar *msg_src_element = NULL;
14665         GstStructure *s = NULL;
14666         guint error_id = 0;
14667         gchar *error_string = NULL;
14668
14669         MMPLAYER_FENTER();
14670
14671         return_val_if_fail ( player, FALSE );
14672         return_val_if_fail ( message, FALSE );
14673
14674         s = malloc( sizeof(GstStructure) );
14675         memcpy ( s, gst_message_get_structure ( message ), sizeof(GstStructure));
14676
14677         if ( !gst_structure_get_uint (s, "error_id", &error_id) )
14678                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
14679
14680         switch ( error_id )
14681         {
14682                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
14683                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
14684                         break;
14685                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
14686                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
14687                         break;
14688                 case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
14689                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
14690                         break;
14691                 case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
14692                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
14693                         break;
14694                 case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
14695                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
14696                         break;
14697                 case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
14698                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
14699                         break;
14700                 case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
14701                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
14702                         break;
14703                 case MMPLAYER_STREAMING_ERROR_INVALID_URL:
14704                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
14705                         break;
14706                 case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
14707                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
14708                         break;
14709                 case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
14710                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
14711                         break;
14712                 case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
14713                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
14714                         break;
14715                 case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
14716                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
14717                         break;
14718                 case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
14719                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
14720                         break;
14721                 case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
14722                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
14723                         break;
14724                 case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
14725                         msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
14726                         break;
14727                 case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
14728                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
14729                         break;
14730                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
14731                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
14732                         break;
14733                 case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
14734                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
14735                         break;
14736                 case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
14737                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
14738                         break;
14739                 case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
14740                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
14741                         break;
14742                 case MMPLAYER_STREAMING_ERROR_GONE:
14743                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
14744                         break;
14745                 case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
14746                         msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
14747                         break;
14748                 case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
14749                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
14750                         break;
14751                 case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
14752                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
14753                         break;
14754                 case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
14755                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
14756                         break;
14757                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
14758                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
14759                         break;
14760                 case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
14761                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
14762                         break;
14763                 case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
14764                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
14765                         break;
14766                 case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
14767                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
14768                         break;
14769                 case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
14770                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
14771                         break;
14772                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
14773                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
14774                         break;
14775                 case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
14776                         msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
14777                         break;
14778                 case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
14779                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
14780                         break;
14781                 case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
14782                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
14783                         break;
14784                 case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
14785                         msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
14786                         break;
14787                 case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
14788                         msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
14789                         break;
14790                 case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
14791                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
14792                         break;
14793                 case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
14794                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
14795                         break;
14796                 case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
14797                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
14798                         break;
14799                 case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
14800                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
14801                         break;
14802                 case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
14803                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
14804                         break;
14805                 case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
14806                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
14807                         break;
14808                 case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
14809                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
14810                         break;
14811                 case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
14812                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
14813                         break;
14814                 case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
14815                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
14816                         break;
14817                 default:
14818                         {
14819                                 MMPLAYER_FREEIF(s);
14820                                 return MM_ERROR_PLAYER_STREAMING_FAIL;
14821                         }
14822         }
14823
14824         error_string = g_strdup(gst_structure_get_string (s, "error_string"));
14825         if ( error_string )
14826                 msg_param.data = (void *) error_string;
14827
14828         if ( message->src )
14829         {
14830                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
14831
14832                 debug_error("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
14833                         msg_src_element, msg_param.code, (char*)msg_param.data );
14834         }
14835
14836         /* post error to application */
14837         if ( ! player->msg_posted )
14838         {
14839                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
14840
14841                 /* don't post more if one was sent already */
14842                 player->msg_posted = TRUE;
14843         }
14844         else
14845         {
14846                 debug_log("skip error post because it's sent already.\n");
14847         }
14848
14849         MMPLAYER_FREEIF(s);
14850         MMPLAYER_FLEAVE();
14851         g_free(error_string);
14852
14853         return TRUE;
14854
14855 }
14856
14857 static gint
14858 __gst_handle_core_error( mm_player_t* player, int code )
14859 {
14860         gint trans_err = MM_ERROR_NONE;
14861
14862         MMPLAYER_FENTER();
14863
14864         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14865
14866         switch ( code )
14867         {
14868                 case GST_CORE_ERROR_MISSING_PLUGIN:
14869                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
14870                 case GST_CORE_ERROR_STATE_CHANGE:
14871                 case GST_CORE_ERROR_SEEK:
14872                 case GST_CORE_ERROR_NOT_IMPLEMENTED:
14873                 case GST_CORE_ERROR_FAILED:
14874                 case GST_CORE_ERROR_TOO_LAZY:
14875                 case GST_CORE_ERROR_PAD:
14876                 case GST_CORE_ERROR_THREAD:
14877                 case GST_CORE_ERROR_NEGOTIATION:
14878                 case GST_CORE_ERROR_EVENT:
14879                 case GST_CORE_ERROR_CAPS:
14880                 case GST_CORE_ERROR_TAG:
14881                 case GST_CORE_ERROR_CLOCK:
14882                 case GST_CORE_ERROR_DISABLED:
14883                 default:
14884                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
14885                 break;
14886         }
14887
14888         MMPLAYER_FLEAVE();
14889
14890         return trans_err;
14891 }
14892
14893 static gint
14894 __gst_handle_library_error( mm_player_t* player, int code )
14895 {
14896         gint trans_err = MM_ERROR_NONE;
14897
14898         MMPLAYER_FENTER();
14899
14900         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14901
14902         switch ( code )
14903         {
14904                 case GST_LIBRARY_ERROR_FAILED:
14905                 case GST_LIBRARY_ERROR_TOO_LAZY:
14906                 case GST_LIBRARY_ERROR_INIT:
14907                 case GST_LIBRARY_ERROR_SHUTDOWN:
14908                 case GST_LIBRARY_ERROR_SETTINGS:
14909                 case GST_LIBRARY_ERROR_ENCODE:
14910                 default:
14911                         trans_err =  MM_ERROR_PLAYER_INVALID_STREAM;
14912                 break;
14913         }
14914
14915         MMPLAYER_FLEAVE();
14916
14917         return trans_err;
14918 }
14919
14920
14921 static gint
14922 __gst_handle_resource_error( mm_player_t* player, int code )
14923 {
14924         gint trans_err = MM_ERROR_NONE;
14925
14926         MMPLAYER_FENTER();
14927
14928         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14929
14930         switch ( code )
14931         {
14932                 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
14933                         trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
14934                         break;
14935                 case GST_RESOURCE_ERROR_NOT_FOUND:
14936                 case GST_RESOURCE_ERROR_OPEN_READ:
14937                         if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
14938                                 || MMPLAYER_IS_RTSP_STREAMING(player))
14939                         {
14940                                 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
14941                                 break;
14942                         }
14943                 case GST_RESOURCE_ERROR_READ:
14944                         if ( MMPLAYER_IS_HTTP_STREAMING(player) ||  MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
14945                                 || MMPLAYER_IS_RTSP_STREAMING(player))
14946                         {
14947                                 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
14948                                 break;
14949                         }
14950                 case GST_RESOURCE_ERROR_WRITE:
14951                 case GST_RESOURCE_ERROR_FAILED:
14952                 case GST_RESOURCE_ERROR_SEEK:
14953                 case GST_RESOURCE_ERROR_TOO_LAZY:
14954                 case GST_RESOURCE_ERROR_BUSY:
14955                 case GST_RESOURCE_ERROR_OPEN_WRITE:
14956                 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
14957                 case GST_RESOURCE_ERROR_CLOSE:
14958                 case GST_RESOURCE_ERROR_SYNC:
14959                 case GST_RESOURCE_ERROR_SETTINGS:
14960                 default:
14961                         trans_err = MM_ERROR_PLAYER_INTERNAL;
14962                 break;
14963         }
14964
14965         MMPLAYER_FLEAVE();
14966
14967         return trans_err;
14968 }
14969
14970
14971 static gint
14972 __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message )
14973 {
14974         gint trans_err = MM_ERROR_NONE;
14975
14976         MMPLAYER_FENTER();
14977
14978         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14979         return_val_if_fail( error, MM_ERROR_INVALID_ARGUMENT );
14980         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
14981
14982         switch ( error->code )
14983         {
14984                 case GST_STREAM_ERROR_FAILED:
14985                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
14986                 case GST_STREAM_ERROR_DECODE:
14987                 case GST_STREAM_ERROR_WRONG_TYPE:
14988                 case GST_STREAM_ERROR_DECRYPT:
14989                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
14990                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
14991                          trans_err = __gst_transform_gsterror( player, message, error );
14992                 break;
14993
14994                 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
14995                 case GST_STREAM_ERROR_TOO_LAZY:
14996                 case GST_STREAM_ERROR_ENCODE:
14997                 case GST_STREAM_ERROR_DEMUX:
14998                 case GST_STREAM_ERROR_MUX:
14999                 case GST_STREAM_ERROR_FORMAT:
15000                 default:
15001                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
15002                 break;
15003         }
15004
15005         MMPLAYER_FLEAVE();
15006
15007         return trans_err;
15008 }
15009
15010 /* NOTE : decide gstreamer state whether there is some playable track or not. */
15011 static gint
15012 __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error )
15013 {
15014         gchar *src_element_name = NULL;
15015         GstElement *src_element = NULL;
15016         GstElementFactory *factory = NULL;
15017         const gchar* klass = NULL;
15018
15019         MMPLAYER_FENTER();
15020
15021         /* FIXIT */
15022         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
15023         return_val_if_fail ( message->src, MM_ERROR_INVALID_ARGUMENT );
15024         return_val_if_fail ( error, MM_ERROR_INVALID_ARGUMENT );
15025
15026         src_element = GST_ELEMENT_CAST(message->src);
15027         if ( !src_element )
15028                 goto INTERNAL_ERROR;
15029
15030         src_element_name = GST_ELEMENT_NAME(src_element);
15031         if ( !src_element_name )
15032                 goto INTERNAL_ERROR;
15033
15034         factory = gst_element_get_factory(src_element);
15035         if ( !factory )
15036                 goto INTERNAL_ERROR;
15037
15038         klass = gst_element_factory_get_klass(factory);
15039         if ( !klass )
15040                 goto INTERNAL_ERROR;
15041
15042         debug_log("error code=%d, msg=%s, src element=%s, class=%s\n",
15043                         error->code, error->message, src_element_name, klass);
15044
15045         //<-
15046         {
15047                 if (player->selector) {
15048                         int msg_src_pos = 0;
15049                         gint active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
15050                         debug_log ("current  active pad index  -%d", active_pad_index);
15051
15052                         if  (src_element_name) {
15053                                 int idx = 0;
15054
15055                                 if (player->audio_decoders) {
15056                                         GList *adec = player->audio_decoders;
15057                                         for ( ;adec ; adec = g_list_next(adec)) {
15058                                                 gchar *name = adec->data;
15059
15060                                                 debug_log("found audio decoder name  = %s", name);
15061                                                 if (g_strrstr(name, src_element_name)) {
15062                                                         msg_src_pos = idx;
15063                                                         break;
15064                                                 }
15065                                                 idx++;
15066                                         }
15067                                 }
15068                                 debug_log("active pad = %d, error src index = %d", active_pad_index,  msg_src_pos);
15069                         }
15070
15071                         if (active_pad_index != msg_src_pos) {
15072                                 debug_log("skip error because error is posted from no activated track");
15073                                 return MM_ERROR_NONE;
15074                         }
15075                 }
15076         }
15077         //-> temp code
15078
15079         switch ( error->code )
15080         {
15081                 case GST_STREAM_ERROR_DECODE:
15082                 {
15083                         /* Demuxer can't parse one track because it's corrupted.
15084                          * So, the decoder for it is not linked.
15085                          * But, it has one playable track.
15086                          */
15087                         if ( g_strrstr(klass, "Demux") )
15088                         {
15089                                 if ( player->can_support_codec == FOUND_PLUGIN_VIDEO )
15090                                 {
15091                                         return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
15092                                 }
15093                                 else if ( player->can_support_codec == FOUND_PLUGIN_AUDIO )
15094                                 {
15095                                         return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15096                                 }
15097                                 else
15098                                 {
15099                                         if ( player->pipeline->audiobin ) // PCM
15100                                         {
15101                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15102                                         }
15103                                         else
15104                                         {
15105                                                 goto CODEC_NOT_FOUND;
15106                                         }
15107                                 }
15108                         }
15109                         return MM_ERROR_PLAYER_INVALID_STREAM;
15110                 }
15111                 break;
15112
15113                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
15114                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
15115                 case GST_STREAM_ERROR_WRONG_TYPE:
15116                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15117
15118                 case GST_STREAM_ERROR_FAILED:
15119                 {
15120                         /* Decoder Custom Message */
15121                         if ( strstr(error->message, "ongoing") )
15122                         {
15123                                 if ( strncasecmp(klass, "audio", 5) )
15124                                 {
15125                                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) )
15126                                         {
15127                                                 debug_log("Video can keep playing.\n");
15128                                                 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
15129                                         }
15130                                         else
15131                                         {
15132                                                 goto CODEC_NOT_FOUND;
15133                                         }
15134
15135                                 }
15136                                 else if ( strncasecmp(klass, "video", 5) )
15137                                 {
15138                                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) )
15139                                         {
15140                                                 debug_log("Audio can keep playing.\n");
15141                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15142                                         }
15143                                         else
15144                                         {
15145                                                 goto CODEC_NOT_FOUND;
15146                                         }
15147                                 }
15148                         }
15149                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15150                 }
15151                 break;
15152
15153                 case GST_STREAM_ERROR_DECRYPT:
15154                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
15155                 {
15156                         debug_error("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
15157
15158                         if ( strstr(error->message, "rights expired") )
15159                         {
15160                                 return MM_ERROR_PLAYER_DRM_EXPIRED;
15161                         }
15162                         else if ( strstr(error->message, "no rights") )
15163                         {
15164                                 return MM_ERROR_PLAYER_DRM_NO_LICENSE;
15165                         }
15166                         else if ( strstr(error->message, "has future rights") )
15167                         {
15168                                 return MM_ERROR_PLAYER_DRM_FUTURE_USE;
15169                         }
15170                         else if ( strstr(error->message, "opl violation") )
15171                         {
15172                                 return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
15173                         }
15174                         return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
15175                 }
15176                 break;
15177
15178                 default:
15179                 break;
15180         }
15181
15182         MMPLAYER_FLEAVE();
15183
15184         return MM_ERROR_PLAYER_INVALID_STREAM;
15185
15186 INTERNAL_ERROR:
15187         return MM_ERROR_PLAYER_INTERNAL;
15188
15189 CODEC_NOT_FOUND:
15190         debug_log("not found any available codec. Player should be destroyed.\n");
15191         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
15192 }
15193
15194 static void
15195 __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms )
15196 {
15197         return_if_fail( player );
15198
15199
15200         /* post now if delay is zero */
15201         if ( delay_in_ms == 0 || player->set_mode.pcm_extraction)
15202         {
15203                 debug_log("eos delay is zero. posting EOS now\n");
15204                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15205
15206                 if ( player->set_mode.pcm_extraction )
15207                         __mmplayer_cancel_eos_timer(player);
15208
15209                 return;
15210         }
15211
15212         /* cancel if existing */
15213         __mmplayer_cancel_eos_timer( player );
15214
15215         /* init new timeout */
15216         /* NOTE : consider give high priority to this timer */
15217         debug_log("posting EOS message after [%d] msec\n", delay_in_ms);
15218
15219         player->eos_timer = g_timeout_add( delay_in_ms,
15220                 __mmplayer_eos_timer_cb, player );
15221
15222         player->context.global_default = g_main_context_default ();
15223         debug_log("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
15224
15225         /* check timer is valid. if not, send EOS now */
15226         if ( player->eos_timer == 0 )
15227         {
15228                 debug_warning("creating timer for delayed EOS has failed. sending EOS now\n");
15229                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15230         }
15231 }
15232
15233 static void
15234 __mmplayer_cancel_eos_timer( mm_player_t* player )
15235 {
15236         return_if_fail( player );
15237
15238         if ( player->eos_timer )
15239         {
15240                 debug_log("cancel eos timer");
15241                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
15242                 player->eos_timer = 0;
15243         }
15244
15245         return;
15246 }
15247
15248 static gboolean
15249 __mmplayer_eos_timer_cb(gpointer u_data)
15250 {
15251         mm_player_t* player = NULL;
15252         player = (mm_player_t*) u_data;
15253
15254         return_val_if_fail( player, FALSE );
15255
15256         if ( player->play_count > 1 )
15257         {
15258                 gint ret_value = 0;
15259                 ret_value = __gst_set_position( player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
15260                 if (ret_value == MM_ERROR_NONE)
15261                 {
15262                         MMHandleType attrs = 0;
15263                         attrs = MMPLAYER_GET_ATTRS(player);
15264
15265                         /* we successeded to rewind. update play count and then wait for next EOS */
15266                         player->play_count--;
15267
15268                         mm_attrs_set_int_by_name(attrs, "profile_play_count", player->play_count);
15269                         mmf_attrs_commit ( attrs );
15270                 }
15271                 else
15272                 {
15273                         debug_error("seeking to 0 failed in repeat play");
15274                 }
15275         }
15276         else
15277         {
15278                 /* posting eos */
15279                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15280         }
15281
15282         /* we are returning FALSE as we need only one posting */
15283         return FALSE;
15284 }
15285
15286 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force)
15287 {
15288         gint antishock = FALSE;
15289         MMHandleType attrs = 0;
15290
15291         MMPLAYER_FENTER();
15292
15293         return_if_fail ( player && player->pipeline );
15294
15295         /* It should be passed for video only clip */
15296         if ( ! player->pipeline->audiobin )
15297                 return;
15298
15299         if ( ( g_strrstr(player->ini.name_of_audiosink, "avsysaudiosink")) )
15300         {
15301                 attrs = MMPLAYER_GET_ATTRS(player);
15302                 if ( ! attrs )
15303                 {
15304                         debug_error("fail to get attributes.\n");
15305                         return;
15306                 }
15307
15308                 mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock);
15309
15310                 if (player->sm.antishock) {
15311                         antishock = TRUE;
15312                         player->sm.antishock = 0;
15313                 }
15314
15315                 debug_log("setting antishock as (%d)\n", antishock);
15316
15317                 if ( disable_by_force )
15318                 {
15319                         debug_log("but, antishock is disabled by force when is seeked\n");
15320
15321                         antishock = FALSE;
15322                 }
15323
15324                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "fadeup", antishock, NULL);
15325         }
15326
15327         MMPLAYER_FLEAVE();
15328
15329         return;
15330 }
15331
15332
15333 static gboolean
15334 __mmplayer_link_decoder( mm_player_t* player, GstPad *srcpad)
15335 {
15336         const gchar* name = NULL;
15337         GstStructure* str = NULL;
15338         GstCaps* srccaps = NULL;
15339
15340         MMPLAYER_FENTER();
15341
15342         return_val_if_fail( player, FALSE );
15343         return_val_if_fail ( srcpad, FALSE );
15344
15345         /* to check any of the decoder (video/audio) need to be linked  to parser*/
15346         srccaps = gst_pad_query_caps( srcpad, NULL);
15347         if ( !srccaps )
15348                 goto ERROR;
15349
15350         str = gst_caps_get_structure( srccaps, 0 );
15351         if ( ! str )
15352                 goto ERROR;
15353
15354         name = gst_structure_get_name(str);
15355         if ( ! name )
15356                 goto ERROR;
15357
15358         if (strstr(name, "video"))
15359         {
15360                 if(player->videodec_linked)
15361                 {
15362                     debug_msg("Video decoder already linked\n");
15363                         return FALSE;
15364                 }
15365         }
15366         if (strstr(name, "audio"))
15367         {
15368                 if(player->audiodec_linked)
15369                 {
15370                     debug_msg("Audio decoder already linked\n");
15371                         return FALSE;
15372                 }
15373         }
15374
15375         gst_caps_unref( srccaps );
15376
15377         MMPLAYER_FLEAVE();
15378
15379         return TRUE;
15380
15381 ERROR:
15382         if ( srccaps )
15383                 gst_caps_unref( srccaps );
15384
15385         return FALSE;
15386 }
15387
15388 static gboolean
15389 __mmplayer_link_sink( mm_player_t* player , GstPad *srcpad)
15390 {
15391         const gchar* name = NULL;
15392         GstStructure* str = NULL;
15393         GstCaps* srccaps = NULL;
15394
15395         MMPLAYER_FENTER();
15396
15397         return_val_if_fail ( player, FALSE );
15398         return_val_if_fail ( srcpad, FALSE );
15399
15400         /* to check any of the decoder (video/audio) need to be linked  to parser*/
15401         srccaps = gst_pad_query_caps( srcpad, NULL );
15402         if ( !srccaps )
15403                 goto ERROR;
15404
15405         str = gst_caps_get_structure( srccaps, 0 );
15406         if ( ! str )
15407                 goto ERROR;
15408
15409         name = gst_structure_get_name(str);
15410         if ( ! name )
15411                 goto ERROR;
15412
15413         if (strstr(name, "video"))
15414         {
15415                 if(player->videosink_linked)
15416                 {
15417                         debug_msg("Video Sink already linked\n");
15418                         return FALSE;
15419                 }
15420         }
15421         if (strstr(name, "audio"))
15422         {
15423                 if(player->audiosink_linked)
15424                 {
15425                         debug_msg("Audio Sink already linked\n");
15426                         return FALSE;
15427                 }
15428         }
15429         if (strstr(name, "text"))
15430         {
15431                 if(player->textsink_linked)
15432                 {
15433                         debug_msg("Text Sink already linked\n");
15434                         return FALSE;
15435                 }
15436         }
15437
15438         gst_caps_unref( srccaps );
15439
15440         MMPLAYER_FLEAVE();
15441
15442         return TRUE;
15443         //return (!player->videosink_linked || !player->audiosink_linked);
15444
15445 ERROR:
15446         if ( srccaps )
15447                 gst_caps_unref( srccaps );
15448
15449         return FALSE;
15450 }
15451
15452
15453 /* sending event to one of sinkelements */
15454 static gboolean
15455 __gst_send_event_to_sink( mm_player_t* player, GstEvent* event )
15456 {
15457         GstEvent * event2 = NULL;
15458         GList *sinks = NULL;
15459         gboolean res = FALSE;
15460         MMPLAYER_FENTER();
15461
15462         return_val_if_fail( player, FALSE );
15463         return_val_if_fail ( event, FALSE );
15464
15465         if ( player->play_subtitle && !player->use_textoverlay)
15466                 event2 = gst_event_copy((const GstEvent *)event);
15467
15468         sinks = player->sink_elements;
15469         while (sinks)
15470         {
15471                 GstElement *sink = GST_ELEMENT_CAST (sinks->data);
15472
15473                 if (GST_IS_ELEMENT(sink))
15474                 {
15475                         /* keep ref to the event */
15476                         gst_event_ref (event);
15477
15478                         if ( (res = gst_element_send_event (sink, event)) )
15479                         {
15480                                 debug_log("sending event[%s] to sink element [%s] success!\n",
15481                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
15482
15483                                 /* rtsp case, asyn_done is not called after seek during pause state */
15484                                 if (MMPLAYER_IS_RTSP_STREAMING(player))
15485                                 {
15486                                         if (strstr(GST_EVENT_TYPE_NAME(event), "seek"))
15487                                         {
15488                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
15489                                                 {
15490                                                         debug_log("RTSP seek completed, after pause state..\n");
15491                                                         player->doing_seek = FALSE;
15492                                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
15493                                                 }
15494
15495                                         }
15496                                 }
15497
15498                                 if( MMPLAYER_IS_ES_BUFF_SRC(player))
15499                                 {
15500                                         sinks = g_list_next (sinks);
15501                                         continue;
15502                                 }
15503                                 else
15504                                         break;
15505                         }
15506
15507                         debug_log("sending event[%s] to sink element [%s] failed. try with next one.\n",
15508                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
15509                 }
15510
15511                 sinks = g_list_next (sinks);
15512         }
15513
15514 #if 0
15515         if (internal_sub)
15516           request pad name = sink0;
15517         else
15518           request pad name = sink1; // external
15519 #endif
15520
15521         /* Note : Textbin is not linked to the video or audio bin.
15522          * It needs to send the event to the text sink seperatelly.
15523          */
15524          if ( player->play_subtitle && !player->use_textoverlay)
15525          {
15526                 GstElement *text_sink = GST_ELEMENT_CAST (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
15527
15528                 if (GST_IS_ELEMENT(text_sink))
15529                 {
15530                         /* keep ref to the event */
15531                         gst_event_ref (event2);
15532
15533                         if ((res = gst_element_send_event (text_sink, event2)))
15534                         {
15535                                 debug_log("sending event[%s] to subtitle sink element [%s] success!\n",
15536                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
15537                         }
15538                         else
15539                         {
15540                                 debug_error("sending event[%s] to subtitle sink element [%s] failed!\n",
15541                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
15542                         }
15543
15544                         gst_event_unref (event2);
15545                 }
15546          }
15547
15548         gst_event_unref (event);
15549
15550         MMPLAYER_FLEAVE();
15551
15552         return res;
15553 }
15554
15555 static void
15556 __mmplayer_add_sink( mm_player_t* player, GstElement* sink )
15557 {
15558         MMPLAYER_FENTER();
15559
15560         return_if_fail ( player );
15561         return_if_fail ( sink );
15562
15563         player->sink_elements =
15564                 g_list_append(player->sink_elements, sink);
15565
15566         MMPLAYER_FLEAVE();
15567 }
15568
15569 static void
15570 __mmplayer_del_sink( mm_player_t* player, GstElement* sink )
15571 {
15572         MMPLAYER_FENTER();
15573
15574         return_if_fail ( player );
15575         return_if_fail ( sink );
15576
15577         player->sink_elements =
15578                         g_list_remove(player->sink_elements, sink);
15579
15580         MMPLAYER_FLEAVE();
15581 }
15582
15583 static gboolean
15584 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
15585                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
15586                         gint64 cur, GstSeekType stop_type, gint64 stop )
15587 {
15588         GstEvent* event = NULL;
15589         gboolean result = FALSE;
15590
15591         MMPLAYER_FENTER();
15592
15593         return_val_if_fail( player, FALSE );
15594
15595         __mmplayer_drop_subtitle(player, FALSE);
15596
15597         event = gst_event_new_seek (rate, format, flags, cur_type,
15598                 cur, stop_type, stop);
15599
15600         result = __gst_send_event_to_sink( player, event );
15601
15602         MMPLAYER_FLEAVE();
15603
15604         return result;
15605 }
15606
15607 /* NOTE : be careful with calling this api. please refer to below glib comment
15608  * glib comment : Note that there is a bug in GObject that makes this function much
15609  * less useful than it might seem otherwise. Once gobject is disposed, the callback
15610  * will no longer be called, but, the signal handler is not currently disconnected.
15611  * If the instance is itself being freed at the same time than this doesn't matter,
15612  * since the signal will automatically be removed, but if instance persists,
15613  * then the signal handler will leak. You should not remove the signal yourself
15614  * because in a future versions of GObject, the handler will automatically be
15615  * disconnected.
15616  *
15617  * It's possible to work around this problem in a way that will continue to work
15618  * with future versions of GObject by checking that the signal handler is still
15619  * connected before disconnected it:
15620  *
15621  *  if (g_signal_handler_is_connected (instance, id))
15622  *    g_signal_handler_disconnect (instance, id);
15623  */
15624 static void
15625 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
15626 {
15627         GList* sig_list = NULL;
15628         MMPlayerSignalItem* item = NULL;
15629
15630         MMPLAYER_FENTER();
15631
15632         return_if_fail( player );
15633
15634         debug_log("release signals type : %d", type);
15635
15636         if ((type < MM_PLAYER_SIGNAL_TYPE_AUTOPLUG) || (type >= MM_PLAYER_SIGNAL_TYPE_ALL))
15637         {
15638                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
15639                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
15640                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
15641                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
15642                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
15643                 return;
15644         }
15645
15646         sig_list = player->signals[type];
15647
15648         for ( ; sig_list; sig_list = sig_list->next )
15649         {
15650                 item = sig_list->data;
15651
15652                 if ( item && item->obj && GST_IS_ELEMENT(item->obj) )
15653                 {
15654                         if ( g_signal_handler_is_connected ( item->obj, item->sig ) )
15655                         {
15656                                 g_signal_handler_disconnect ( item->obj, item->sig );
15657                         }
15658                 }
15659
15660                 MMPLAYER_FREEIF( item );
15661         }
15662
15663         g_list_free ( player->signals[type] );
15664         player->signals[type] = NULL;
15665
15666         MMPLAYER_FLEAVE();
15667
15668         return;
15669 }
15670
15671 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
15672 {
15673         mm_player_t* player = 0;
15674         int prev_display_surface_type = 0;
15675         void *prev_display_overlay = NULL;
15676         const gchar *klass = NULL;
15677         gchar *cur_videosink_name = NULL;
15678         int ret = 0;
15679         int i = 0;
15680         int num_of_dec = 2; /* DEC1, DEC2 */
15681
15682         MMPLAYER_FENTER();
15683
15684         return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
15685         return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
15686
15687         player = MM_PLAYER_CAST(handle);
15688
15689         if (surface_type < MM_DISPLAY_SURFACE_X && surface_type > MM_DISPLAY_SURFACE_EVAS)
15690         {
15691                 debug_error("Not support this surface type(%d) for changing vidoesink", surface_type);
15692                 MMPLAYER_FLEAVE();
15693                 return MM_ERROR_INVALID_ARGUMENT;
15694         }
15695
15696         /* load previous attributes */
15697         if (player->attrs)
15698         {
15699                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &prev_display_surface_type);
15700                 mm_attrs_get_data_by_name (player->attrs, "display_overlay", &prev_display_overlay);
15701                 debug_log("[0: X surface, 1: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
15702                 if (prev_display_surface_type == surface_type)
15703                 {
15704                         debug_log("incoming display surface type is same as previous one, do nothing..");
15705                         MMPLAYER_FLEAVE();
15706                         return MM_ERROR_NONE;
15707                 }
15708         }
15709         else
15710         {
15711                 debug_error("failed to load attributes");
15712                 MMPLAYER_FLEAVE();
15713                 return MM_ERROR_PLAYER_INTERNAL;
15714         }
15715
15716         /* check videosink element is created */
15717         if (!player->pipeline || !player->pipeline->videobin ||
15718                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
15719         {
15720                 debug_log("videosink element is not yet ready");
15721
15722                 /* videobin is not created yet, so we just set attributes related to display surface */
15723                 debug_log("store display attribute for given surface type(%d)", surface_type);
15724                 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
15725                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
15726                 if ( mmf_attrs_commit ( player->attrs ) )
15727                 {
15728                         debug_error("failed to commit attribute");
15729                         MMPLAYER_FLEAVE();
15730                         return MM_ERROR_PLAYER_INTERNAL;
15731                 }
15732                 MMPLAYER_FLEAVE();
15733                 return MM_ERROR_NONE;
15734         }
15735         else
15736         {
15737                 /* get player command status */
15738                 if ( !(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE) )
15739                 {
15740                         debug_error("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command",player->cmd);
15741                         MMPLAYER_FLEAVE();
15742                         return MM_ERROR_PLAYER_INVALID_STATE;
15743                 }
15744
15745                 /* get a current videosink name */
15746                 cur_videosink_name = GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
15747
15748                 /* surface change */
15749                 for ( i = 0 ; i < num_of_dec ; i++)
15750                 {
15751                         if ( player->pipeline->mainbin &&
15752                                 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst )
15753                         {
15754                                 klass = gst_element_factory_get_klass( gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) );
15755                                 if ((g_strrstr(klass, "Codec/Decoder/Video")))
15756                                 {
15757                                         if ( !strncmp(cur_videosink_name, "x", 1) && (surface_type == MM_DISPLAY_SURFACE_EVAS) )
15758                                         {
15759                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_evas, surface_type, display_overlay);
15760                                                 if (ret)
15761                                                 {
15762                                                         goto ERROR_CASE;
15763                                                 }
15764                                                 else
15765                                                 {
15766                                                         debug_warning("success to changing display surface(%d)",surface_type);
15767                                                         MMPLAYER_FLEAVE();
15768                                                         return MM_ERROR_NONE;
15769                                                 }
15770                                         }
15771                                         else if (!strncmp(cur_videosink_name, "evas", 4) && (surface_type == MM_DISPLAY_SURFACE_X) )
15772                                         {
15773                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_x, surface_type, display_overlay);
15774                                                 if (ret)
15775                                                 {
15776                                                         goto ERROR_CASE;
15777                                                 }
15778                                                 else
15779                                                 {
15780                                                         debug_warning("success to changing display surface(%d)",surface_type);
15781                                                         MMPLAYER_FLEAVE();
15782                                                         return MM_ERROR_NONE;
15783                                                 }
15784                                         }
15785                                         else
15786                                         {
15787                                                 debug_error("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface",surface_type, cur_videosink_name);
15788                                                 ret = MM_ERROR_PLAYER_INTERNAL;
15789                                                 goto ERROR_CASE;
15790                                         }
15791                                 }
15792                         }
15793                 }
15794         }
15795
15796 ERROR_CASE:
15797         /* rollback to previous attributes */
15798         mm_attrs_set_int_by_name (player->attrs, "display_surface_type", prev_display_surface_type);
15799         mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(void*));
15800         if ( mmf_attrs_commit ( player->attrs ) )
15801         {
15802                 debug_error("failed to commit attributes to rollback");
15803                 MMPLAYER_FLEAVE();
15804                 return MM_ERROR_PLAYER_INTERNAL;
15805         }
15806         MMPLAYER_FLEAVE();
15807         return ret;
15808 }
15809
15810 /* NOTE : It does not support some use cases, eg using colorspace converter */
15811 int
15812 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
15813 {
15814         GstPad *src_pad_dec = NULL;
15815         GstPad *sink_pad_videosink = NULL;
15816         GstPad *sink_pad_videobin = NULL;
15817         GstClock *clock = NULL;
15818         MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
15819         int ret = MM_ERROR_NONE;
15820         gboolean is_audiobin_created = TRUE;
15821
15822         MMPLAYER_FENTER();
15823
15824         return_val_if_fail(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
15825         return_val_if_fail(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
15826         return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
15827
15828         debug_log("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
15829         debug_log("surface type(%d), display overlay(%x)", surface_type, display_overlay);
15830
15831         /* get information whether if audiobin is created */
15832         if ( !player->pipeline->audiobin ||
15833                      !player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
15834         {
15835                 debug_warning("audiobin is null, this video content may not have audio data");
15836                 is_audiobin_created = FALSE;
15837         }
15838
15839         /* get current state of player */
15840         previous_state = MMPLAYER_CURRENT_STATE(player);
15841         debug_log("previous state(%d)", previous_state);
15842
15843
15844         /* get src pad of decoder and block it */
15845         src_pad_dec = gst_element_get_static_pad (GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
15846         if (!src_pad_dec)
15847         {
15848                 debug_error("failed to get src pad from decode in mainbin");
15849                 return MM_ERROR_PLAYER_INTERNAL;
15850         }
15851
15852         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
15853         {
15854                 debug_warning("trying to block pad(video)");
15855 //              if (!gst_pad_set_blocked (src_pad_dec, TRUE))
15856                 gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
15857                         NULL, NULL, NULL);
15858
15859                 {
15860                         debug_error("failed to set block pad(video)");
15861                         return MM_ERROR_PLAYER_INTERNAL;
15862                 }
15863                 debug_warning("pad is blocked(video)");
15864         }
15865         else
15866         {
15867                 /* no data flows, so no need to do pad_block */
15868                 if (player->doing_seek) {
15869                         debug_warning("not completed seek(%d), do nothing", player->doing_seek);
15870                 }
15871                 debug_log("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
15872         }
15873
15874         /* remove pad */
15875         if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
15876                 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin))))
15877         {
15878                 debug_error("failed to remove previous ghost_pad for videobin");
15879                 return MM_ERROR_PLAYER_INTERNAL;
15880         }
15881
15882         /* change state of videobin to NULL */
15883         debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
15884         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
15885         if (ret != GST_STATE_CHANGE_SUCCESS)
15886         {
15887                 debug_error("failed to change state of videobin to NULL");
15888                 return MM_ERROR_PLAYER_INTERNAL;
15889         }
15890
15891         /* unlink between decoder and videobin and remove previous videosink from videobin */
15892         GST_ELEMENT_UNLINK(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst),GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
15893         if ( !gst_bin_remove (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst)) )
15894         {
15895                 debug_error("failed to remove former videosink from videobin");
15896                 return MM_ERROR_PLAYER_INTERNAL;
15897         }
15898
15899         __mmplayer_del_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
15900
15901         /* create a new videosink and add it to videobin */
15902         player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, videosink_element);
15903         gst_bin_add (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
15904         __mmplayer_add_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
15905         g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
15906
15907         /* save attributes */
15908         if (player->attrs)
15909         {
15910                 /* set a new display surface type */
15911                 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
15912                 /* set a new diplay overlay */
15913                 switch (surface_type)
15914                 {
15915                         case MM_DISPLAY_SURFACE_X:
15916                                 debug_log("save attributes related to display surface to X : xid = %d", *(int*)display_overlay);
15917                                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
15918                                 break;
15919                         case MM_DISPLAY_SURFACE_EVAS:
15920                                 debug_log("save attributes related to display surface to EVAS : evas image object = %x", display_overlay);
15921                                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(void*));
15922                                 break;
15923                         default:
15924                                 debug_error("invalid type(%d) for changing display surface",surface_type);
15925                                 MMPLAYER_FLEAVE();
15926                                 return MM_ERROR_INVALID_ARGUMENT;
15927                 }
15928                 if ( mmf_attrs_commit ( player->attrs ) )
15929                 {
15930                         debug_error("failed to commit");
15931                         MMPLAYER_FLEAVE();
15932                         return MM_ERROR_PLAYER_INTERNAL;
15933                 }
15934         }
15935         else
15936         {
15937                 debug_error("player->attrs is null, failed to save attributes");
15938                 MMPLAYER_FLEAVE();
15939                 return MM_ERROR_PLAYER_INTERNAL;
15940         }
15941
15942         /* update video param */
15943         if ( MM_ERROR_NONE != _mmplayer_update_video_param( player ) )
15944         {
15945                 debug_error("failed to update video param");
15946                 return MM_ERROR_PLAYER_INTERNAL;
15947         }
15948
15949         /* change state of videobin to READY */
15950         debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
15951         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
15952         if (ret != GST_STATE_CHANGE_SUCCESS)
15953         {
15954                 debug_error("failed to change state of videobin to READY");
15955                 return MM_ERROR_PLAYER_INTERNAL;
15956         }
15957
15958         /* change ghostpad */
15959         sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
15960         if ( !sink_pad_videosink )
15961         {
15962                 debug_error("failed to get sink pad from videosink element");
15963                 return MM_ERROR_PLAYER_INTERNAL;
15964         }
15965         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
15966         if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE))
15967         {
15968                 debug_error("failed to set active to ghost_pad");
15969                 return MM_ERROR_PLAYER_INTERNAL;
15970         }
15971         if ( FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
15972         {
15973                 debug_error("failed to change ghostpad for videobin");
15974                 return MM_ERROR_PLAYER_INTERNAL;
15975         }
15976         gst_object_unref(sink_pad_videosink);
15977
15978         /* link decoder with videobin */
15979         sink_pad_videobin = gst_element_get_static_pad( GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
15980         if ( !sink_pad_videobin )
15981         {
15982                 debug_error("failed to get sink pad from videobin");
15983                 return MM_ERROR_PLAYER_INTERNAL;
15984         }
15985         if ( GST_PAD_LINK_OK != GST_PAD_LINK(src_pad_dec, sink_pad_videobin) )
15986         {
15987                 debug_error("failed to link");
15988                 return MM_ERROR_PLAYER_INTERNAL;
15989         }
15990         gst_object_unref(sink_pad_videobin);
15991
15992         /* clock setting for a new videosink plugin */
15993         /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
15994                         so we set it from audiosink plugin or pipeline(system clock) */
15995         if (!is_audiobin_created)
15996         {
15997                 debug_warning("audiobin is not created, get clock from pipeline..");
15998                 clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
15999         }
16000         else
16001         {
16002                 clock = GST_ELEMENT_CLOCK (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
16003         }
16004         if (clock)
16005         {
16006                 GstClockTime now;
16007                 GstClockTime base_time;
16008                 debug_log("set the clock to videosink");
16009                 gst_element_set_clock (GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
16010                 clock = GST_ELEMENT_CLOCK (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
16011                 if (clock)
16012                 {
16013                         debug_log("got clock of videosink");
16014                         now = gst_clock_get_time ( clock );
16015                         base_time = GST_ELEMENT_CAST (player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
16016                         debug_log ("at time %" GST_TIME_FORMAT ", base %"
16017                                         GST_TIME_FORMAT, GST_TIME_ARGS (now), GST_TIME_ARGS (base_time));
16018                 }
16019                 else
16020                 {
16021                         debug_error("failed to get clock of videosink after setting clock");
16022                         return MM_ERROR_PLAYER_INTERNAL;
16023                 }
16024         }
16025         else
16026         {
16027                 debug_warning("failed to get clock, maybe it is the time before first playing");
16028         }
16029
16030         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
16031         {
16032                 /* change state of videobin to PAUSED */
16033                 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
16034                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
16035                 if (ret != GST_STATE_CHANGE_FAILURE)
16036                 {
16037                         debug_warning("change state of videobin to PLAYING, ret(%d)", ret);
16038                 }
16039                 else
16040                 {
16041                         debug_error("failed to change state of videobin to PLAYING");
16042                         return MM_ERROR_PLAYER_INTERNAL;
16043                 }
16044
16045                 /* release blocked and unref src pad of video decoder */
16046                 #if 0
16047                 if (!gst_pad_set_blocked (src_pad_dec, FALSE))
16048                 {
16049                         debug_error("failed to set pad blocked FALSE(video)");
16050                         return MM_ERROR_PLAYER_INTERNAL;
16051                 }
16052                 #endif
16053                 debug_warning("pad is unblocked(video)");
16054         }
16055         else
16056         {
16057                 if (player->doing_seek) {
16058                         debug_warning("not completed seek(%d)", player->doing_seek);
16059                 }
16060                 /* change state of videobin to PAUSED */
16061                 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
16062                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
16063                 if (ret != GST_STATE_CHANGE_FAILURE)
16064                 {
16065                         debug_warning("change state of videobin to PAUSED, ret(%d)", ret);
16066                 }
16067                 else
16068                 {
16069                         debug_error("failed to change state of videobin to PLAYING");
16070                         return MM_ERROR_PLAYER_INTERNAL;
16071                 }
16072
16073                 /* already skipped pad block */
16074                 debug_log("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
16075         }
16076
16077         /* do get/set position for new videosink plugin */
16078         {
16079                 unsigned long position = 0;
16080                 gint64 pos_msec = 0;
16081
16082                 debug_log("do get/set position for new videosink plugin");
16083                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
16084                 {
16085                         debug_error("failed to get position");
16086                         return MM_ERROR_PLAYER_INTERNAL;
16087                 }
16088 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
16089                 /* accurate seek */
16090                 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE ))
16091                 {
16092                         debug_error("failed to set position");
16093                         return MM_ERROR_PLAYER_INTERNAL;
16094                 }
16095 #else
16096                 /* key unit seek */
16097                 pos_msec = position * G_GINT64_CONSTANT(1000000);
16098                 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
16099                                 GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT ),
16100                                                         GST_SEEK_TYPE_SET, pos_msec,
16101                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
16102                 if ( !ret  )
16103                 {
16104                         debug_error("failed to set position");
16105                         return MM_ERROR_PLAYER_INTERNAL;
16106                 }
16107 #endif
16108         }
16109
16110         if (src_pad_dec)
16111         {
16112                 gst_object_unref (src_pad_dec);
16113         }
16114         debug_log("success to change sink");
16115
16116         MMPLAYER_FLEAVE();
16117
16118         return MM_ERROR_NONE;
16119 }
16120
16121
16122 /* Note : if silent is true, then subtitle would not be displayed. :*/
16123 int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent)
16124 {
16125         mm_player_t* player = (mm_player_t*) hplayer;
16126
16127         MMPLAYER_FENTER();
16128
16129         /* check player handle */
16130         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16131
16132         player->set_mode.subtitle_off = silent;
16133
16134         debug_log("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
16135
16136         MMPLAYER_FLEAVE();
16137
16138         return MM_ERROR_NONE;
16139 }
16140
16141 int _mmplayer_remove_audio_parser_decoder(mm_player_t* player,GstPad *inpad)
16142 {
16143         int result = MM_ERROR_NONE;
16144         GstPad *peer = NULL,*pad = NULL;
16145         GstElement *Element = NULL;
16146         MMPlayerGstElement* mainbin = NULL;
16147         mainbin = player->pipeline->mainbin;
16148
16149         #if 0
16150         if(!gst_pad_set_blocked(inpad,TRUE))
16151         {
16152                 result = MM_ERROR_PLAYER_INTERNAL;
16153                 goto EXIT;
16154         }
16155         #endif
16156         gst_pad_add_probe(inpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
16157                         NULL, NULL, NULL);
16158
16159         /*Getting pad connected to demuxer audio pad */
16160         peer = gst_pad_get_peer(inpad);
16161         /* Disconnecting Demuxer and its peer plugin [audio] */
16162         if(peer)
16163         {
16164                 if(!gst_pad_unlink(inpad,peer))
16165                 {
16166                         result = MM_ERROR_PLAYER_INTERNAL;
16167                         goto EXIT;
16168                 }
16169         }
16170         else
16171         {
16172                 result = MM_ERROR_PLAYER_INTERNAL;
16173                 goto EXIT;
16174         }
16175         /*Removing elements between Demuxer and audiobin*/
16176         while(peer != NULL)
16177         {
16178                 gchar *Element_name = NULL;
16179                 gchar *factory_name = NULL;
16180                 GList *elements = NULL;
16181                 GstElementFactory *factory = NULL;
16182                 /*Getting peer element*/
16183                 Element = gst_pad_get_parent_element(peer);
16184                 if(Element == NULL)
16185                 {
16186                         gst_object_unref(peer);
16187                         result = MM_ERROR_PLAYER_INTERNAL;
16188                         break;
16189                 }
16190
16191                 Element_name = gst_element_get_name(Element);
16192                 factory = gst_element_get_factory(Element);
16193                 /*checking the element is audio bin*/
16194                 if(!strcmp(Element_name,"audiobin"))
16195                 {
16196                         gst_object_unref(peer);
16197                         result = MM_ERROR_NONE;
16198             g_free(Element_name);
16199                         break;
16200                 }
16201                 factory_name = GST_OBJECT_NAME(factory);
16202                 pad = gst_element_get_static_pad(Element,"src");
16203                 if(pad == NULL)
16204                 {
16205                         result = MM_ERROR_PLAYER_INTERNAL;
16206             g_free(Element_name);
16207                         break;
16208                 }
16209                 gst_object_unref(peer);
16210                 peer = gst_pad_get_peer(pad);
16211                 if(peer)
16212                 {
16213                         if(!gst_pad_unlink(pad,peer))
16214                         {
16215                                 gst_object_unref(peer);
16216                                 gst_object_unref(pad);
16217                                 result = MM_ERROR_PLAYER_INTERNAL;
16218                 g_free(Element_name);
16219                                 break;
16220                         }
16221                 }
16222                 elements = player->parsers;
16223                 /* Removing the element form the list*/
16224                 for ( ; elements; elements = g_list_next(elements))
16225                 {
16226                         Element_name = elements->data;
16227                         if(g_strrstr(Element_name,factory_name))
16228                         {
16229                                 player->parsers = g_list_remove(player->parsers,elements->data);
16230                         }
16231                 }
16232                 gst_element_set_state(Element,GST_STATE_NULL);
16233                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),Element);
16234                 gst_object_unref(pad);
16235                 if(Element == mainbin[MMPLAYER_M_Q1].gst)
16236                 {
16237                         mainbin[MMPLAYER_M_Q1].gst = NULL;
16238                 }
16239                 else if(Element == mainbin[MMPLAYER_M_Q2].gst)
16240                 {
16241                         mainbin[MMPLAYER_M_Q2].gst = NULL;
16242                 }
16243                 else if(Element == mainbin[MMPLAYER_M_DEC1].gst)
16244                 {
16245                         mainbin[MMPLAYER_M_DEC1].gst = NULL;
16246                 }
16247                 else if(Element == mainbin[MMPLAYER_M_DEC2].gst)
16248                 {
16249                         mainbin[MMPLAYER_M_DEC2].gst = NULL;
16250                 }
16251                 gst_object_unref(Element);
16252         }
16253 EXIT:
16254         return result;
16255 }
16256
16257 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
16258 {
16259         MMPlayerGstElement* mainbin = NULL;
16260         MMPlayerGstElement* textbin = NULL;
16261         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
16262         GstState current_state = GST_STATE_VOID_PENDING;
16263         GstState element_state = GST_STATE_VOID_PENDING;
16264         GstState element_pending_state = GST_STATE_VOID_PENDING;
16265         gint64 time = 0;
16266         GstEvent *event = NULL;
16267         int result = MM_ERROR_NONE;
16268
16269         GstClock *curr_clock = NULL;
16270         GstClockTime base_time, start_time, curr_time;
16271
16272
16273         MMPLAYER_FENTER();
16274
16275         /* check player handle */
16276         return_val_if_fail ( player && player->pipeline , MM_ERROR_PLAYER_NOT_INITIALIZED);
16277
16278         if (!(player->pipeline->mainbin) || !(player->pipeline->textbin))
16279         {
16280                 debug_error("Pipeline is not in proper state\n");
16281                 result = MM_ERROR_PLAYER_NOT_INITIALIZED;
16282                 goto EXIT;
16283         }
16284
16285         mainbin = player->pipeline->mainbin;
16286         textbin = player->pipeline->textbin;
16287
16288         current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
16289
16290         // sync clock with current pipeline
16291         curr_clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
16292         curr_time = gst_clock_get_time (curr_clock);
16293
16294         base_time = gst_element_get_base_time (GST_ELEMENT_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
16295         start_time = gst_element_get_start_time (GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
16296
16297         debug_log ("base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
16298                 GST_TIME_ARGS (base_time), GST_TIME_ARGS (start_time), GST_TIME_ARGS (curr_time));
16299
16300         if (current_state > GST_STATE_READY)
16301         {
16302                 // sync state with current pipeline
16303                 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
16304                 gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_PAUSED);
16305                 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
16306
16307                 ret = gst_element_get_state (mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
16308                 if ( GST_STATE_CHANGE_FAILURE == ret )
16309                 {
16310                         debug_error("fail to state change.\n");
16311                 }
16312         }
16313
16314         gst_element_set_base_time (textbin[MMPLAYER_T_BIN].gst, base_time);
16315         gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
16316
16317         if (curr_clock)
16318         {
16319                 gst_element_set_clock (textbin[MMPLAYER_T_BIN].gst, curr_clock);
16320                 gst_object_unref (curr_clock);
16321         }
16322
16323         // seek to current position
16324         if (!gst_element_query_position (mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time))
16325         {
16326                 result = MM_ERROR_PLAYER_INVALID_STATE;
16327                 debug_error("gst_element_query_position failed, invalid state\n");
16328                 goto EXIT;
16329         }
16330
16331         debug_log("seek time = %lld\n", time);
16332         event = gst_event_new_seek (1.0, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
16333         if (event)
16334         {
16335                 __gst_send_event_to_sink(player, event);
16336         }
16337         else
16338         {
16339                 result = MM_ERROR_PLAYER_INTERNAL;
16340                 debug_error("gst_event_new_seek failed\n");
16341                 goto EXIT;
16342         }
16343
16344         // sync state with current pipeline
16345         gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
16346         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
16347         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
16348
16349 EXIT:
16350         return result;
16351 }
16352
16353 static int
16354 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
16355 {
16356         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
16357         GstState current_state = GST_STATE_VOID_PENDING;
16358
16359         MMHandleType attrs = 0;
16360         MMPlayerGstElement* mainbin = NULL;
16361         MMPlayerGstElement* textbin = NULL;
16362
16363         gchar* subtitle_uri = NULL;
16364         int result = MM_ERROR_NONE;
16365         const gchar *charset = NULL;
16366
16367         MMPLAYER_FENTER();
16368
16369         /* check player handle */
16370         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16371         return_val_if_fail( filepath, MM_ERROR_COMMON_INVALID_ARGUMENT );
16372
16373         if (!(player->pipeline) || !(player->pipeline->mainbin))
16374         {
16375                 result = MM_ERROR_PLAYER_INVALID_STATE;
16376                 debug_error("Pipeline is not in proper state\n");
16377                 goto EXIT;
16378         }
16379
16380         mainbin = player->pipeline->mainbin;
16381         textbin = player->pipeline->textbin;
16382
16383         current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
16384         if (current_state < GST_STATE_READY)
16385         {
16386                 result = MM_ERROR_PLAYER_INVALID_STATE;
16387                 debug_error("Pipeline is not in proper state\n");
16388                 goto EXIT;
16389         }
16390
16391         attrs = MMPLAYER_GET_ATTRS(player);
16392         if (!attrs)
16393         {
16394                 debug_error("cannot get content attribute\n");
16395                 result = MM_ERROR_PLAYER_INTERNAL;
16396                 goto EXIT;
16397         }
16398
16399         mm_attrs_get_string_by_name (attrs, "subtitle_uri", &subtitle_uri);
16400         if (!subtitle_uri || strlen(subtitle_uri) < 1)
16401         {
16402                 debug_error("subtitle uri is not proper filepath\n");
16403                 result = MM_ERROR_PLAYER_INVALID_URI;
16404                 goto EXIT;
16405         }
16406
16407         debug_log("old subtitle file path is [%s]\n", subtitle_uri);
16408         debug_log("new subtitle file path is [%s]\n", filepath);
16409
16410         if (!strcmp (filepath, subtitle_uri))
16411         {
16412                 debug_log("No need to swtich subtitle, as input filepath is same as current filepath\n");
16413                 goto EXIT;
16414         }
16415         else
16416         {
16417                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16418                 if (mmf_attrs_commit(player->attrs))
16419                 {
16420                         debug_error("failed to commit.\n");
16421                         goto EXIT;
16422                 }
16423         }
16424
16425         //gst_pad_set_blocked_async(src-srcpad, TRUE)
16426
16427         ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
16428         if (ret != GST_STATE_CHANGE_SUCCESS)
16429         {
16430                 debug_error("failed to change state of textbin to READY");
16431                 result = MM_ERROR_PLAYER_INTERNAL;
16432                 goto EXIT;
16433         }
16434
16435         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_READY);
16436         if (ret != GST_STATE_CHANGE_SUCCESS)
16437         {
16438                 debug_error("failed to change state of subparse to READY");
16439                 result = MM_ERROR_PLAYER_INTERNAL;
16440                 goto EXIT;
16441         }
16442
16443         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
16444         if (ret != GST_STATE_CHANGE_SUCCESS)
16445         {
16446                 debug_error("failed to change state of filesrc to READY");
16447                 result = MM_ERROR_PLAYER_INTERNAL;
16448                 goto EXIT;
16449         }
16450
16451         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
16452
16453         charset = util_get_charset(filepath);
16454         if (charset)
16455         {
16456                 debug_log ("detected charset is %s\n", charset );
16457                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
16458         }
16459
16460         result = _mmplayer_sync_subtitle_pipeline(player);
16461
16462 EXIT:
16463         MMPLAYER_FLEAVE();
16464         return result;
16465 }
16466
16467 /* API to switch between external subtitles */
16468 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
16469 {
16470         int result = MM_ERROR_NONE;
16471         mm_player_t* player = (mm_player_t*)hplayer;
16472
16473         MMPLAYER_FENTER();
16474
16475         /* check player handle */
16476         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16477
16478         if (!player->pipeline)  // IDLE state
16479         {
16480                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16481                 if (mmf_attrs_commit(player->attrs))
16482                 {
16483                         debug_error("failed to commit.\n");
16484                         result= MM_ERROR_PLAYER_INTERNAL;
16485                 }
16486         }
16487         else    // curr state <> IDLE (READY, PAUSE, PLAYING..)
16488         {
16489                 if ( filepath == NULL )
16490                         return MM_ERROR_COMMON_INVALID_ARGUMENT;
16491
16492                 if (!__mmplayer_check_subtitle(player))
16493                 {
16494                         mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16495                         if (mmf_attrs_commit(player->attrs))
16496                         {
16497                                 debug_error("failed to commit.\n");
16498                                 result = MM_ERROR_PLAYER_INTERNAL;
16499                         }
16500
16501                         if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
16502                                 debug_error("fail to create subtitle src\n");
16503
16504                         result = _mmplayer_sync_subtitle_pipeline(player);
16505                 }
16506                 else
16507                 {
16508                         result = __mmplayer_change_external_subtitle_language(player, filepath);
16509                 }
16510         }
16511
16512         MMPLAYER_FLEAVE();
16513         return result;
16514 }
16515
16516 static int
16517 __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index)
16518 {
16519         int result = MM_ERROR_NONE;
16520         gchar* change_pad_name = NULL;
16521         GstPad* sinkpad = NULL;
16522         MMPlayerGstElement* mainbin = NULL;
16523         enum MainElementID elemId = MMPLAYER_M_NUM;
16524         GstCaps* caps = NULL;
16525         gint total_track_num = 0;
16526
16527         MMPLAYER_FENTER();
16528
16529         return_val_if_fail (player && player->pipeline && player->pipeline->mainbin,
16530                                                                                                         MM_ERROR_PLAYER_NOT_INITIALIZED);
16531
16532         debug_log ("Change Track(%d) to %d\n", type, index);
16533
16534         mainbin = player->pipeline->mainbin;
16535
16536         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
16537         {
16538                 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
16539         }
16540         else if (type == MM_PLAYER_TRACK_TYPE_TEXT)
16541         {
16542                 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
16543         }
16544         else
16545         {
16546                 debug_error ("Track Type Error\n");
16547                 goto EXIT;
16548         }
16549
16550         if (mainbin[elemId].gst == NULL)
16551         {
16552                 result = MM_ERROR_PLAYER_NO_OP;
16553                 debug_log ("Req track doesn't exist\n");
16554                 goto EXIT;
16555         }
16556
16557         total_track_num = player->selector[type].total_track_num;
16558         if (total_track_num <= 0)
16559         {
16560                 result = MM_ERROR_PLAYER_NO_OP;
16561                 debug_log ("Language list is not available \n");
16562                 goto EXIT;
16563         }
16564
16565         if ((index < 0) || (index >= total_track_num))
16566         {
16567                 result = MM_ERROR_INVALID_ARGUMENT;
16568                 debug_log ("Not a proper index : %d \n", index);
16569                 goto EXIT;
16570         }
16571
16572         /*To get the new pad from the selector*/
16573         change_pad_name = g_strdup_printf ("sink_%u", index);
16574         if (change_pad_name == NULL)
16575         {
16576                 result = MM_ERROR_PLAYER_INTERNAL;
16577                 debug_log ("Pad does not exists\n");
16578                 goto EXIT;
16579         }
16580
16581         debug_log ("new active pad name: %s\n", change_pad_name);
16582
16583         sinkpad = gst_element_get_static_pad (mainbin[elemId].gst, change_pad_name);
16584         if (sinkpad == NULL)
16585         {
16586                 debug_log ("sinkpad is NULL");
16587                 result = MM_ERROR_PLAYER_INTERNAL;
16588                 goto EXIT;
16589         }
16590
16591         debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
16592         g_object_set (mainbin[elemId].gst, "active-pad", sinkpad, NULL);
16593
16594         caps = gst_pad_get_current_caps(sinkpad);
16595         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
16596
16597         if (sinkpad)
16598                 gst_object_unref (sinkpad);
16599
16600         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
16601         {
16602                 __mmplayer_set_audio_attrs (player, caps);
16603         }
16604
16605 EXIT:
16606
16607         MMPLAYER_FREEIF(change_pad_name);
16608         return result;
16609 }
16610
16611 int _mmplayer_change_track_language (MMHandleType hplayer, MMPlayerTrackType type, int index)
16612 {
16613         int result = MM_ERROR_NONE;
16614         mm_player_t* player = NULL;
16615         MMPlayerGstElement* mainbin = NULL;
16616
16617         gint current_active_index = 0;
16618
16619         GstState current_state = GST_STATE_VOID_PENDING;
16620         GstEvent* event = NULL;
16621         gint64 time = 0;
16622
16623         MMPLAYER_FENTER();
16624
16625         player = (mm_player_t*)hplayer;
16626         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
16627
16628         if (!player->pipeline)
16629         {
16630                 debug_error ("Track %d pre setting -> %d\n", type, index);
16631
16632                 player->selector[type].active_pad_index = index;
16633                 goto EXIT;
16634         }
16635
16636         mainbin = player->pipeline->mainbin;
16637
16638         current_active_index = player->selector[type].active_pad_index;
16639
16640         /*If index is same as running index no need to change the pad*/
16641         if (current_active_index == index)
16642         {
16643                 goto EXIT;
16644         }
16645
16646         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time))
16647         {
16648                 result = MM_ERROR_PLAYER_INVALID_STATE;
16649                 goto EXIT;
16650         }
16651
16652         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
16653         if (current_state < GST_STATE_PAUSED)
16654         {
16655                 result = MM_ERROR_PLAYER_INVALID_STATE;
16656                 debug_warning ("Pipeline not in porper state\n");
16657                 goto EXIT;
16658         }
16659
16660         result = __mmplayer_change_selector_pad(player, type, index);
16661         if (result != MM_ERROR_NONE)
16662         {
16663                 debug_error ("change selector pad error\n");
16664                 goto EXIT;
16665         }
16666
16667         player->selector[type].active_pad_index = index;
16668
16669         if (current_state == GST_STATE_PLAYING)
16670         {
16671                 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);
16672                 if (event)
16673                 {
16674                         __gst_send_event_to_sink (player, event);
16675                 }
16676                 else
16677                 {
16678                         result = MM_ERROR_PLAYER_INTERNAL;
16679                         goto EXIT;
16680                 }
16681         }
16682
16683 EXIT:
16684         return result;
16685 }
16686
16687 int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent)
16688 {
16689         mm_player_t* player = (mm_player_t*) hplayer;
16690
16691         MMPLAYER_FENTER();
16692
16693         /* check player handle */
16694         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16695
16696         *silent = player->set_mode.subtitle_off;
16697
16698         debug_log("subtitle is %s.\n", silent ? "ON" : "OFF");
16699
16700         MMPLAYER_FLEAVE();
16701
16702         return MM_ERROR_NONE;
16703 }
16704
16705 const gchar *
16706 __get_state_name ( int state )
16707 {
16708         switch ( state )
16709         {
16710                 case MM_PLAYER_STATE_NULL:
16711                         return "NULL";
16712                 case MM_PLAYER_STATE_READY:
16713                         return "READY";
16714                 case MM_PLAYER_STATE_PAUSED:
16715                         return "PAUSED";
16716                 case MM_PLAYER_STATE_PLAYING:
16717                         return "PLAYING";
16718                 case MM_PLAYER_STATE_NONE:
16719                         return "NONE";
16720                 default:
16721                         return "INVAID";
16722         }
16723 }
16724
16725 gboolean
16726 __is_rtsp_streaming ( mm_player_t* player )
16727 {
16728         return_val_if_fail ( player, FALSE );
16729
16730         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP ) ? TRUE : FALSE;
16731 }
16732
16733 gboolean
16734 __is_wfd_streaming ( mm_player_t* player )
16735 {
16736   return_val_if_fail ( player, FALSE );
16737
16738   return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_WFD ) ? TRUE : FALSE;
16739 }
16740
16741 static gboolean
16742 __is_http_streaming ( mm_player_t* player )
16743 {
16744         return_val_if_fail ( player, FALSE );
16745
16746         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP ) ? TRUE : FALSE;
16747 }
16748
16749 static gboolean
16750 __is_streaming ( mm_player_t* player )
16751 {
16752         return_val_if_fail ( player, FALSE );
16753
16754   return ( __is_http_progressive_down( player ) || __is_rtsp_streaming ( player ) || __is_wfd_streaming ( player ) || __is_http_streaming ( player )
16755           || __is_http_live_streaming ( player ) || __is_dash_streaming ( player ) || __is_smooth_streaming(player) ) ? TRUE : FALSE;
16756 }
16757
16758 gboolean
16759 __is_live_streaming ( mm_player_t* player )
16760 {
16761         return_val_if_fail ( player, FALSE );
16762
16763         return ( __is_rtsp_streaming ( player ) && player->streaming_type == STREAMING_SERVICE_LIVE ) ? TRUE : FALSE;
16764 }
16765
16766 static gboolean
16767 __is_http_live_streaming( mm_player_t* player )
16768 {
16769         return_val_if_fail( player, FALSE );
16770
16771         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS ) ? TRUE : FALSE;
16772 }
16773
16774 static gboolean
16775 __is_dash_streaming ( mm_player_t* player )
16776 {
16777         return_val_if_fail ( player, FALSE );
16778
16779         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH ) ? TRUE : FALSE;
16780 }
16781
16782 static gboolean
16783 __is_smooth_streaming ( mm_player_t* player )
16784 {
16785         return_val_if_fail ( player, FALSE );
16786
16787         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_SS ) ? TRUE : FALSE;
16788 }
16789
16790
16791 static gboolean
16792 __is_http_progressive_down(mm_player_t* player)
16793 {
16794         return_val_if_fail( player, FALSE );
16795
16796         return ((player->pd_mode) ? TRUE:FALSE);
16797 }
16798
16799 gboolean
16800 __is_es_buff_src( mm_player_t* player )
16801 {
16802         return_val_if_fail ( player, FALSE );
16803
16804         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF) ? TRUE : FALSE;
16805 }
16806
16807 gboolean
16808 __has_suffix(mm_player_t* player, const gchar* suffix)
16809 {
16810         return_val_if_fail( player, FALSE );
16811         return_val_if_fail( suffix, FALSE );
16812
16813         gboolean ret = FALSE;
16814         gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
16815         gchar* t_suffix = g_ascii_strdown(suffix, -1);
16816
16817         if ( g_str_has_suffix(player->profile.uri, suffix) )
16818         {
16819                 ret = TRUE;
16820         }
16821
16822         MMPLAYER_FREEIF(t_url);
16823         MMPLAYER_FREEIF(t_suffix);
16824
16825         return ret;
16826 }
16827
16828 int
16829 _mmplayer_set_display_zoom(MMHandleType hplayer, float level, int x, int y)
16830 {
16831         mm_player_t* player = (mm_player_t*) hplayer;
16832
16833         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16834
16835         MMPLAYER_VIDEO_SINK_CHECK(player);
16836
16837         debug_log("setting display zoom level = %f, offset = %d, %d", level, x, y);
16838
16839         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", level, "zoom-pos-x", x, "zoom-pos-y", y, NULL);
16840
16841         return MM_ERROR_NONE;
16842 }
16843 int
16844 _mmplayer_get_display_zoom(MMHandleType hplayer, float *level, int *x, int *y)
16845 {
16846
16847         mm_player_t* player = (mm_player_t*) hplayer;
16848         float _level = 0.0;
16849         int _x = 0;
16850         int _y = 0;
16851
16852         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16853
16854         MMPLAYER_VIDEO_SINK_CHECK(player);
16855
16856         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", &_level, "zoom-pos-x", &_x, "zoom-pos-y", &_y, NULL);
16857
16858         debug_log("display zoom level = %f, start off x = %d, y = %d", _level, _x, _y);
16859
16860         *level = _level;
16861         *x = _x;
16862         *y = _y;
16863
16864         return MM_ERROR_NONE;
16865 }
16866
16867 int
16868 _mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
16869 {
16870         mm_player_t* player = (mm_player_t*) hplayer;
16871
16872         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
16873
16874         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL)
16875         {
16876                 MMPLAYER_PRINT_STATE(player);
16877                 debug_error("wrong-state : can't set the download mode to parse");
16878                 return MM_ERROR_PLAYER_INVALID_STATE;
16879         }
16880
16881         debug_log("set video hub download mode to %s", (mode)?"ON":"OFF");
16882         player->video_hub_download_mode = mode;
16883
16884         return MM_ERROR_NONE;
16885 }
16886
16887 int
16888 _mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
16889 {
16890         mm_player_t* player = (mm_player_t*) hplayer;
16891
16892         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
16893
16894         debug_log("enable sync handler : %s", (enable)?"ON":"OFF");
16895         player->sync_handler = enable;
16896
16897         return MM_ERROR_NONE;
16898 }
16899
16900 int
16901 _mmplayer_use_system_clock (MMHandleType hplayer)
16902 {
16903         mm_player_t* player = (mm_player_t*) hplayer;
16904
16905         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
16906
16907         debug_log("change clock provider to system");
16908
16909         // to use system clock
16910         player->ini.provide_clock_for_movie = FALSE;
16911         player->ini.provide_clock_for_music = FALSE;
16912
16913         return MM_ERROR_NONE;
16914 }
16915
16916 int
16917 _mmplayer_set_video_share_master_clock( MMHandleType hplayer,
16918                                         long long clock,
16919                                         long long clock_delta,
16920                                         long long video_time,
16921                                         long long media_clock,
16922                                         long long audio_time)
16923 {
16924         mm_player_t* player = (mm_player_t*) hplayer;
16925         MMPlayerGstElement* mainbin = NULL;
16926         GstClockTime start_time_audio = 0, start_time_video = 0;
16927         GstClockTimeDiff base_time = 0, new_base_time = 0;
16928         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
16929         gint64 api_delta = 0;
16930         gint64 position = 0, position_delta = 0;
16931         gint64 adj_base_time = 0;
16932         GstClock *curr_clock = NULL;
16933         GstClockTime curr_time = 0;
16934         gboolean query_ret = TRUE;
16935         int result = MM_ERROR_NONE;
16936
16937         MMPLAYER_FENTER();
16938
16939         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
16940         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
16941         return_val_if_fail ( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
16942
16943         // debug_log("in(us) : %lld, %lld, %lld, %lld, %lld", clock, clock_delta, video_time, media_clock, audio_time);
16944
16945         if ((video_time < 0) || (player->doing_seek))
16946         {
16947                 debug_log("skip setting master clock.  %lld", video_time);
16948                 goto EXIT;
16949         }
16950
16951         mainbin = player->pipeline->mainbin;
16952
16953         curr_clock = gst_pipeline_get_clock (GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
16954         curr_time = gst_clock_get_time (curr_clock);
16955
16956         current_state = MMPLAYER_CURRENT_STATE(player);
16957
16958         if ( current_state == MM_PLAYER_STATE_PLAYING )
16959                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
16960
16961         if ( ( current_state != MM_PLAYER_STATE_PLAYING ) ||
16962                  ( !query_ret ))
16963         {
16964                 position = player->last_position;
16965                 debug_log ("query fail. %lld", position);
16966         }
16967
16968         clock*= GST_USECOND;
16969         clock_delta *= GST_USECOND;
16970
16971         api_delta = clock - curr_time;
16972         if ((player->video_share_api_delta == 0 ) || (player->video_share_api_delta > api_delta))
16973         {
16974                 player->video_share_api_delta = api_delta;
16975         }
16976         else
16977         {
16978                 clock_delta += (api_delta - player->video_share_api_delta);
16979         }
16980
16981         if ((player->video_share_clock_delta == 0 ) || (player->video_share_clock_delta > clock_delta))
16982         {
16983                 player->video_share_clock_delta = (gint64)clock_delta;
16984
16985                 position_delta = (position/GST_USECOND) - video_time;
16986                 position_delta *= GST_USECOND;
16987
16988                 adj_base_time = position_delta;
16989                 debug_log ("video_share_clock_delta = %lld, adj = %lld", player->video_share_clock_delta, adj_base_time);
16990
16991         }
16992         else
16993         {
16994                 gint64 new_play_time = 0;
16995                 gint64 network_delay =0;
16996
16997                 video_time *= GST_USECOND;
16998
16999                 network_delay = clock_delta - player->video_share_clock_delta;
17000                 new_play_time = video_time + network_delay;
17001
17002                 adj_base_time = position - new_play_time;
17003
17004                 debug_log ("%lld(delay) = %lld - %lld / %lld(adj) = %lld(slave_pos) - %lld(master_pos) - %lld(delay)",
17005                         network_delay, clock_delta, player->video_share_clock_delta, adj_base_time, position, video_time, network_delay);
17006         }
17007
17008         /* Adjust Current Stream Time with base_time of sink
17009          * 1. Set Start time to CLOCK NONE, to control the base time by MSL
17010          * 2. Set new base time
17011          *    if adj_base_time is positive value, the stream time will be decreased.
17012          * 3. If seek event is occurred, the start time will be reset. */
17013         if ((player->pipeline->audiobin) &&
17014                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
17015         {
17016                 start_time_audio = gst_element_get_start_time (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
17017
17018                 if (start_time_audio != GST_CLOCK_TIME_NONE)
17019                 {
17020                         debug_log ("audio sink : gst_element_set_start_time -> NONE");
17021                         gst_element_set_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, GST_CLOCK_TIME_NONE);
17022                 }
17023
17024                 base_time = gst_element_get_base_time (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
17025         }
17026
17027         if ((player->pipeline->videobin) &&
17028                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
17029         {
17030                 start_time_video = gst_element_get_start_time (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
17031
17032                 if (start_time_video != GST_CLOCK_TIME_NONE)
17033                 {
17034                         debug_log ("video sink : gst_element_set_start_time -> NONE");
17035                         gst_element_set_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst, GST_CLOCK_TIME_NONE);
17036                 }
17037
17038                 // if videobin exist, get base_time from videobin.
17039                 base_time = gst_element_get_base_time (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
17040         }
17041
17042         new_base_time = base_time + adj_base_time;
17043
17044         if ((player->pipeline->audiobin) &&
17045                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
17046                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), (GstClockTime)new_base_time);
17047
17048         if ((player->pipeline->videobin) &&
17049                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
17050                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), (GstClockTime)new_base_time);
17051
17052 EXIT:
17053         MMPLAYER_FLEAVE();
17054
17055         return result;
17056 }
17057
17058 int
17059 _mmplayer_get_video_share_master_clock( MMHandleType hplayer,
17060                                         long long *video_time,
17061                                         long long *media_clock,
17062                                         long long *audio_time)
17063 {
17064         mm_player_t* player = (mm_player_t*) hplayer;
17065         MMPlayerGstElement* mainbin = NULL;
17066         GstClock *curr_clock = NULL;
17067         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
17068         gint64 position = 0;
17069         gboolean query_ret = TRUE;
17070
17071         MMPLAYER_FENTER();
17072
17073         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
17074         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
17075         return_val_if_fail ( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
17076
17077         return_val_if_fail ( video_time, MM_ERROR_COMMON_INVALID_ARGUMENT );
17078         return_val_if_fail ( media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT );
17079         return_val_if_fail ( audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT );
17080
17081         mainbin = player->pipeline->mainbin;
17082
17083         curr_clock = gst_pipeline_get_clock (GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
17084
17085         current_state = MMPLAYER_CURRENT_STATE(player);
17086
17087         if ( current_state != MM_PLAYER_STATE_PAUSED )
17088                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
17089
17090         if ( ( current_state == MM_PLAYER_STATE_PAUSED ) ||
17091                  ( !query_ret ))
17092         {
17093                 position = player->last_position;
17094         }
17095
17096         *media_clock = *video_time = *audio_time = (position/GST_USECOND);
17097
17098         debug_log("media_clock: %lld, video_time: %lld (us)", *media_clock, *video_time);
17099
17100         if (curr_clock)
17101                 gst_object_unref (curr_clock);
17102
17103         MMPLAYER_FLEAVE();
17104
17105         return MM_ERROR_NONE;
17106 }
17107
17108 int
17109 _mmplayer_get_video_rotate_angle(MMHandleType hplayer, int *angle)
17110 {
17111         mm_player_t* player = (mm_player_t*) hplayer;
17112         int org_angle = 0;
17113
17114         MMPLAYER_FENTER();
17115
17116         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17117         return_val_if_fail ( angle, MM_ERROR_COMMON_INVALID_ARGUMENT );
17118
17119         if (player->v_stream_caps)
17120         {
17121                 GstStructure *str = NULL;
17122
17123                 str = gst_caps_get_structure (player->v_stream_caps, 0);
17124                 if ( !gst_structure_get_int (str, "orientation", &org_angle))
17125                 {
17126                         debug_log ("missing 'orientation' field in video caps");
17127                 }
17128         }
17129
17130         debug_log("orientation: %d", org_angle);
17131         *angle = org_angle;
17132
17133         MMPLAYER_FLEAVE();
17134         return MM_ERROR_NONE;
17135 }
17136
17137 gboolean
17138 __mmplayer_is_streaming(mm_player_t* player)
17139 {
17140         gboolean result = FALSE;
17141
17142         MMPLAYER_FENTER();
17143
17144         return_val_if_fail (player, FALSE);
17145         result = __is_streaming (player) ;
17146
17147         MMPLAYER_FLEAVE();
17148         return result;
17149 }
17150
17151 static gboolean
17152 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
17153 {
17154         return_val_if_fail (player, FALSE);
17155         return_val_if_fail (element, FALSE);
17156
17157         gchar *factory_name = GST_OBJECT_NAME (gst_element_get_factory(element));
17158         gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
17159
17160         int idx = 0;
17161
17162         for ( idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++ )
17163         {
17164                 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx]))
17165                 {
17166                         debug_log("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
17167                         mm_player_dump_t *dump_s;
17168                         dump_s = g_malloc (sizeof(mm_player_dump_t));
17169
17170                         if (dump_s == NULL)
17171                         {
17172                                 debug_error ("malloc fail");
17173                                 return FALSE;
17174                         }
17175
17176                         dump_s->dump_element_file = NULL;
17177                         dump_s->dump_pad = NULL;
17178                         dump_s->dump_pad = gst_element_get_static_pad (element, "sink");
17179
17180                         if (dump_s->dump_pad)
17181                         {
17182                                 memset (dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
17183                                 sprintf (dump_file_name, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
17184                                 dump_s->dump_element_file = fopen(dump_file_name,"w+");
17185                                 dump_s->probe_handle_id = gst_pad_add_probe (dump_s->dump_pad, GST_PAD_PROBE_TYPE_BUFFER, __mmplayer_dump_buffer_probe_cb, dump_s->dump_element_file, NULL);
17186                                 /* add list for removed buffer probe and close FILE */
17187                                 player->dump_list = g_list_append (player->dump_list, dump_s);
17188                                 debug_log ("%s sink pad added buffer probe for dump", factory_name);
17189                                 return TRUE;
17190                         }
17191                         else
17192                         {
17193                                 g_free(dump_s);
17194                                 dump_s = NULL;
17195                                 debug_error ("failed to get %s sink pad added", factory_name);
17196                         }
17197
17198
17199                 }
17200         }
17201         return FALSE;
17202 }
17203
17204 static GstPadProbeReturn
17205 __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data)
17206 {
17207         FILE *dump_data = (FILE *) u_data;
17208 //      int written = 0;
17209         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
17210         GstMapInfo probe_info = GST_MAP_INFO_INIT;
17211
17212         return_val_if_fail ( dump_data, FALSE );
17213
17214         gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
17215
17216 //      debug_log ("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS( GST_BUFFER_TIMESTAMP(buffer)));
17217
17218         fwrite ( probe_info.data, 1, probe_info.size , dump_data);
17219
17220         return GST_PAD_PROBE_OK;
17221 }
17222
17223 static void
17224 __mmplayer_release_dump_list (GList *dump_list)
17225 {
17226         if (dump_list)
17227         {
17228                 GList *d_list = dump_list;
17229                 for ( ;d_list ; d_list = g_list_next(d_list))
17230                 {
17231                         mm_player_dump_t *dump_s = d_list->data;
17232                         if (dump_s->dump_pad)
17233                         {
17234                                 if (dump_s->probe_handle_id)
17235                                 {
17236                                         gst_pad_remove_probe (dump_s->dump_pad, dump_s->probe_handle_id);
17237                                 }
17238
17239                         }
17240                         if (dump_s->dump_element_file)
17241                         {
17242                                 fclose(dump_s->dump_element_file);
17243                                 dump_s->dump_element_file = NULL;
17244                         }
17245                         MMPLAYER_FREEIF(dump_s);
17246                 }
17247                 g_list_free(dump_list);
17248                 dump_list = NULL;
17249         }
17250 }
17251
17252 int
17253 _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
17254 {
17255         mm_player_t* player = (mm_player_t*) hplayer;
17256
17257         MMPLAYER_FENTER();
17258
17259         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17260         return_val_if_fail ( exist, MM_ERROR_INVALID_ARGUMENT );
17261
17262         *exist = player->has_closed_caption;
17263
17264         MMPLAYER_FLEAVE();
17265
17266         return MM_ERROR_NONE;
17267 }
17268
17269 int
17270 _mmplayer_enable_media_packet_video_stream(MMHandleType hplayer, bool enable)
17271 {
17272         mm_player_t* player = (mm_player_t*) hplayer;
17273
17274         MMPLAYER_FENTER();
17275
17276         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
17277         return_val_if_fail (enable == TRUE || enable == FALSE, MM_ERROR_INVALID_ARGUMENT);
17278         if(enable)
17279                 player->bufmgr = tbm_bufmgr_init(-1);
17280         else {
17281                 tbm_bufmgr_deinit(player->bufmgr);
17282                 player->bufmgr = NULL;
17283         }
17284
17285         player->set_mode.media_packet_video_stream = enable;
17286
17287         MMPLAYER_FLEAVE();
17288
17289         return MM_ERROR_NONE;
17290 }
17291
17292 void * _mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer)
17293 {
17294         void * ret = NULL
17295         MMPLAYER_FENTER();
17296         /* increase ref count of gst buffer */
17297         if (buffer)
17298                 ret = gst_buffer_ref((GstBuffer *)buffer);
17299
17300         MMPLAYER_FLEAVE();
17301         return ret;
17302 }
17303
17304 void _mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer)
17305 {
17306         MMPLAYER_FENTER();
17307         if (buffer) {
17308                 gst_buffer_unref((GstBuffer *)buffer);
17309                 buffer = NULL;
17310         }
17311         MMPLAYER_FLEAVE();
17312 }
17313
17314 void
17315 __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data)
17316 {
17317         mm_player_t *player  = (mm_player_t*)user_data;
17318         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
17319
17320         return_if_fail ( player );
17321
17322         debug_msg("app-src: feed audio\n");
17323
17324         if (player->media_stream_buffer_status_cb[type])
17325         {
17326                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
17327         }
17328 }
17329
17330 void
17331 __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data)
17332 {
17333         mm_player_t *player  = (mm_player_t*)user_data;
17334         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
17335
17336         return_if_fail ( player );
17337
17338         debug_msg("app-src: feed video\n");
17339
17340         if (player->media_stream_buffer_status_cb[type])
17341         {
17342                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
17343         }
17344 }
17345
17346 void
17347 __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data)
17348 {
17349         mm_player_t *player  = (mm_player_t*)user_data;
17350         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
17351
17352         return_if_fail ( player );
17353
17354         debug_msg("app-src: feed subtitle\n");
17355
17356         if (player->media_stream_buffer_status_cb[type])
17357         {
17358                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
17359         }
17360 }
17361
17362 void
17363 __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data)
17364 {
17365         mm_player_t *player  = (mm_player_t*)user_data;
17366         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
17367
17368         return_if_fail ( player );
17369
17370         debug_msg("app-src: audio buffer is full.\n");
17371
17372         if (player->media_stream_buffer_status_cb[type])
17373         {
17374                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
17375         }
17376 }
17377
17378 void
17379 __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data)
17380 {
17381         mm_player_t *player  = (mm_player_t*)user_data;
17382         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
17383
17384         return_if_fail ( player );
17385
17386         debug_msg("app-src: video buffer is full.\n");
17387
17388         if (player->media_stream_buffer_status_cb[type])
17389         {
17390                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
17391         }
17392 }
17393
17394 gboolean
17395 __gst_seek_audio_data (GstElement * appsrc, guint64 position, gpointer user_data)
17396 {
17397         mm_player_t *player  = (mm_player_t*)user_data;
17398         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
17399
17400         return_val_if_fail( player, FALSE );
17401
17402         debug_log("app-src: seek audio data\n");
17403
17404         if (player->media_stream_seek_data_cb[type])
17405         {
17406                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
17407         }
17408
17409         return TRUE;
17410 }
17411
17412 gboolean
17413 __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data)
17414 {
17415         mm_player_t *player  = (mm_player_t*)user_data;
17416         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
17417
17418         return_val_if_fail( player, FALSE );
17419
17420         debug_log("app-src: seek video data\n");
17421
17422         if (player->media_stream_seek_data_cb[type])
17423         {
17424                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
17425         }
17426
17427         return TRUE;
17428 }
17429
17430 gboolean
17431 __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data)
17432 {
17433         mm_player_t *player  = (mm_player_t*)user_data;
17434         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
17435
17436         return_val_if_fail( player, FALSE );
17437
17438         debug_log("app-src: seek subtitle data\n");
17439
17440         if (player->media_stream_seek_data_cb[type])
17441         {
17442                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
17443         }
17444
17445         return TRUE;
17446 }
17447
17448 int
17449 _mmplayer_set_pcm_spec(MMHandleType hplayer, int samplerate, int channel)
17450 {
17451         mm_player_t* player = (mm_player_t*) hplayer;
17452
17453         MMPLAYER_FENTER();
17454
17455         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17456
17457         player->pcm_samplerate = samplerate;
17458         player->pcm_channel = channel;
17459
17460         MMPLAYER_FLEAVE();
17461         return MM_ERROR_NONE;
17462 }
17463