tizen 2.3.1 release
[framework/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/interfaces/xoverlay.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <sys/time.h>
35 #include <stdlib.h>
36 #include <utilX.h>
37
38 #include <mm_error.h>
39 #include <mm_attrs.h>
40 #include <mm_attrs_private.h>
41 #include <mm_debug.h>
42
43 #include "mm_player_priv.h"
44 #include "mm_player_ini.h"
45 #include "mm_player_attrs.h"
46 #include "mm_player_capture.h"
47 #include "mm_player_utils.h"
48 #include <sched.h>
49
50 #include <mm_sound.h>
51
52 #define MM_SMOOTH_STREAMING
53
54 /*===========================================================================================
55 |                                                                                                                                                                                       |
56 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
57 |                                                                                                                                                                                       |
58 ========================================================================================== */
59
60 /*---------------------------------------------------------------------------
61 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
62 ---------------------------------------------------------------------------*/
63
64 /*---------------------------------------------------------------------------
65 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
66 ---------------------------------------------------------------------------*/
67
68 /*---------------------------------------------------------------------------
69 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
70 ---------------------------------------------------------------------------*/
71
72 /*---------------------------------------------------------------------------
73 |    LOCAL #defines:                                                                                                            |
74 ---------------------------------------------------------------------------*/
75 #define TRICK_PLAY_MUTE_THRESHOLD_MAX   2.0
76 #define TRICK_PLAY_MUTE_THRESHOLD_MIN   0.0
77
78 #define MM_VOLUME_FACTOR_DEFAULT                1.0
79 #define MM_VOLUME_FACTOR_MIN                    0
80 #define MM_VOLUME_FACTOR_MAX                    1.0
81
82 #define MM_PLAYER_FADEOUT_TIME_DEFAULT  700000 // 700 msec
83
84 #define MM_PLAYER_MPEG_VNAME                            "mpegversion"
85 #define MM_PLAYER_DIVX_VNAME                            "divxversion"
86 #define MM_PLAYER_WMV_VNAME                             "wmvversion"
87 #define MM_PLAYER_WMA_VNAME                             "wmaversion"
88
89 #define DEFAULT_PLAYBACK_RATE                   1.0
90 #define PLAYBACK_RATE_EX_AUDIO_MIN              0.5
91 #define PLAYBACK_RATE_EX_AUDIO_MAX              2.0
92 #define PLAYBACK_RATE_EX_VIDEO_MIN              0.5
93 #define PLAYBACK_RATE_EX_VIDEO_MAX              1.5
94
95 #define GST_QUEUE_DEFAULT_TIME                  4
96 #define GST_QUEUE_HLS_TIME                              8
97
98 #define DEFAULT_AUDIO_CH                                0
99
100 /* video capture callback*/
101 gulong ahs_appsrc_cb_probe_id = 0;
102
103 #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) )
104
105 #define LAZY_PAUSE_TIMEOUT_MSEC 700
106 #define MM_PLAYER_NAME  "mmplayer"
107
108 //#define ENABLE_DRMSRC
109
110 /*---------------------------------------------------------------------------
111 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
112 ---------------------------------------------------------------------------*/
113
114 /*---------------------------------------------------------------------------
115 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
116 ---------------------------------------------------------------------------*/
117
118 /*---------------------------------------------------------------------------
119 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
120 ---------------------------------------------------------------------------*/
121
122 /*---------------------------------------------------------------------------
123 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
124 ---------------------------------------------------------------------------*/
125
126 /*---------------------------------------------------------------------------
127 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
128 ---------------------------------------------------------------------------*/
129 static int              __mmplayer_set_state(mm_player_t* player, int state);
130 static int              __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
131 static int              __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
132 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player);
133 static int              __mmplayer_gst_create_subtitle_src(mm_player_t* player);
134 static int              __mmplayer_gst_create_pipeline(mm_player_t* player);
135 static int              __mmplayer_gst_destroy_pipeline(mm_player_t* player);
136 static int              __mmplayer_gst_element_link_bucket(GList* element_bucket);
137
138 static gboolean __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data);
139 static void     __mmplayer_gst_selector_blocked(GstPad* pad, gboolean blocked, gpointer data);
140 static void             __mmplayer_gst_decode_pad_added(GstElement* elem, GstPad* pad, gpointer data);
141 static void     __mmplayer_gst_decode_no_more_pads(GstElement* elem, gpointer data);
142 static void     __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gpointer data);
143 static void             __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad, GstCaps *caps, gpointer data);
144 static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
145 static gint __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad, GstCaps * caps, GstElementFactory* factory, gpointer data);
146 //static GValueArray* __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
147 static GValueArray* __mmplayer_gst_decode_autoplug_sort(GstElement *bin,  GstPad* pad, GstCaps * caps, GValueArray *factories, gpointer data);
148 static void __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad, gpointer data);
149 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
150 static void     __mmplayer_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
151 static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
152 static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
153
154 static void     __mmplayer_typefind_have_type(  GstElement *tf, guint probability, GstCaps *caps, gpointer data);
155 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
156 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
157 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
158 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
159 static gboolean __mmplayer_is_omx_decoder_type(mm_player_t* player); // mp3
160 static void     __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
161 //static void   __mmplayer_check_video_zero_cpoy(mm_player_t* player, GstElementFactory* factory);
162
163 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
164 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
165 static void     __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
166
167 static void             __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data);
168 static void    __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
169 static void             __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
170 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player );
171 static gboolean __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
172
173
174 static void     __mmplayer_init_factories(mm_player_t* player);
175 static void     __mmplayer_release_factories(mm_player_t* player);
176 static void             __mmplayer_release_misc(mm_player_t* player);
177 static void             __mmplayer_release_misc_post(mm_player_t* player);
178 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
179
180 static int              __mmplayer_gst_set_state (mm_player_t* player, GstElement * pipeline,  GstState state, gboolean async, gint timeout );
181 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
182 static gboolean      __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
183
184 int             __mmplayer_switch_audio_sink (mm_player_t* player);
185 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
186 static int              __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
187 static gboolean __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data);
188 static gboolean __mmplayer_video_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data);
189 static gboolean __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstBuffer *buffer, gpointer u_data);
190 static int __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index);
191
192 static gboolean __mmplayer_dump_pipeline_state( mm_player_t* player );
193 static gboolean __mmplayer_check_subtitle( mm_player_t* player );
194 static gboolean __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error );
195 static gboolean __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message );
196 static void             __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms );
197 static void     __mmplayer_cancel_eos_timer( mm_player_t* player );
198 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
199 static gboolean __mmplayer_link_decoder( mm_player_t* player,GstPad *srcpad);
200 static gboolean __mmplayer_link_sink( mm_player_t* player,GstPad *srcpad);
201 static int      __mmplayer_handle_missed_plugin(mm_player_t* player);
202 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
203 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
204 static void     __mmplayer_add_sink( mm_player_t* player, GstElement* sink);
205 static void     __mmplayer_del_sink( mm_player_t* player, GstElement* sink);
206 static void     __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
207 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force);
208 static gpointer __mmplayer_next_play_thread(gpointer data);
209 static gpointer __mmplayer_repeat_thread(gpointer data);
210 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
211
212
213 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
214 static gboolean __mmplayer_dump_buffer_probe_cb(GstPad *pad, GstBuffer *buffer, gpointer u_data);
215 static void __mmplayer_release_dump_list (GList *dump_list);
216
217 static int              __gst_realize(mm_player_t* player);
218 static int              __gst_unrealize(mm_player_t* player);
219 static int              __gst_start(mm_player_t* player);
220 static int              __gst_stop(mm_player_t* player);
221 static int              __gst_pause(mm_player_t* player, gboolean async);
222 static int              __gst_resume(mm_player_t* player, gboolean async);
223 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
224                                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
225                                         gint64 cur, GstSeekType stop_type, gint64 stop );
226 static int __gst_pending_seek ( mm_player_t* player );
227
228 static int              __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called);
229 static int              __gst_get_position(mm_player_t* player, int format, unsigned long *position);
230 static int              __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
231 static int              __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
232 static int              __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
233
234 static gint     __gst_handle_core_error( mm_player_t* player, int code );
235 static gint     __gst_handle_library_error( mm_player_t* player, int code );
236 static gint     __gst_handle_resource_error( mm_player_t* player, int code );
237 static gint     __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message );
238 static gint             __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error);
239 static gboolean __gst_send_event_to_sink( mm_player_t* player, GstEvent* event );
240
241 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
242 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
243
244 /*fadeout */
245 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
246 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
247
248 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
249 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
250
251 /* util */
252 const gchar * __get_state_name ( int state );
253 static gboolean __is_streaming( mm_player_t* player );
254 static gboolean __is_rtsp_streaming( mm_player_t* player );
255 static gboolean __is_wfd_streaming( mm_player_t* player );
256 static gboolean __is_live_streaming ( mm_player_t* player );
257 static gboolean __is_http_streaming( mm_player_t* player );
258 static gboolean __is_http_live_streaming( mm_player_t* player );
259 static gboolean __is_dash_streaming( mm_player_t* player );
260 static gboolean __is_smooth_streaming( mm_player_t* player );
261 static gboolean __is_http_progressive_down(mm_player_t* player);
262 static gboolean __has_suffix(mm_player_t * player, const gchar * suffix);
263
264 static GstBusSyncReply __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data);
265
266 static int  __mmplayer_realize_streaming_ext(mm_player_t* player);
267 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
268 static int __mmplayer_start_streaming_ext(mm_player_t *player);
269 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
270 static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
271 static void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id);
272
273 static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
274 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
275 static void __mmplayer_check_pipeline(mm_player_t* player);
276 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
277 static void __mmplayer_deactivate_old_path(mm_player_t *player);
278 static int __mmplayer_ignore_current_external_display_mode(mm_player_t* player);
279 #if 0 // We'll need this in future.
280 static int __mmplayer_gst_switching_element(mm_player_t *player, GstElement *search_from, const gchar *removal_name, const gchar *new_element_name);
281 #endif
282
283 static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg);
284 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
285 static gboolean __mmplayer_can_do_interrupt(mm_player_t *player);
286
287 /* device change post proc */
288 void __mmplayer_device_change_post_process(gpointer user);
289 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score);
290 void __mmplayer_inc_cb_score(mm_player_t* player);
291 void __mmplayer_post_proc_reset(mm_player_t* player);
292 void __mmplayer_device_change_trigger_post_process(mm_player_t* player);
293 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
294
295
296 /*===========================================================================================
297 |                                                                                                                                                                                       |
298 |  FUNCTION DEFINITIONS                                                                                                                                         |
299 |                                                                                                                                                                                       |
300 ========================================================================================== */
301
302 /* implementing player FSM */
303 /* FIXIT : We need to handle state transition also at here since start api is no more sync */
304 static int
305 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
306 {
307         MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
308         MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
309 //      MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
310 //      MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
311
312         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
313
314         //debug_log("incomming command : %d \n", command );
315
316         current_state = MMPLAYER_CURRENT_STATE(player);
317         pending_state = MMPLAYER_PENDING_STATE(player);
318 //      target_state = MMPLAYER_TARGET_STATE(player);
319 //      prev_state = MMPLAYER_PREV_STATE(player);
320
321         MMPLAYER_PRINT_STATE(player);
322
323         switch( command )
324         {
325                 case MMPLAYER_COMMAND_CREATE:
326                 {
327                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
328
329                         if ( current_state == MM_PLAYER_STATE_NULL ||
330                                 current_state == MM_PLAYER_STATE_READY ||
331                                 current_state == MM_PLAYER_STATE_PAUSED ||
332                                 current_state == MM_PLAYER_STATE_PLAYING )
333                                 goto NO_OP;
334                 }
335                 break;
336
337                 case MMPLAYER_COMMAND_DESTROY:
338                 {
339                         /* destroy can called anytime */
340
341                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
342                 }
343                 break;
344
345                 case MMPLAYER_COMMAND_REALIZE:
346                 {
347                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
348
349                         if ( pending_state != MM_PLAYER_STATE_NONE )
350                         {
351                                 goto INVALID_STATE;
352                         }
353                         else
354                         {
355                                 /* need ready state to realize */
356                                 if ( current_state == MM_PLAYER_STATE_READY )
357                                         goto NO_OP;
358
359                                 if ( current_state != MM_PLAYER_STATE_NULL )
360                                         goto INVALID_STATE;
361                         }
362                 }
363                 break;
364
365                 case MMPLAYER_COMMAND_UNREALIZE:
366                 {
367                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
368
369                         if ( current_state == MM_PLAYER_STATE_NULL )
370                                 goto NO_OP;
371                 }
372                 break;
373
374                 case MMPLAYER_COMMAND_START:
375                 {
376                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
377
378                         if ( pending_state == MM_PLAYER_STATE_NONE )
379                         {
380                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
381                                         goto NO_OP;
382                                 else if ( current_state  != MM_PLAYER_STATE_READY &&
383                                         current_state != MM_PLAYER_STATE_PAUSED )
384                                         goto INVALID_STATE;
385                         }
386                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
387                         {
388                                 goto ALREADY_GOING;
389                         }
390                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
391                         {
392                                 debug_log("player is going to paused state, just change the pending state as playing");
393                         }
394                         else
395                         {
396                                 goto INVALID_STATE;
397                         }
398                 }
399                 break;
400
401                 case MMPLAYER_COMMAND_STOP:
402                 {
403                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
404
405                         if ( current_state == MM_PLAYER_STATE_READY )
406                                 goto NO_OP;
407
408                         /* need playing/paused state to stop */
409                         if ( current_state != MM_PLAYER_STATE_PLAYING &&
410                                  current_state != MM_PLAYER_STATE_PAUSED )
411                                 goto INVALID_STATE;
412                 }
413                 break;
414
415                 case MMPLAYER_COMMAND_PAUSE:
416                 {
417                         if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
418                                 goto NO_OP;
419
420                         if (player->doing_seek)
421                                 goto NOT_COMPLETED_SEEK;
422
423                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
424
425                         if ( pending_state == MM_PLAYER_STATE_NONE )
426                         {
427                                 if ( current_state == MM_PLAYER_STATE_PAUSED )
428                                         goto NO_OP;
429                                 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
430                                         goto INVALID_STATE;
431                         }
432                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
433                         {
434                                 goto ALREADY_GOING;
435                         }
436                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
437                         {
438                                 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
439                                         debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
440                                 } else {
441                                         goto INVALID_STATE;
442                                 }
443                         }
444                 }
445                 break;
446
447                 case MMPLAYER_COMMAND_RESUME:
448                 {
449
450                         if (player->doing_seek)
451                                 goto NOT_COMPLETED_SEEK;
452
453                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
454
455                         if ( pending_state == MM_PLAYER_STATE_NONE )
456                         {
457                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
458                                         goto NO_OP;
459                                 else if (  current_state != MM_PLAYER_STATE_PAUSED )
460                                         goto INVALID_STATE;
461                         }
462                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
463                         {
464                                 goto ALREADY_GOING;
465                         }
466                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
467                         {
468                                 debug_log("player is going to paused state, just change the pending state as playing");
469                         }
470                         else
471                         {
472                                 goto INVALID_STATE;
473                         }
474                 }
475                 break;
476
477                 default:
478                 break;
479         }
480         player->cmd = command;
481
482         return MM_ERROR_NONE;
483
484 INVALID_STATE:
485         debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
486                 MMPLAYER_STATE_GET_NAME(current_state), command);
487         return MM_ERROR_PLAYER_INVALID_STATE;
488
489 NOT_COMPLETED_SEEK:
490         debug_warning("not completed seek");
491         return MM_ERROR_PLAYER_DOING_SEEK;
492
493 NO_OP:
494         debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
495         return MM_ERROR_PLAYER_NO_OP;
496
497 ALREADY_GOING:
498         debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
499         return MM_ERROR_PLAYER_NO_OP;
500 }
501
502 int
503 __mmplayer_gst_set_state (mm_player_t* player, GstElement * element,  GstState state, gboolean async, gint timeout) // @
504 {
505         GstState element_state = GST_STATE_VOID_PENDING;
506         GstState element_pending_state = GST_STATE_VOID_PENDING;
507         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
508
509         MMPLAYER_FENTER();
510
511         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
512         return_val_if_fail ( element, MM_ERROR_INVALID_ARGUMENT );
513
514         debug_log("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
515
516         /* set state */
517         ret = gst_element_set_state(element, state);
518
519         if ( ret == GST_STATE_CHANGE_FAILURE )
520         {
521                 debug_error("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
522
523                 /* dump state of all element */
524                 __mmplayer_dump_pipeline_state( player );
525
526                 return MM_ERROR_PLAYER_INTERNAL;
527         }
528
529         /* return here so state transition to be done in async mode */
530         if ( async )
531         {
532                 debug_log("async state transition. not waiting for state complete.\n");
533                 return MM_ERROR_NONE;
534         }
535
536         /* wait for state transition */
537         ret = gst_element_get_state( element, &element_state, &element_pending_state, timeout * GST_SECOND );
538
539         if ( ret == GST_STATE_CHANGE_FAILURE || ( state != element_state ) )
540         {
541                 debug_error("failed to change [%s] element state to [%s] within %d sec\n",
542                         GST_ELEMENT_NAME(element),
543                         gst_element_state_get_name(state), timeout );
544
545                 debug_error(" [%s] state : %s   pending : %s \n",
546                         GST_ELEMENT_NAME(element),
547                         gst_element_state_get_name(element_state),
548                         gst_element_state_get_name(element_pending_state) );
549
550                 /* dump state of all element */
551                 __mmplayer_dump_pipeline_state( player );
552
553                 return MM_ERROR_PLAYER_INTERNAL;
554         }
555
556         debug_log("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
557
558         MMPLAYER_FLEAVE();
559
560         return MM_ERROR_NONE;
561 }
562
563 static void
564 __mmplayer_videostream_cb(GstElement *element, void *data,
565 int width, int height, gpointer user_data) // @
566 {
567         mm_player_t* player = (mm_player_t*)user_data;
568
569         return_if_fail ( player );
570
571         MMPLAYER_FENTER();
572
573         if (player->is_drm_file)
574         {
575                 MMMessageParamType msg_param = { 0, };
576                 debug_warning("not supported in drm file");
577                 msg_param.code = MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
578                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
579         }
580         else if ( !player->set_mode.media_packet_video_stream && player->video_stream_cb)
581         {
582                 MMPlayerVideoStreamDataType stream;
583
584                 /* clear stream data structure */
585                 memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
586
587                 stream.data = data;
588                 stream.length_total = width * height * 4; // for rgb 32bit
589                 stream.height = height;
590                 stream.width = width;
591                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
592         }
593
594         MMPLAYER_FLEAVE();
595 }
596
597 static void
598 __mmplayer_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer data)
599 {
600         mm_player_t* player = (mm_player_t*)data;
601
602         return_if_fail ( player );
603
604         MMPLAYER_FENTER();
605
606         if (player->video_frame_render_error_cb )
607         {
608                 if (player->attrs)
609                 {
610                         int surface_type = 0;
611                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
612                         switch (surface_type)
613                         {
614                         case MM_DISPLAY_SURFACE_X_EXT:
615                                 player->video_frame_render_error_cb((unsigned int*)error_id, player->video_frame_render_error_cb_user_param);
616                                 debug_log("display surface type(X_EXT) : render error callback(%p) is finished", player->video_frame_render_error_cb);
617                                 break;
618                         default:
619                                 debug_error("video_frame_render_error_cb was set, but this surface type(%d) is not supported", surface_type);
620                                 break;
621                         }
622                 }
623                 else
624                 {
625                         debug_error("could not get surface type");
626                 }
627         }
628         else
629         {
630                 debug_warning("video_frame_render_error_cb was not set");
631         }
632
633         MMPLAYER_FLEAVE();
634 }
635
636 void
637 __mmplayer_device_change_post_process(gpointer user)
638 {
639         mm_player_t* player = (mm_player_t*)user;
640         unsigned long position = 0;
641         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
642         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
643
644         MMPLAYER_FENTER();
645
646         if (! player ||
647                 ! player->pipeline ||
648                 ! player->pipeline->mainbin ||
649                 ! player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
650         {
651                 goto EXIT;
652         }
653
654         current_state = MMPLAYER_CURRENT_STATE(player);
655         pending_state = MMPLAYER_PENDING_STATE(player);
656
657         if (player->post_proc.need_pause_and_resume)
658         {
659                 debug_log("pausing");
660                 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
661                         ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
662                         gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED);
663         }
664
665         /* seek should be done within pause and resume */
666         if (player->post_proc.need_seek)
667         {
668                 debug_log("seeking");
669                 __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position);
670                 debug_log(">> seek to current position = %ld ms", position);
671                 __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE);
672         }
673
674         if (player->post_proc.need_pause_and_resume)
675         {
676                 debug_log("resuming");
677                 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
678                         ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
679                         gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING);
680         }
681
682         /* async */
683         if (player->post_proc.need_async)
684         {
685                 debug_log("setting async");
686                 debug_log(">> player->display_stat = %d", player->display_stat);
687
688                 if ((player->display_stat == MMPLAYER_DISPLAY_STATUS_HDMI_ACTIVE) ||
689                         (player->display_stat == MMPLAYER_DISPLAY_STATUS_UNKNOWN_ACTIVE))
690                 {
691                         g_object_set(G_OBJECT(player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "async", TRUE, NULL);
692                 }
693                 /* TODO : need some comment here */
694                 else if (player->display_stat == MMPLAYER_DISPLAY_STATUS_NULL)
695                 {
696                         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
697                 }
698         }
699
700 EXIT:
701         /* reset all */
702         __mmplayer_post_proc_reset(player);
703         return;
704 }
705
706 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score)
707 {
708         return_if_fail(player);
709         player->post_proc.required_cb_score = score;
710         debug_log("set required score to : %d", score);
711 }
712
713 void __mmplayer_inc_cb_score(mm_player_t* player)
714 {
715         return_if_fail(player);
716         player->post_proc.cb_score++;
717         debug_log("post proc cb score increased to %d", player->post_proc.cb_score);
718 }
719
720 void __mmplayer_post_proc_reset(mm_player_t* player)
721 {
722         return_if_fail(player);
723
724         /* check if already triggered */
725         if (player->post_proc.id)
726         {
727                 /* TODO : need to consider multiple main context. !!!! */
728                 if (FALSE == g_source_remove(player->post_proc.id) )
729                 {
730                         debug_error("failed to remove exist post_proc item");
731                 }
732                 player->post_proc.id = 0;
733         }
734
735         memset(&player->post_proc, 0, sizeof(mm_player_post_proc_t));
736
737         /* set default required cb score 1 as only audio device has changed in this case.
738            if display status is changed with audio device, required cb score is set 2 in display status callback.
739            this logic bases on the assumption which audio device callback is called after calling display status callback. */
740         player->post_proc.required_cb_score = 1;
741 }
742
743 void
744 __mmplayer_device_change_trigger_post_process(mm_player_t* player)
745 {
746         return_if_fail(player);
747
748         /* check score */
749         if ( player->post_proc.cb_score < player->post_proc.required_cb_score )
750         {
751                 /* wait for next turn */
752                 debug_log("wait for next turn. required cb score : %d   current score : %d\n",
753                         player->post_proc.required_cb_score, player->post_proc.cb_score);
754                 return;
755         }
756
757         /* check if already triggered */
758         if (player->post_proc.id)
759         {
760                 /* TODO : need to consider multiple main context. !!!! */
761                 if (FALSE == g_source_remove(player->post_proc.id) )
762                 {
763                         debug_error("failed to remove exist post_proc item");
764                 }
765                 player->post_proc.id = 0;
766         }
767
768         player->post_proc.id = g_idle_add((GSourceFunc)__mmplayer_device_change_post_process, (gpointer)player);
769 }
770
771 /* NOTE : Sound module has different latency according to output device So,
772  * synchronization problem can be happened whenever device is changed.
773  * To avoid this issue, we do reset avsystem or seek as workaroud.
774  */
775 static void
776 __mmplayer_sound_device_info_changed_cb_func (MMSoundDevice_t device_h, int changed_info_type, void *user_data)
777 {
778     int ret;
779     mm_sound_device_type_e device_type;
780         mm_player_t* player = (mm_player_t*) user_data;
781
782         return_if_fail( player );
783
784         debug_warning("device_info_changed_cb is called, device_h[0x%x], changed_info_type[%d]\n", device_h, changed_info_type);
785
786         __mmplayer_inc_cb_score(player);
787
788         /* get device type with device_h*/
789         ret = mm_sound_get_device_type(device_h, &device_type);
790         if (ret) {
791                 debug_error("failed to mm_sound_get_device_type()\n");
792         }
793
794         /* do pause and resume only if video is playing  */
795         if ( player->videodec_linked && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING )
796         {
797                 switch (device_type)
798                 {
799                         case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
800                         case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
801                         case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
802                         case MM_SOUND_DEVICE_TYPE_HDMI:
803                         case MM_SOUND_DEVICE_TYPE_MIRRORING:
804                         {
805                                 player->post_proc.need_pause_and_resume = TRUE;
806                         }
807                         break;
808
809                         default:
810                                 debug_log("do nothing");
811                 }
812         }
813         debug_warning("dispatched");
814
815         __mmplayer_device_change_trigger_post_process(player);
816 }
817
818 static void
819 __mmplayer_display_status_cb(GstElement *element, MMPlayerDisplayStatus stat, gpointer data)
820 {
821         mm_player_t* player = (mm_player_t*)data;
822         return_if_fail ( player );
823         MMPLAYER_FENTER();
824
825         guint required_cb_score = 2;
826
827         __mmplayer_inc_cb_score(player);
828         __mmplayer_set_required_cb_score(player, required_cb_score);
829
830         if ((player->pipeline->textbin == NULL) ||
831                 (player->pipeline->textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst == NULL) ||
832                 (player->pipeline->textbin[MMPLAYER_T_TEXT_IDENTITY].gst == NULL) ||
833                 (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst == NULL))
834         {
835                 debug_warning("text bin is not ready yet");
836                 goto EXIT;
837         }
838
839         if (player->is_subtitle_force_drop == TRUE)
840         {
841                 debug_warning("subtitle is dropping");
842                 player->display_stat = stat;
843                 goto EXIT;
844         }
845
846         if (stat != util_get_is_connected_external_display())
847         {
848                 debug_warning("stat is wrong!! (%d from xvimagesink)", stat);
849                 goto EXIT;
850         }
851
852         if ((stat == MMPLAYER_DISPLAY_STATUS_HDMI_ACTIVE) || (stat == MMPLAYER_DISPLAY_STATUS_UNKNOWN_ACTIVE))
853         {
854                 MMMessageParamType msg = {0, };
855                 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst), "drop-probability", (gfloat)1.0, NULL);
856                 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_TEXT_IDENTITY].gst), "drop-probability", (gfloat)0.0, NULL);
857                 debug_log("external display is ACTIVE");
858
859                 msg.data = NULL;
860                 msg.subtitle.duration = 0;
861
862                 MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
863         }
864         else if (stat == MMPLAYER_DISPLAY_STATUS_NULL)
865         {
866                 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst), "drop-probability", (gfloat)0.0, NULL);
867                 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_TEXT_IDENTITY].gst), "drop-probability", (gfloat)1.0, NULL); //If it is not ACTIVE...
868                 debug_log("external display is NULL");
869         }
870
871         if (player->display_stat != stat)
872         {
873                 player->display_stat = stat;
874
875                 g_object_set(G_OBJECT(player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "async", FALSE, NULL);
876                 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst), "async", FALSE, NULL);
877
878                 /* setup post processing */
879                 player->post_proc.need_async = TRUE;
880                 player->post_proc.need_seek = TRUE;
881                 player->post_proc.need_pause_and_resume = TRUE;
882         }
883
884         MMPLAYER_FLEAVE();
885
886 EXIT:
887         __mmplayer_device_change_trigger_post_process(player);
888         return;
889 }
890
891 static void
892 __mmplayer_external_resolution_cb(GstElement *element, int width, int height, gpointer data)
893 {
894         mm_player_t* player = (mm_player_t*)data;
895         return_if_fail ( player );
896         MMPLAYER_FENTER();
897
898         if ((player->pipeline->textbin == NULL) ||
899                 (player->pipeline->textbin[MMPLAYER_T_RENDER].gst == NULL) ||
900                 (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst == NULL))
901         {
902                 debug_warning("text bin is not ready yet");
903                 return;
904         }
905
906         if((width==0 || height==0) && util_get_is_connected_external_display()!=MMPLAYER_DISPLAY_STATUS_NULL)
907         {
908                 debug_warning("stat is wrong!! skip setting external resolution to 0");
909                 return;
910         }
911         debug_log("set external width and height : %d * %d", width, height);
912         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_RENDER].gst), "external-width", width, NULL);
913         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_RENDER].gst), "external-height", height, NULL);
914
915         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "external-width", width, NULL);
916         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "external-height", height, NULL);
917
918         MMPLAYER_FLEAVE();
919 }
920
921 static void
922 __mmplayer_hided_window_cb(GstElement *element, gboolean is_hided , gpointer data)
923 {
924         mm_player_t* player = (mm_player_t*)data;
925         return_if_fail ( player );
926         MMPLAYER_FENTER();
927
928         if ((player->pipeline->textbin == NULL) ||
929                 (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst == NULL))
930         {
931                 debug_warning("text_xvimagesink is not ready yet");
932                 return;
933         }
934         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "hided-window", is_hided, NULL);
935         debug_log("update window-hide status : %d", is_hided);
936
937         MMPLAYER_FLEAVE();
938 }
939
940 static void
941 __mmplayer_quick_panel_on_cb(GstElement *element, gboolean quick_panel_on , gpointer data)
942 {
943         mm_player_t* player = (mm_player_t*)data;
944         return_if_fail ( player );
945         MMPLAYER_FENTER();
946
947         if ((player->pipeline->textbin == NULL) ||
948                 (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst == NULL))
949         {
950                 debug_warning("text_xvimagesink is not ready yet");
951                 return;
952         }
953         g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "quick-panel-on", quick_panel_on, NULL);
954         debug_log("update quick panel status : %d", quick_panel_on);
955
956         MMPLAYER_FLEAVE();
957 }
958
959 static void
960 __mmplayer_multiwindow_active_cb(GstElement *element, gboolean multiwindow_active , gpointer data)
961 {
962         mm_player_t* player = (mm_player_t*)data;
963         return_if_fail ( player );
964
965         if ((player->pipeline->textbin == NULL) ||
966                 (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst == NULL))
967         {
968                 return;
969         }
970         if (player->last_multiwin_status != multiwindow_active)
971         {
972                 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "multiwindow-active", multiwindow_active, NULL);
973                 player->last_multiwin_status = multiwindow_active;
974                 debug_log("update multiwindow-active status : %d", multiwindow_active);
975         }
976 }
977
978
979 /* This function should be called after the pipeline goes PAUSED or higher
980 state. */
981 gboolean
982 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
983 {
984         static gboolean has_duration = FALSE;
985         static gboolean has_video_attrs = FALSE;
986         static gboolean has_audio_attrs = FALSE;
987         static gboolean has_bitrate = FALSE;
988         gboolean missing_only = FALSE;
989         gboolean all = FALSE;
990
991         GstFormat fmt  = GST_FORMAT_TIME;
992         gint64 dur_nsec = 0;
993         GstStructure* p = NULL;
994         MMHandleType attrs = 0;
995         gchar *path = NULL;
996         gint stream_service_type = STREAMING_SERVICE_NONE;
997         struct stat sb;
998
999         MMPLAYER_FENTER();
1000
1001         return_val_if_fail ( player, FALSE );
1002
1003         /* check player state here */
1004         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
1005                 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING )
1006         {
1007                 /* give warning now only */
1008                 debug_warning("be careful. content attributes may not available in this state ");
1009         }
1010
1011         /* get content attribute first */
1012         attrs = MMPLAYER_GET_ATTRS(player);
1013         if ( !attrs )
1014         {
1015                 debug_error("cannot get content attribute");
1016                 return FALSE;
1017         }
1018
1019         /* get update flag */
1020
1021         if ( flag & ATTR_MISSING_ONLY )
1022         {
1023                 missing_only = TRUE;
1024                 debug_log("updating missed attr only");
1025         }
1026
1027         if ( flag & ATTR_ALL )
1028         {
1029                 all = TRUE;
1030                 has_duration = FALSE;
1031                 has_video_attrs = FALSE;
1032                 has_audio_attrs = FALSE;
1033                 has_bitrate = FALSE;
1034
1035                 debug_log("updating all attrs");
1036         }
1037
1038         if ( missing_only && all )
1039         {
1040                 debug_warning("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
1041                 missing_only = FALSE;
1042         }
1043
1044         if (  (flag & ATTR_DURATION) || (!has_duration && missing_only) || all )
1045         {
1046                 debug_log("try to update duration");
1047                 has_duration = FALSE;
1048
1049                 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec ))
1050                 {
1051                         player->duration = dur_nsec;
1052                         debug_warning("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
1053                 }
1054
1055                 /* try to get streaming service type */
1056                 stream_service_type = __mmplayer_get_stream_service_type( player );
1057                 mm_attrs_set_int_by_name ( attrs, "streaming_type", stream_service_type );
1058
1059                 /* check duration is OK */
1060                 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
1061                 {
1062                         /* FIXIT : find another way to get duration here. */
1063                         debug_error("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
1064                 }
1065                 else
1066                 {
1067                         /*update duration */
1068                         mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
1069                         has_duration = TRUE;
1070                 }
1071         }
1072
1073         if (  (flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all )
1074         {
1075                 /* update audio params
1076                 NOTE : We need original audio params and it can be only obtained from src pad of audio
1077                 decoder. Below code only valid when we are not using 'resampler' just before
1078                 'audioconverter'. */
1079
1080                 debug_log("try to update audio attrs");
1081                 has_audio_attrs = FALSE;
1082
1083                 if ( player->pipeline->audiobin &&
1084                          player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
1085                 {
1086                         GstCaps *caps_a = NULL;
1087                         GstPad* pad = NULL;
1088                         gint samplerate = 0, channels = 0;
1089
1090                         pad = gst_element_get_static_pad(
1091                                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
1092
1093                         if ( pad )
1094                         {
1095                                 caps_a = gst_pad_get_negotiated_caps( pad );
1096
1097                                 if ( caps_a )
1098                                 {
1099                                         p = gst_caps_get_structure (caps_a, 0);
1100
1101                                         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
1102
1103                                         gst_structure_get_int (p, "rate", &samplerate);
1104                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
1105
1106                                         gst_structure_get_int (p, "channels", &channels);
1107                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
1108
1109                                         secure_debug_log("samplerate : %d       channels : %d", samplerate, channels);
1110
1111                                         gst_caps_unref( caps_a );
1112                                         caps_a = NULL;
1113
1114                                         has_audio_attrs = TRUE;
1115                                 }
1116                                 else
1117                                 {
1118                                         debug_warning("not ready to get audio caps");
1119                                 }
1120
1121                                 gst_object_unref( pad );
1122                         }
1123                         else
1124                         {
1125                                 debug_warning("failed to get pad from audiosink");
1126                         }
1127                 }
1128         }
1129
1130         if ( (flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all )
1131         {
1132                 debug_log("try to update video attrs");
1133                 has_video_attrs = FALSE;
1134
1135                 if ( player->pipeline->videobin &&
1136                          player->pipeline->videobin[MMPLAYER_V_SINK].gst )
1137                 {
1138                         GstCaps *caps_v = NULL;
1139                         GstPad* pad = NULL;
1140                         gint tmpNu, tmpDe;
1141                         gint width, height;
1142
1143                         pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
1144                         if ( pad )
1145                         {
1146                                 caps_v = gst_pad_get_negotiated_caps( pad );
1147                                 if (caps_v)
1148                                 {
1149                                         p = gst_caps_get_structure (caps_v, 0);
1150                                         gst_structure_get_int (p, "width", &width);
1151                                         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
1152
1153                                         gst_structure_get_int (p, "height", &height);
1154                                         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
1155
1156                                         gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
1157
1158                                         secure_debug_log("width : %d     height : %d", width, height );
1159
1160                                         gst_caps_unref( caps_v );
1161                                         caps_v = NULL;
1162
1163                                         if (tmpDe > 0)
1164                                         {
1165                                                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
1166                                                 secure_debug_log("fps : %d", tmpNu / tmpDe);
1167                                         }
1168
1169                                         has_video_attrs = TRUE;
1170                                 }
1171                                 else
1172                                 {
1173                                         debug_log("no negitiated caps from videosink");
1174                                 }
1175                                 gst_object_unref( pad );
1176                                 pad = NULL;
1177                         }
1178                         else
1179                         {
1180                                 debug_log("no videosink sink pad");
1181                         }
1182                 }
1183         }
1184
1185
1186         if ( (flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all )
1187         {
1188                 has_bitrate = FALSE;
1189
1190                 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
1191                 if (player->duration)
1192                 {
1193                         guint64 data_size = 0;
1194
1195                         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1196                         {
1197                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1198
1199                                 if (stat(path, &sb) == 0)
1200                                 {
1201                                         data_size = (guint64)sb.st_size;
1202                                 }
1203                         }
1204                         else if (MMPLAYER_IS_HTTP_STREAMING(player))
1205                         {
1206                                 data_size = player->http_content_size;
1207                         }
1208                         debug_log("try to update bitrate : data_size = %lld", data_size);
1209
1210                         if (data_size)
1211                         {
1212                                 guint64 bitrate = 0;
1213                                 guint64 msec_dur = 0;
1214
1215                                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
1216                                 bitrate = data_size * 8 * 1000 / msec_dur;
1217                                 secure_debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
1218                                 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
1219
1220                                 has_bitrate = TRUE;
1221                         }
1222
1223                         if (MMPLAYER_IS_RTSP_STREAMING(player))
1224                         {
1225                                 if(player->total_bitrate)
1226                                 {
1227                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
1228                                         has_bitrate = TRUE;
1229                                 }
1230                         }
1231                 }
1232         }
1233
1234         /* validate all */
1235         if (  mmf_attrs_commit ( attrs ) )
1236         {
1237                 debug_error("failed to update attributes\n");
1238                 return FALSE;
1239         }
1240
1241         MMPLAYER_FLEAVE();
1242
1243         return TRUE;
1244 }
1245
1246 gint __mmplayer_get_stream_service_type( mm_player_t* player )
1247 {
1248         gint streaming_type = STREAMING_SERVICE_NONE;
1249
1250         MMPLAYER_FENTER();
1251
1252         return_val_if_fail ( player &&
1253                         player->pipeline &&
1254                         player->pipeline->mainbin &&
1255                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
1256                         FALSE );
1257
1258         /* streaming service type if streaming */
1259         if ( ! MMPLAYER_IS_STREAMING(player) )
1260                 return STREAMING_SERVICE_NONE;
1261
1262         if (MMPLAYER_IS_RTSP_STREAMING(player))
1263         {
1264                 /* get property from rtspsrc element */
1265                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst),
1266                         "service_type", &streaming_type, NULL);
1267         }
1268         else if (MMPLAYER_IS_HTTP_STREAMING(player))
1269         {
1270                 streaming_type = (player->duration == 0) ?
1271                         STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
1272         }
1273
1274         switch ( streaming_type )
1275         {
1276                 case STREAMING_SERVICE_LIVE:
1277                         debug_log("it's live streaming");
1278                 break;
1279                 case STREAMING_SERVICE_VOD:
1280                         debug_log("it's vod streaming");
1281                 break;
1282                 case STREAMING_SERVICE_NONE:
1283                         debug_error("should not get here");
1284                 break;
1285                 default:
1286                         debug_error("should not get here");
1287         }
1288
1289         player->streaming_type = streaming_type;
1290         MMPLAYER_FLEAVE();
1291
1292         return streaming_type;
1293 }
1294
1295
1296 /* this function sets the player state and also report
1297  * it to applicaton by calling callback function
1298  */
1299 static int
1300 __mmplayer_set_state(mm_player_t* player, int state) // @
1301 {
1302         MMMessageParamType msg = {0, };
1303         int asm_result = MM_ERROR_NONE;
1304         gboolean post_bos = FALSE;
1305         gboolean interrupted_by_asm = FALSE;
1306         int ret = MM_ERROR_NONE;
1307
1308         return_val_if_fail ( player, FALSE );
1309
1310         if ( MMPLAYER_CURRENT_STATE(player) == state )
1311         {
1312                 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
1313                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1314                 return ret;
1315         }
1316
1317         /* update player states */
1318         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
1319         MMPLAYER_CURRENT_STATE(player) = state;
1320
1321         /* FIXIT : it's better to do like below code
1322         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player) )
1323                         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1324         and add more code to handling PENDING_STATE.
1325         */
1326         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
1327                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1328
1329         /* print state */
1330         MMPLAYER_PRINT_STATE(player);
1331
1332         /* do some FSM stuffs before posting new state to application  */
1333         interrupted_by_asm = player->sm.by_asm_cb;
1334
1335         switch ( MMPLAYER_CURRENT_STATE(player) )
1336         {
1337                 case MM_PLAYER_STATE_NULL:
1338                 case MM_PLAYER_STATE_READY:
1339                 {
1340                         if (player->cmd == MMPLAYER_COMMAND_STOP)
1341                         {
1342                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP, FALSE);
1343                                 if ( asm_result != MM_ERROR_NONE )
1344                                 {
1345                                         debug_error("failed to set asm state to stop\n");
1346                                         return MM_ERROR_POLICY_INTERNAL;
1347                                 }
1348                         }
1349                 }
1350                 break;
1351
1352                 case MM_PLAYER_STATE_PAUSED:
1353                 {
1354                          if ( ! player->sent_bos )
1355                          {
1356                                 int found = 0;
1357                                 #define MMPLAYER_MAX_SOUND_PRIORITY     3
1358
1359                                 /* it's first time to update all content attrs. */
1360                                 _mmplayer_update_content_attrs( player, ATTR_ALL );
1361                                 /* set max sound priority to keep own sound and not to mute other's one */
1362                                 mm_attrs_get_int_by_name(player->attrs, "content_video_found", &found);
1363                                 if (found)
1364                                 {
1365                                         mm_attrs_get_int_by_name(player->attrs, "content_audio_found", &found);
1366                                         if (found)
1367                                         {
1368                                                 debug_log("set max audio priority");
1369                                                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "priority", MMPLAYER_MAX_SOUND_PRIORITY, NULL);
1370                                         }
1371                                 }
1372
1373                          }
1374
1375                         /* add audio callback probe if condition is satisfied */
1376                         if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction )
1377                         {
1378                                 __mmplayer_configure_audio_callback(player);
1379                                 /* FIXIT : handle return value */
1380                         }
1381
1382                         if (!MMPLAYER_IS_STREAMING(player) || (player->streamer && !player->streamer->is_buffering))
1383                         {
1384                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE, FALSE);
1385                                 if ( asm_result )
1386                                 {
1387                                         debug_error("failed to set asm state to PAUSE\n");
1388                                         return MM_ERROR_POLICY_INTERNAL;
1389                                 }
1390                         }
1391                 }
1392                 break;
1393
1394                 case MM_PLAYER_STATE_PLAYING:
1395                 {
1396                         /* try to get content metadata */
1397                         if ( ! player->sent_bos )
1398                         {
1399                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
1400                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
1401                                  * legacy mmfw-player api */
1402                                 _mmplayer_update_content_attrs( player, ATTR_MISSING_ONLY);
1403                         }
1404
1405                         if ( (player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME) )
1406                         {
1407                                 if (!player->sent_bos)
1408                                 {
1409                                         __mmplayer_handle_missed_plugin ( player );
1410                                 }
1411
1412                                 /* update ASM state for video and streaming buffering */
1413                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING, TRUE);
1414                                 if (asm_result != MM_ERROR_NONE)
1415                                 {
1416                                         if (player->pipeline->videobin)
1417                                         {
1418                                                 MMMessageParamType msg = {0, };
1419
1420                                                 debug_error("failed to go ahead because of video conflict\n");
1421
1422                                                 msg.union_type = MM_MSG_UNION_CODE;
1423                                                 msg.code = MM_ERROR_POLICY_INTERRUPTED;
1424                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
1425
1426                                                 _mmplayer_unrealize((MMHandleType)player);
1427                                         }
1428                                         else
1429                                         {
1430                                                 debug_error("failed to play by ASM error : 0x%X\n", asm_result);
1431                                                 _mmplayer_pause((MMHandleType)player);
1432                                                 return asm_result;
1433                                         }
1434
1435                                         return MM_ERROR_POLICY_INTERNAL;
1436                                 }
1437                         }
1438
1439                         if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
1440                         {
1441                                 /* initialize because auto resume is done well. */
1442                                 player->resumed_by_rewind = FALSE;
1443                                 player->playback_rate = 1.0;
1444                         }
1445
1446                         if ( !player->sent_bos )
1447                         {
1448                                 /* check audio codec field is set or not
1449                                  * we can get it from typefinder or codec's caps.
1450                                  */
1451                                 gchar *audio_codec = NULL;
1452                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
1453
1454                                 /* The codec format can't be sent for audio only case like amr, mid etc.
1455                                  * Because, parser don't make related TAG.
1456                                  * So, if it's not set yet, fill it with found data.
1457                                  */
1458                                 if ( ! audio_codec )
1459                                 {
1460                                         if ( g_strrstr(player->type, "audio/midi"))
1461                                         {
1462                                                 audio_codec = g_strdup("MIDI");
1463
1464                                         }
1465                                         else if ( g_strrstr(player->type, "audio/x-amr"))
1466                                         {
1467                                                 audio_codec = g_strdup("AMR");
1468                                         }
1469                                         else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
1470                                         {
1471                                                 audio_codec = g_strdup("AAC");
1472                                         }
1473                                         else
1474                                         {
1475                                                 audio_codec = g_strdup("unknown");
1476                                         }
1477                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1478
1479                                         MMPLAYER_FREEIF(audio_codec);
1480                                         mmf_attrs_commit(player->attrs);
1481                                         debug_log("set audio codec type with caps\n");
1482                                 }
1483
1484                                 post_bos = TRUE;
1485                         }
1486                 }
1487                 break;
1488
1489                 case MM_PLAYER_STATE_NONE:
1490                 default:
1491                         debug_warning("invalid target state, there is nothing to do.\n");
1492                         break;
1493         }
1494
1495
1496         /* post message to application */
1497         if (MMPLAYER_TARGET_STATE(player) == state)
1498         {
1499                 /* fill the message with state of player */
1500                 msg.state.previous = MMPLAYER_PREV_STATE(player);
1501                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
1502
1503                 debug_log ("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
1504
1505                 /* state changed by asm callback */
1506                 if ( interrupted_by_asm )
1507                 {
1508                         msg.union_type = MM_MSG_UNION_CODE;
1509                         msg.code = player->sm.event_src;
1510                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
1511                 }
1512                 /* state changed by usecase */
1513                 else
1514                 {
1515                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
1516                 }
1517         }
1518         else
1519         {
1520                 debug_log ("intermediate state, do nothing.\n");
1521                 MMPLAYER_PRINT_STATE(player);
1522                 return ret;
1523         }
1524
1525         if ( post_bos )
1526         {
1527                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
1528                 player->sent_bos = TRUE;
1529         }
1530
1531         return ret;
1532 }
1533
1534 gboolean
1535 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
1536 {
1537         return_val_if_fail( player, FALSE );
1538
1539         if ( !player->msg_cb )
1540         {
1541                 return FALSE;
1542         }
1543
1544         //debug_log("Message (type : %d)  will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
1545
1546         player->msg_cb(msgtype, param, player->msg_cb_param);
1547
1548         return TRUE;
1549 }
1550
1551 static gpointer __mmplayer_next_play_thread(gpointer data)
1552 {
1553         mm_player_t* player = (mm_player_t*) data;
1554         MMPlayerGstElement *mainbin = NULL;
1555
1556         return_val_if_fail ( player, NULL );
1557
1558         while ( ! player->next_play_thread_exit )
1559         {
1560                 debug_log("next play thread started. waiting for signal.\n");
1561                 g_cond_wait( player->next_play_thread_cond, player->next_play_thread_mutex );
1562
1563                 debug_log("re building pipeline for next play.\n");
1564
1565                 if ( player->next_play_thread_exit )
1566                 {
1567                         MMPLAYER_PLAYBACK_UNLOCK(player);
1568
1569                         debug_log("exiting next play thread\n");
1570                         break;
1571                 }
1572
1573                 mainbin = player->pipeline->mainbin;
1574
1575                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
1576                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
1577                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
1578                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
1579                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
1580
1581                 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
1582         }
1583
1584         return NULL;
1585 }
1586
1587 static gpointer __mmplayer_repeat_thread(gpointer data)
1588 {
1589         mm_player_t* player = (mm_player_t*) data;
1590         gboolean ret_value = FALSE;
1591         MMHandleType attrs = 0;
1592         gint count = 0;
1593
1594         return_val_if_fail ( player, NULL );
1595
1596         while ( ! player->repeat_thread_exit )
1597         {
1598                 debug_log("repeat thread started. waiting for signal.\n");
1599                 g_cond_wait( player->repeat_thread_cond, player->repeat_thread_mutex );
1600
1601                 if ( player->repeat_thread_exit )
1602                 {
1603                         debug_log("exiting repeat thread\n");
1604                         break;
1605                 }
1606
1607                 if ( !player->cmd_lock )
1608                 {
1609                         debug_log("can't get cmd lock\n");
1610                         return NULL;
1611                 }
1612
1613                 /* lock */
1614                 g_mutex_lock(player->cmd_lock);
1615
1616                 attrs = MMPLAYER_GET_ATTRS(player);
1617
1618                 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1619                 {
1620                         debug_error("can not get play count\n");
1621                         break;
1622                 }
1623
1624                 if ( player->section_repeat )
1625                 {
1626                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1627                 }
1628                 else
1629                 {
1630                         if ( player->playback_rate < 0.0 )
1631                         {
1632                                 player->resumed_by_rewind = TRUE;
1633                                 _mmplayer_set_mute((MMHandleType)player, 0);
1634                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1635                         }
1636
1637                         ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
1638                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1639                                 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1640
1641                         /* initialize */
1642                         player->sent_bos = FALSE;
1643                 }
1644
1645                 if ( ! ret_value )
1646                 {
1647                         debug_error("failed to set position to zero for rewind\n");
1648                         continue;
1649                 }
1650
1651                 /* decrease play count */
1652                 if ( count > 1 )
1653                 {
1654                         /* we successeded to rewind. update play count and then wait for next EOS */
1655                         count--;
1656
1657                         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1658
1659                         /* commit attribute */
1660                         if ( mmf_attrs_commit ( attrs ) )
1661                         {
1662                                 debug_error("failed to commit attribute\n");
1663                         }
1664                 }
1665
1666                 /* unlock */
1667                 g_mutex_unlock(player->cmd_lock);
1668         }
1669
1670         return NULL;
1671 }
1672
1673 static void
1674 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
1675 {
1676         MMHandleType attrs = 0;
1677         guint64 data_size = 0;
1678         gchar* path = NULL;
1679         unsigned long pos_msec = 0;
1680         struct stat sb;
1681
1682         return_if_fail( player && player->pipeline && player->pipeline->mainbin);
1683
1684         __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_msec);       // update last_position
1685
1686         attrs = MMPLAYER_GET_ATTRS(player);
1687         if ( !attrs )
1688         {
1689                 debug_error("fail to get attributes.\n");
1690                 return;
1691         }
1692
1693         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1694         {
1695                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1696
1697                 if (stat(path, &sb) == 0)
1698                 {
1699                         data_size = (guint64)sb.st_size;
1700                 }
1701         }
1702         else if (MMPLAYER_IS_HTTP_STREAMING(player))
1703         {
1704                 data_size = player->http_content_size;
1705         }
1706
1707         __mm_player_streaming_buffering(        player->streamer,
1708                                                                                 buffering_msg,
1709                                                                                 data_size,
1710                                                                                 player->last_position,
1711                                                                                 player->duration);
1712
1713         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
1714
1715         return;
1716 }
1717
1718
1719 static void
1720 __mmplayer_handle_buffering_message ( mm_player_t* player )
1721 {
1722         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1723         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1724         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1725         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1726
1727         return_if_fail ( player );
1728
1729         prev_state = MMPLAYER_PREV_STATE(player);
1730         current_state = MMPLAYER_CURRENT_STATE(player);
1731         target_state = MMPLAYER_TARGET_STATE(player);
1732         pending_state = MMPLAYER_PENDING_STATE(player);
1733
1734         if (MMPLAYER_IS_LIVE_STREAMING(player))
1735                 return;
1736
1737         if ( !player->streamer->is_buffering )
1738         {
1739                 debug_log( "player state : prev %s, current %s, pending %s, target %s \n",
1740                         MMPLAYER_STATE_GET_NAME(prev_state),
1741                         MMPLAYER_STATE_GET_NAME(current_state),
1742                         MMPLAYER_STATE_GET_NAME(pending_state),
1743                         MMPLAYER_STATE_GET_NAME(target_state));
1744
1745                 /* NOTE : if buffering has done, player has to go to target state. */
1746                 switch ( target_state )
1747                 {
1748                         case MM_PLAYER_STATE_PAUSED :
1749                         {
1750                                 switch ( pending_state )
1751                                 {
1752                                         case MM_PLAYER_STATE_PLAYING:
1753                                         {
1754                                                 __gst_pause ( player, TRUE );
1755                                         }
1756                                         break;
1757
1758                                         case MM_PLAYER_STATE_PAUSED:
1759                                         {
1760                                                  debug_log("player is already going to paused state, there is nothing to do.\n");
1761                                         }
1762                                         break;
1763
1764                                         case MM_PLAYER_STATE_NONE:
1765                                         case MM_PLAYER_STATE_NULL:
1766                                         case MM_PLAYER_STATE_READY:
1767                                         default :
1768                                         {
1769                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1770                                         }
1771                                                 break;
1772                                 }
1773                         }
1774                         break;
1775
1776                         case MM_PLAYER_STATE_PLAYING :
1777                         {
1778                                 switch ( pending_state )
1779                                 {
1780                                         case MM_PLAYER_STATE_NONE:
1781                                         {
1782                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
1783                                                         __gst_resume ( player, TRUE );
1784                                         }
1785                                         break;
1786
1787                                         case MM_PLAYER_STATE_PAUSED:
1788                                         {
1789                                                 /* NOTE: It should be worked as asynchronously.
1790                                                  * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1791                                                  */
1792                                                 __gst_resume ( player, TRUE );
1793                                         }
1794                                         break;
1795
1796                                         case MM_PLAYER_STATE_PLAYING:
1797                                         {
1798                                                  debug_log("player is already going to playing state, there is nothing to do.\n");
1799                                         }
1800                                         break;
1801
1802                                         case MM_PLAYER_STATE_NULL:
1803                                         case MM_PLAYER_STATE_READY:
1804                                         default :
1805                                         {
1806                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1807                                         }
1808                                                 break;
1809                                 }
1810                         }
1811                         break;
1812
1813                         case MM_PLAYER_STATE_NULL :
1814                         case MM_PLAYER_STATE_READY :
1815                         case MM_PLAYER_STATE_NONE :
1816                         default:
1817                         {
1818                                 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1819                         }
1820                                 break;
1821                 }
1822         }
1823         else
1824         {
1825                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1826                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
1827                  */
1828                 switch ( pending_state )
1829                 {
1830                         case MM_PLAYER_STATE_NONE:
1831                         {
1832                                 if (current_state != MM_PLAYER_STATE_PAUSED)
1833                                 {
1834                                         debug_log("set pause state during buffering\n");
1835                                         __gst_pause ( player, TRUE );
1836
1837                                         // to cover the weak-signal environment.
1838                                         if (MMPLAYER_IS_RTSP_STREAMING(player))
1839                                         {
1840                                                 unsigned long position = 0;
1841                                                 gint64 pos_msec = 0;
1842
1843                                                 debug_log("[RTSP] seek to the buffering start point\n");
1844
1845                                                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
1846                                                 {
1847                                                         debug_error("failed to get position\n");
1848                                                         break;
1849                                                 }
1850
1851                                                 /* key unit seek */
1852                                                 pos_msec = position * G_GINT64_CONSTANT(1000000);
1853
1854                                                 __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
1855                                                                         GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1856                                                                         pos_msec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1857                                         }
1858                                 }
1859                         }
1860                         break;
1861
1862                         case MM_PLAYER_STATE_PLAYING:
1863                         {
1864                                 __gst_pause ( player, TRUE );
1865                         }
1866                         break;
1867
1868                         case MM_PLAYER_STATE_PAUSED:
1869                         {
1870                         }
1871                         break;
1872
1873                         case MM_PLAYER_STATE_NULL:
1874                         case MM_PLAYER_STATE_READY:
1875                         default :
1876                         {
1877                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1878                         }
1879                                 break;
1880                 }
1881         }
1882 }
1883
1884 static void
1885 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
1886 {
1887         MMPlayerGstElement *textbin;
1888         MMPLAYER_FENTER();
1889
1890         return_if_fail ( player &&
1891                                         player->pipeline &&
1892                                         player->pipeline->textbin);
1893
1894         return_if_fail ( player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst &&
1895                                         player->pipeline->textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst &&
1896                                         player->pipeline->textbin[MMPLAYER_T_TEXT_IDENTITY].gst);
1897
1898         textbin = player->pipeline->textbin;
1899
1900         if (is_drop)
1901         {
1902                 debug_log("Drop subtitle text after getting EOS\n");
1903
1904                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
1905                 g_object_set(textbin[MMPLAYER_T_VIDEO_SINK].gst, "async", FALSE, NULL);
1906                 g_object_set(textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1907                 g_object_set(textbin[MMPLAYER_T_TEXT_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1908
1909                 player->is_subtitle_force_drop = TRUE;
1910         }
1911         else
1912         {
1913                 if (player->is_subtitle_force_drop == TRUE)
1914                 {
1915                         debug_log("Enable subtitle data path without drop\n");
1916
1917                         // player->display_stat = util_get_is_connected_external_display();
1918
1919                         /* if connected with external display */
1920                         if ((player->display_stat == MMPLAYER_DISPLAY_STATUS_HDMI_ACTIVE) ||
1921                                 (player->display_stat == MMPLAYER_DISPLAY_STATUS_UNKNOWN_ACTIVE))
1922                         {
1923                                 g_object_set(textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1924                                 g_object_set(textbin[MMPLAYER_T_TEXT_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1925                                 g_object_set(textbin[MMPLAYER_T_VIDEO_SINK].gst, "async", TRUE, NULL);
1926                                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
1927
1928                                 debug_log ("connected with external display");
1929                         }
1930                         else
1931                         {
1932                                 g_object_set(textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1933                                 g_object_set(textbin[MMPLAYER_T_TEXT_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1934                                 g_object_set(textbin[MMPLAYER_T_VIDEO_SINK].gst, "async", FALSE, NULL);
1935                                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
1936
1937                                 debug_log ("non-connected with external display");
1938                         }
1939
1940                         player->is_subtitle_force_drop = FALSE;
1941                 }
1942         }
1943 }
1944
1945 static gboolean
1946 __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
1947 {
1948         mm_player_t* player = (mm_player_t*) data;
1949         gboolean ret = TRUE;
1950         static gboolean async_done = FALSE;
1951
1952         return_val_if_fail ( player, FALSE );
1953         return_val_if_fail ( msg && GST_IS_MESSAGE(msg), FALSE );
1954
1955         switch ( GST_MESSAGE_TYPE( msg ) )
1956         {
1957                 case GST_MESSAGE_UNKNOWN:
1958                         debug_log("unknown message received\n");
1959                 break;
1960
1961                 case GST_MESSAGE_EOS:
1962                 {
1963                         MMHandleType attrs = 0;
1964                         gint count = 0;
1965
1966                         debug_log("GST_MESSAGE_EOS received\n");
1967
1968                         /* NOTE : EOS event is comming multiple time. watch out it */
1969                         /* check state. we only process EOS when pipeline state goes to PLAYING */
1970                         if ( ! (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) )
1971                         {
1972                                 debug_log("EOS received on non-playing state. ignoring it\n");
1973                                 break;
1974                         }
1975
1976                         __mmplayer_drop_subtitle(player, TRUE);
1977
1978                         if ( (player->audio_stream_cb) && (player->set_mode.pcm_extraction) )
1979                         {
1980                                 GstPad *pad = NULL;
1981
1982                                 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1983
1984                                 debug_log("release audio callback\n");
1985
1986                                 /* release audio callback */
1987                                 gst_pad_remove_buffer_probe (pad, player->audio_cb_probe_id);
1988                                 player->audio_cb_probe_id = 0;
1989                                 /* audio callback should be free because it can be called even though probe remove.*/
1990                                 player->audio_stream_cb = NULL;
1991                                 player->audio_stream_cb_user_param = NULL;
1992
1993                         }
1994
1995                         /* rewind if repeat count is greater then zero */
1996                         /* get play count */
1997                         attrs = MMPLAYER_GET_ATTRS(player);
1998
1999                         if ( attrs )
2000                         {
2001                                 gboolean smooth_repeat = FALSE;
2002
2003                                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
2004                                 mm_attrs_get_int_by_name(attrs, "profile_smooth_repeat", &smooth_repeat);
2005
2006                                 player->play_count = count;
2007
2008                                 debug_log("remaining play count: %d, playback rate: %f\n", count, player->playback_rate);
2009
2010                                 if ( count > 1 || count == -1 || player->playback_rate < 0.0 ) /* default value is 1 */
2011                                 {
2012                                         if ( smooth_repeat )
2013                                         {
2014                                                 debug_log("smooth repeat enabled. seeking operation will be excuted in new thread\n");
2015
2016                                                 g_cond_signal( player->repeat_thread_cond );
2017
2018                                                 break;
2019                                         }
2020                                         else
2021                                         {
2022                                                 gint ret_value = 0;
2023
2024                                                 if ( player->section_repeat )
2025                                                 {
2026                                                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
2027                                                 }
2028                                                 else
2029                                                 {
2030                                                         if ( player->playback_rate < 0.0 )
2031                                                         {
2032                                                                 player->resumed_by_rewind = TRUE;
2033                                                                 _mmplayer_set_mute((MMHandleType)player, 0);
2034                                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
2035                                                         }
2036
2037                                                         __mmplayer_handle_eos_delay( player, player->ini.delay_before_repeat );
2038
2039                                                         /* initialize */
2040                                                         player->sent_bos = FALSE;
2041                                                 }
2042
2043                                                 if ( MM_ERROR_NONE != ret_value )
2044                                                 {
2045                                                         debug_error("failed to set position to zero for rewind\n");
2046                                                 }
2047
2048                                                 /* not posting eos when repeating */
2049                                                 break;
2050                                         }
2051                                 }
2052                         }
2053
2054                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-eos" );
2055
2056                         /* post eos message to application */
2057                         __mmplayer_handle_eos_delay( player, player->ini.eos_delay );
2058
2059                         /* reset last position */
2060                         player->last_position = 0;
2061                 }
2062                 break;
2063
2064                 case GST_MESSAGE_ERROR:
2065                 {
2066                         GError *error = NULL;
2067                         gchar* debug = NULL;
2068
2069                         /* generating debug info before returning error */
2070                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-error" );
2071
2072                         /* get error code */
2073                         gst_message_parse_error( msg, &error, &debug );
2074
2075                         if ( gst_structure_has_name ( msg->structure, "streaming_error" ) )
2076                         {
2077                                 /* Note : the streaming error from the streaming source is handled
2078                                  *   using __mmplayer_handle_streaming_error.
2079                                  */
2080                                 __mmplayer_handle_streaming_error ( player, msg );
2081
2082                                 /* dump state of all element */
2083                                 __mmplayer_dump_pipeline_state( player );
2084                         }
2085                         else
2086                         {
2087                                 /* traslate gst error code to msl error code. then post it
2088                                  * to application if needed
2089                                  */
2090                                 __mmplayer_handle_gst_error( player, msg, error );
2091
2092                                 if (debug)
2093                                 {
2094                                         debug_error ("error debug : %s", debug);
2095                                 }
2096
2097                         }
2098
2099                         if (MMPLAYER_IS_HTTP_PD(player))
2100                         {
2101                                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
2102                         }
2103
2104                         MMPLAYER_FREEIF( debug );
2105                         g_error_free( error );
2106                 }
2107                 break;
2108
2109                 case GST_MESSAGE_WARNING:
2110                 {
2111                         char* debug = NULL;
2112                         GError* error = NULL;
2113
2114                         gst_message_parse_warning(msg, &error, &debug);
2115
2116                         debug_log("warning : %s\n", error->message);
2117                         debug_log("debug : %s\n", debug);
2118
2119                         MMPLAYER_POST_MSG( player, MM_MESSAGE_WARNING, NULL );
2120
2121                         MMPLAYER_FREEIF( debug );
2122                         g_error_free( error );
2123                 }
2124                 break;
2125
2126                 case GST_MESSAGE_TAG:
2127                 {
2128                         debug_log("GST_MESSAGE_TAG\n");
2129                         if ( ! __mmplayer_gst_extract_tag_from_msg( player, msg ) )
2130                         {
2131                                 debug_warning("failed to extract tags from gstmessage\n");
2132                         }
2133                 }
2134                 break;
2135
2136                 case GST_MESSAGE_BUFFERING:
2137                 {
2138                         MMMessageParamType msg_param = {0, };
2139                         int asm_result = MM_ERROR_NONE;
2140
2141                         if (!MMPLAYER_IS_STREAMING(player))
2142                                 break;
2143
2144                         /* ignore the prev buffering message */
2145                         if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (player->streamer->is_buffering_done == TRUE))
2146                         {
2147                                 gint buffer_percent = 0;
2148
2149                                 gst_message_parse_buffering (msg, &buffer_percent);
2150
2151                                 if (buffer_percent == MAX_BUFFER_PERCENT)
2152                                 {
2153                                         debug_log ("Ignored all the previous buffering msg! (got %d%%)\n", buffer_percent);
2154                                         player->streamer->is_buffering_done = FALSE;
2155                                 }
2156
2157                                 break;
2158                         }
2159
2160                         /* update ASM state to ASM_STATE_PLAYING */
2161                         /* fixed ASM_STATE_WAITING -> ASM_STATE_PLAYING for Samsunlink issue*/
2162                         if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED))
2163                         {
2164                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_WAITING, TRUE);
2165                                 if ( asm_result != MM_ERROR_NONE )
2166                                 {
2167                                         debug_warning("failed to set asm state to waiting, but keep going...\n");
2168                                 }
2169                         }
2170
2171                         __mmplayer_update_buffer_setting(player, msg);
2172
2173                         __mmplayer_handle_buffering_message ( player );
2174
2175                         msg_param.connection.buffering = player->streamer->buffering_percent;
2176                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param );
2177                         if (MMPLAYER_IS_RTSP_STREAMING(player) && (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT))
2178                         {
2179                                 if (player->doing_seek)
2180                                 {
2181                                         if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2182                                         {
2183                                                 player->doing_seek = FALSE;
2184                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2185                                         }
2186                                         else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2187                                         {
2188                                                 async_done = TRUE;
2189                                         }
2190                                 }
2191                         }
2192                 }
2193                 break;
2194
2195                 case GST_MESSAGE_STATE_CHANGED:
2196                 {
2197                         MMPlayerGstElement *mainbin;
2198                         const GValue *voldstate, *vnewstate, *vpending;
2199                         GstState oldstate, newstate, pending;
2200
2201                         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
2202                         {
2203                                 debug_error("player pipeline handle is null");
2204                                 break;
2205                         }
2206
2207                         mainbin = player->pipeline->mainbin;
2208
2209                         /* we only handle messages from pipeline */
2210                         if( msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst )
2211                                 break;
2212
2213                         /* get state info from msg */
2214                         voldstate = gst_structure_get_value (msg->structure, "old-state");
2215                         vnewstate = gst_structure_get_value (msg->structure, "new-state");
2216                         vpending = gst_structure_get_value (msg->structure, "pending-state");
2217
2218                         oldstate = (GstState)voldstate->data[0].v_int;
2219                         newstate = (GstState)vnewstate->data[0].v_int;
2220                         pending = (GstState)vpending->data[0].v_int;
2221
2222                         debug_log("state changed [%s] : %s ---> %s     final : %s\n",
2223                                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
2224                                 gst_element_state_get_name( (GstState)oldstate ),
2225                                 gst_element_state_get_name( (GstState)newstate ),
2226                                 gst_element_state_get_name( (GstState)pending ) );
2227
2228                         if (oldstate == newstate)
2229                         {
2230                                 debug_log("pipeline reports state transition to old state");
2231                                 break;
2232                         }
2233
2234                         switch(newstate)
2235                         {
2236                                 case GST_STATE_VOID_PENDING:
2237                                 break;
2238
2239                                 case GST_STATE_NULL:
2240                                 break;
2241
2242                                 case GST_STATE_READY:
2243                                 break;
2244
2245                                 case GST_STATE_PAUSED:
2246                                 {
2247                                         gboolean prepare_async = FALSE;
2248                                         gboolean is_drm = FALSE;
2249
2250                                         if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction)
2251                                                 __mmplayer_configure_audio_callback(player);
2252
2253                                         if ( ! player->sent_bos && oldstate == GST_STATE_READY) // managed prepare async case
2254                                         {
2255                                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
2256                                                 debug_log("checking prepare mode for async transition - %d", prepare_async);
2257                                         }
2258
2259                                         if ( MMPLAYER_IS_STREAMING(player) || prepare_async )
2260                                         {
2261                                                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
2262
2263                                                 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
2264                                                 {
2265                                                         __mm_player_streaming_set_content_bitrate(player->streamer,
2266                                                                 player->total_maximum_bitrate, player->total_bitrate);
2267                                                 }
2268                                         }
2269
2270                                         /* NOTE : should consider streaming case */
2271                                         /* check if drm file */
2272                                         if ((player->pipeline->mainbin[MMPLAYER_M_SRC].gst) &&
2273                                                 (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm")))
2274                                         {
2275                                                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
2276
2277                                                 if (is_drm)
2278                                                 {
2279                                                         player->is_drm_file = TRUE;
2280                                                 }
2281                                         }
2282                                 }
2283                                 break;
2284
2285                                 case GST_STATE_PLAYING:
2286                                 {
2287                                         if ( MMPLAYER_IS_STREAMING(player) ) // managed prepare async case when buffering is completed
2288                                         {
2289                                                 // pending state should be reset oyherwise, it's still playing even though it's resumed after bufferging.
2290                                                 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
2291                                                         (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
2292                                                 {
2293                                                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING);
2294                                                 }
2295                                         }
2296
2297                                         if (player->src_changed)
2298                                         {
2299                                                 _mmplayer_update_content_attrs(player, ATTR_ALL);
2300                                                 player->src_changed = FALSE;
2301                                         }
2302
2303                                         if (player->doing_seek && async_done)
2304                                         {
2305                                                 player->doing_seek = FALSE;
2306                                                 async_done = FALSE;
2307                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2308                                         }
2309                                 }
2310                                 break;
2311
2312                                 default:
2313                                 break;
2314                         }
2315                 }
2316                 break;
2317
2318                 case GST_MESSAGE_CLOCK_LOST:
2319                         {
2320                                 GstClock *clock = NULL;
2321                                 gst_message_parse_clock_lost (msg, &clock);
2322                                 debug_log("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2323                                 g_print ("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2324
2325                                 if (((player->ini.provide_clock_for_music) && (!player->videodec_linked)) ||
2326                                         ((player->ini.provide_clock_for_movie) && (player->videodec_linked)))
2327                                 {
2328                                         debug_log ("Provide clock is TRUE, do pause->resume\n");
2329                                         __gst_pause(player, FALSE);
2330                                         __gst_resume(player, FALSE);
2331                                 }
2332                         }
2333                         break;
2334
2335                 case GST_MESSAGE_NEW_CLOCK:
2336                         {
2337                                 GstClock *clock = NULL;
2338                                 gst_message_parse_new_clock (msg, &clock);
2339                                 debug_log("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2340                         }
2341                         break;
2342
2343                 case GST_MESSAGE_ELEMENT:
2344                         {
2345                                 const gchar *structure_name;
2346                                 gint count = 0;
2347                                 MMHandleType attrs = 0;
2348
2349                                 attrs = MMPLAYER_GET_ATTRS(player);
2350                                 if ( !attrs )
2351                                 {
2352                                         debug_error("cannot get content attribute");
2353                                         ret = FALSE;
2354                                         break;
2355                                 }
2356
2357                                 if(msg->structure == NULL)
2358                                         break;
2359
2360                                 structure_name = gst_structure_get_name(msg->structure);
2361                                 if(!strcmp(structure_name, "Language_list"))
2362                                 {
2363                                         const GValue *lang_list = NULL;
2364                                         lang_list = gst_structure_get_value (msg->structure, "lang_list");
2365                                         if(lang_list != NULL)
2366                                         {
2367                                                 count = g_list_length((GList *)g_value_get_pointer (lang_list));
2368                                                 if (count > 1)
2369                                                         debug_log("Total audio tracks (from parser) = %d \n",count);
2370                                         }
2371                                 }
2372
2373                                 if (!strcmp (structure_name, "Ext_Sub_Language_List"))
2374                                 {
2375                                         const GValue *lang_list = NULL;
2376                                         MMPlayerLangStruct *temp = NULL;
2377
2378                                         lang_list = gst_structure_get_value (msg->structure, "lang_list");
2379                                         if (lang_list != NULL)
2380                                         {
2381                                                 count = g_list_length ((GList *)g_value_get_pointer (lang_list));
2382                                                 if (count)
2383                                                 {
2384                                                   player->subtitle_language_list = (GList *)g_value_get_pointer (lang_list);
2385                                                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
2386                                                         if (mmf_attrs_commit (attrs))
2387                                                           debug_error("failed to commit.\n");
2388                                                         debug_log("Total external subtitle tracks = %d \n", count);
2389                                                 }
2390                                                 while (count)
2391                                                 {
2392                                                         temp = g_list_nth_data (player->subtitle_language_list, count - 1);
2393                                                         debug_log ("value of lang_key is %s and lang_code is %s",
2394                                                                                 temp->language_key, temp->language_code);
2395                                                         count--;
2396                                                 }
2397                                         }
2398                                 }
2399                                 if (!strcmp (structure_name, "Int_Sub_Language_List"))
2400                                 {
2401                                         const GValue *lang_list = NULL;
2402                                         MMPlayerLangStruct *temp = NULL;
2403                                         lang_list = gst_structure_get_value (msg->structure, "lang_list");
2404                                         if (lang_list != NULL && !player->is_external_subtitle_present)
2405                                         {
2406                                                 count = g_list_length ((GList *)g_value_get_pointer (lang_list));
2407                                                 if (count)
2408                                                 {
2409                                                         player->subtitle_language_list = (GList *)g_value_get_pointer (lang_list);
2410                                                         g_object_set (G_OBJECT (player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_INTERNAL].gst), "lang-list", player->subtitle_language_list, NULL);
2411                                                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
2412                                                         if (mmf_attrs_commit (attrs))
2413                                                           debug_error("failed to commit.\n");
2414                                                         debug_log("Total internal subtitle tracks = %d \n", count);
2415                                                 }
2416                                                 while (count)
2417                                                 {
2418                                                         temp = g_list_nth_data (player->subtitle_language_list, count - 1);
2419                                                         debug_log ("value of lang_key is %s and lang_code is %s",
2420                                                                                 temp->language_key, temp->language_code);
2421                                                         count--;
2422                                                 }
2423                                         } else if (lang_list != NULL) {
2424                                           GList* internal_lang_list;
2425                                           internal_lang_list = (GList *)g_value_get_pointer (lang_list);
2426                                           debug_log ("it is internal & external case simultaneously");
2427                                           g_object_set (G_OBJECT (player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_INTERNAL].gst), "lang-list", internal_lang_list, NULL);
2428                                         } else {
2429                                           debug_error ("language list is coming null");
2430                                         }
2431                                 }
2432
2433                                 /* custom message */
2434                                 if (!strcmp (structure_name, "audio_codec_not_supported")) {
2435                                         MMMessageParamType msg_param = {0,};
2436                                         msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
2437                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
2438                                 }
2439                         }
2440                         break;
2441
2442                 case GST_MESSAGE_DURATION:
2443                 {
2444                         debug_log("GST_MESSAGE_DURATION\n");
2445                         ret = __mmplayer_gst_handle_duration(player, msg);
2446                         if (!ret)
2447                         {
2448                                 debug_warning("failed to update duration");
2449                         }
2450                 }
2451
2452                 break;
2453
2454                 case GST_MESSAGE_ASYNC_START:
2455                 {
2456                         debug_log("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2457                 }
2458                 break;
2459
2460                 case GST_MESSAGE_ASYNC_DONE:
2461                 {
2462                         debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2463
2464                         /* we only handle messages from pipeline */
2465                         if( msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
2466                                 break;
2467
2468                         if( !MMPLAYER_IS_RTSP_STREAMING(player) )
2469                         {
2470                                 if (player->doing_seek)
2471                                 {
2472                                         if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2473                                         {
2474                                                 player->doing_seek = FALSE;
2475                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2476                                         }
2477                                         else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2478                                         {
2479                                                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2480                                                         (player->streamer) &&
2481                                                         (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
2482                                                         (player->streamer->is_buffering == FALSE))
2483                                                 {
2484                                                         GstQuery *query = NULL;
2485                                                         gboolean busy = FALSE;
2486                                                         gint percent = 0;
2487
2488                                                         if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer)
2489                                                         {
2490                                                                 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
2491                                                                 if ( gst_element_query (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query ) )
2492                                                                 {
2493                                                                         gst_query_parse_buffering_percent ( query, &busy, &percent);
2494                                                                 }
2495                                                                 gst_query_unref (query);
2496
2497                                                                 debug_log("buffered percent(%s): %d\n",
2498                                                                         GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
2499                                                         }
2500
2501                                                         if (percent >= 100)
2502                                                         {
2503                                                                 player->streamer->is_buffering = FALSE;
2504                                                                 __mmplayer_handle_buffering_message(player);
2505                                                         }
2506                                                 }
2507
2508                                                 async_done = TRUE;
2509                                         }
2510                                 }
2511                         }
2512                 }
2513                 break;
2514
2515                 #if 0 /* delete unnecessary logs */
2516                 case GST_MESSAGE_REQUEST_STATE:         debug_log("GST_MESSAGE_REQUEST_STATE\n"); break;
2517                 case GST_MESSAGE_STEP_START:            debug_log("GST_MESSAGE_STEP_START\n"); break;
2518                 case GST_MESSAGE_QOS:                           debug_log("GST_MESSAGE_QOS\n"); break;
2519                 case GST_MESSAGE_PROGRESS:                      debug_log("GST_MESSAGE_PROGRESS\n"); break;
2520                 case GST_MESSAGE_ANY:                           debug_log("GST_MESSAGE_ANY\n"); break;
2521                 case GST_MESSAGE_INFO:                          debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2522                 case GST_MESSAGE_STATE_DIRTY:           debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2523                 case GST_MESSAGE_STEP_DONE:                     debug_log("GST_MESSAGE_STEP_DONE\n"); break;
2524                 case GST_MESSAGE_CLOCK_PROVIDE:         debug_log("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
2525                 case GST_MESSAGE_STRUCTURE_CHANGE:      debug_log("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
2526                 case GST_MESSAGE_STREAM_STATUS:         debug_log("GST_MESSAGE_STREAM_STATUS\n"); break;
2527                 case GST_MESSAGE_APPLICATION:           debug_log("GST_MESSAGE_APPLICATION\n"); break;
2528                 case GST_MESSAGE_SEGMENT_START:         debug_log("GST_MESSAGE_SEGMENT_START\n"); break;
2529                 case GST_MESSAGE_SEGMENT_DONE:          debug_log("GST_MESSAGE_SEGMENT_DONE\n"); break;
2530                 case GST_MESSAGE_LATENCY:                               debug_log("GST_MESSAGE_LATENCY\n"); break;
2531                 #endif
2532
2533                 default:
2534                 break;
2535         }
2536
2537         /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
2538          * gst_element_post_message api takes ownership of the message.
2539          */
2540         //gst_message_unref( msg );
2541
2542         return ret;
2543 }
2544
2545 static gboolean
2546 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
2547 {
2548         GstFormat format;
2549         gint64 bytes = 0;
2550
2551         MMPLAYER_FENTER();
2552
2553         return_val_if_fail(player, FALSE);
2554         return_val_if_fail(msg, FALSE);
2555
2556         gst_message_parse_duration (msg, &format, &bytes);
2557
2558         if (MMPLAYER_IS_HTTP_STREAMING(player) && format == GST_FORMAT_BYTES )
2559         {
2560                 debug_log("data total size of http content: %lld", bytes);
2561                 player->http_content_size = bytes;
2562         }
2563         else if (format == GST_FORMAT_TIME)
2564         {
2565                 /* handling audio clip which has vbr. means duration is keep changing */
2566                 _mmplayer_update_content_attrs (player, ATTR_DURATION );
2567         }
2568         else
2569         {
2570                 debug_warning("duration is neither BYTES or TIME");
2571                 return FALSE;
2572         }
2573
2574         MMPLAYER_FLEAVE();
2575
2576         return TRUE;
2577 }
2578
2579
2580 static gboolean
2581 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg) // @
2582 {
2583
2584 /* macro for better code readability */
2585 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
2586 if (gst_tag_list_get_string(tag_list, gsttag, &string)) \
2587 {\
2588         if (string != NULL)\
2589         {\
2590                 secure_debug_log ( "update tag string : %s\n", string); \
2591                 mm_attrs_set_string_by_name(attribute, playertag, string); \
2592                 g_free(string);\
2593                 string = NULL;\
2594         }\
2595 }
2596
2597 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
2598 value = gst_tag_list_get_value_index(tag_list, gsttag, index); \
2599 if (value) \
2600 {\
2601         buffer = gst_value_get_buffer (value); \
2602         secure_debug_log ( "update album cover data : %p, size : %d\n", GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); \
2603         MMPLAYER_FREEIF(player->album_art); \
2604         player->album_art = (gchar *)g_malloc(GST_BUFFER_SIZE(buffer)); \
2605         if (player->album_art) \
2606         { \
2607                 memcpy(player->album_art, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); \
2608                 mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, GST_BUFFER_SIZE(buffer)); \
2609                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) \
2610                 { \
2611                         msg_param.data = (void *)player->album_art; \
2612                         msg_param.size = GST_BUFFER_SIZE(buffer); \
2613                         MMPLAYER_POST_MSG (player, MM_MESSAGE_IMAGE_BUFFER, &msg_param); \
2614                         secure_debug_log ( "post message image buffer data : %p, size : %d\n", GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); \
2615                 } \
2616         } \
2617 }
2618
2619 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
2620 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint))\
2621 {\
2622         if(v_uint)\
2623         {\
2624                 if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) \
2625                 {\
2626                         if (player->updated_bitrate_count == 0) \
2627                                 mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
2628                         if (player->updated_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2629                         {\
2630                                 player->bitrate[player->updated_bitrate_count] = v_uint;\
2631                                 player->total_bitrate += player->bitrate[player->updated_maximum_bitrate_count]; \
2632                                 player->updated_bitrate_count++; \
2633                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate);\
2634                                 secure_debug_log ( "update bitrate %d[bps] of stream #%d.\n", v_uint, player->updated_bitrate_count);\
2635                         }\
2636                 }\
2637                 else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) \
2638                 {\
2639                         if (player->updated_maximum_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2640                         {\
2641                                 player->maximum_bitrate[player->updated_maximum_bitrate_count] = v_uint;\
2642                                 player->total_maximum_bitrate += player->maximum_bitrate[player->updated_maximum_bitrate_count]; \
2643                                 player->updated_maximum_bitrate_count++; \
2644                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate); \
2645                                 secure_debug_log ( "update maximum bitrate %d[bps] of stream #%d\n", v_uint, player->updated_maximum_bitrate_count);\
2646                         }\
2647                 }\
2648                 else\
2649                 {\
2650                         mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
2651                 }\
2652                 v_uint = 0;\
2653         }\
2654 }
2655
2656 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
2657 if (gst_tag_list_get_date(tag_list, gsttag, &date))\
2658 {\
2659         if (date != NULL)\
2660         {\
2661                 string = g_strdup_printf("%d", g_date_get_year(date));\
2662                 mm_attrs_set_string_by_name(attribute, playertag, string);\
2663                 secure_debug_log ( "metainfo year : %s\n", string);\
2664                 MMPLAYER_FREEIF(string);\
2665                 g_date_free(date);\
2666         }\
2667 }
2668
2669 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
2670 if(gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64))\
2671 {\
2672         if(v_uint64)\
2673         {\
2674                 /* FIXIT : don't know how to store date */\
2675                 g_assert(1);\
2676                 v_uint64 = 0;\
2677         }\
2678 }
2679
2680 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
2681 if(gst_tag_list_get_double(tag_list, gsttag, &v_double))\
2682 {\
2683         if(v_double)\
2684         {\
2685                 /* FIXIT : don't know how to store date */\
2686                 g_assert(1);\
2687                 v_double = 0;\
2688         }\
2689 }
2690
2691         /* function start */
2692         GstTagList* tag_list = NULL;
2693
2694         MMHandleType attrs = 0;
2695
2696         char *string = NULL;
2697         guint v_uint = 0;
2698         GDate *date = NULL;
2699         /* album cover */
2700         GstBuffer *buffer = NULL;
2701         gint index = 0;
2702         const GValue *value;
2703         MMMessageParamType msg_param = {0, };
2704
2705         /* currently not used. but those are needed for above macro */
2706         //guint64 v_uint64 = 0;
2707         //gdouble v_double = 0;
2708
2709         return_val_if_fail( player && msg, FALSE );
2710
2711         attrs = MMPLAYER_GET_ATTRS(player);
2712
2713         return_val_if_fail( attrs, FALSE );
2714
2715         /* get tag list from gst message */
2716         gst_message_parse_tag(msg, &tag_list);
2717
2718         /* store tags to player attributes */
2719         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
2720         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
2721         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
2722         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
2723         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
2724         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
2725         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
2726         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
2727         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
2728         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
2729         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
2730         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
2731         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
2732         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
2733         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
2734         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
2735         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
2736         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
2737         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
2738         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
2739         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
2740         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
2741         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
2742         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
2743         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
2744         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
2745         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
2746         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
2747         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
2748         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
2749         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
2750         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
2751         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
2752         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
2753         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
2754         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
2755         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
2756         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
2757         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
2758         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
2759         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
2760         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
2761         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
2762         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
2763         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
2764
2765         if ( mmf_attrs_commit ( attrs ) )
2766                 debug_error("failed to commit.\n");
2767
2768         gst_tag_list_free(tag_list);
2769
2770         return TRUE;
2771 }
2772
2773 static void
2774 __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data)  // @
2775 {
2776         mm_player_t* player = (mm_player_t*) data;
2777
2778         MMPLAYER_FENTER();
2779
2780         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2781           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2782           * num_dynamic_pad. and this is no-more-pad situation which means mo more pad will be added.
2783           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2784
2785           * [1] audio and video will be dumped with filesink.
2786           * [2] autoplugging is done by just using pad caps.
2787           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
2788           * and the video will be dumped via filesink.
2789           */
2790         if ( player->num_dynamic_pad == 0 )
2791         {
2792                 debug_log("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
2793
2794                 if ( ! __mmplayer_gst_remove_fakesink( player,
2795                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
2796                 {
2797                         /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
2798                          * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
2799                          * source element are not same. To overcome this situation, this function will called
2800                          * several places and several times. Therefore, this is not an error case.
2801                          */
2802                         return;
2803                 }
2804         }
2805
2806         /* create dot before error-return. for debugging */
2807         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-no-more-pad" );
2808
2809         player->no_more_pad = TRUE;
2810
2811         MMPLAYER_FLEAVE();
2812 }
2813
2814 static gboolean
2815 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink) // @
2816 {
2817         GstElement* parent = NULL;
2818
2819         return_val_if_fail(player && player->pipeline, FALSE);
2820
2821         /* if we have no fakesink. this meas we are using decodebin2 which doesn'
2822         t need to add extra fakesink */
2823         return_val_if_fail(fakesink, TRUE);
2824
2825         /* lock */
2826         g_mutex_lock( player->fsink_lock );
2827
2828         if ( ! fakesink->gst )
2829         {
2830                 goto ERROR;
2831         }
2832
2833         /* get parent of fakesink */
2834         parent = (GstElement*)gst_object_get_parent( (GstObject*)fakesink->gst );
2835         if ( ! parent )
2836         {
2837                 debug_log("fakesink already removed\n");
2838                 goto ERROR;
2839         }
2840
2841         gst_element_set_locked_state( fakesink->gst, TRUE );
2842
2843         /* setting the state to NULL never returns async
2844          * so no need to wait for completion of state transiton
2845          */
2846         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (fakesink->gst, GST_STATE_NULL) )
2847         {
2848                 debug_error("fakesink state change failure!\n");
2849
2850                 /* FIXIT : should I return here? or try to proceed to next? */
2851                 /* return FALSE; */
2852         }
2853
2854         /* remove fakesink from it's parent */
2855         if ( ! gst_bin_remove( GST_BIN( parent ), fakesink->gst ) )
2856         {
2857                 debug_error("failed to remove fakesink\n");
2858
2859                 gst_object_unref( parent );
2860
2861                 goto ERROR;
2862         }
2863
2864         gst_object_unref( parent );
2865
2866         debug_log("state-holder removed\n");
2867
2868         gst_element_set_locked_state( fakesink->gst, FALSE );
2869
2870         g_mutex_unlock( player->fsink_lock );
2871         return TRUE;
2872
2873 ERROR:
2874         if ( fakesink->gst )
2875         {
2876                 gst_element_set_locked_state( fakesink->gst, FALSE );
2877         }
2878
2879         g_mutex_unlock( player->fsink_lock );
2880         return FALSE;
2881 }
2882
2883
2884 static void
2885 __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2886 {
2887         GstPad *sinkpad = NULL;
2888         GstCaps* caps = NULL;
2889         GstElement* new_element = NULL;
2890         GstStructure* str = NULL;
2891         const gchar* name = NULL;
2892
2893         mm_player_t* player = (mm_player_t*) data;
2894
2895         MMPLAYER_FENTER();
2896
2897         return_if_fail( element && pad );
2898         return_if_fail( player &&
2899                                         player->pipeline &&
2900                                         player->pipeline->mainbin );
2901
2902
2903         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2904          * num_dynamic_pad will decreased after creating a sinkbin.
2905          */
2906         player->num_dynamic_pad++;
2907         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2908
2909         /* perform autoplugging if dump is disabled */
2910         if ( player->ini.rtsp_do_typefinding )
2911         {
2912                 /* create typefind */
2913                 new_element = gst_element_factory_make( "typefind", NULL );
2914                 if ( ! new_element )
2915                 {
2916                         debug_error("failed to create typefind\n");
2917                         goto ERROR;
2918                 }
2919
2920                 MMPLAYER_SIGNAL_CONNECT(        player,
2921                                                                         G_OBJECT(new_element),
2922                                                                         MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2923                                                                         "have-type",
2924                                                                         G_CALLBACK(__mmplayer_typefind_have_type),
2925                                                                         (gpointer)player);
2926
2927                 /* FIXIT : try to remove it */
2928                 player->have_dynamic_pad = FALSE;
2929         }
2930         else  /* NOTE : use pad's caps directely. if enabled. what I am assuming is there's no elemnt has dynamic pad */
2931         {
2932                 debug_log("using pad caps to autopluging instead of doing typefind\n");
2933
2934                 caps = gst_pad_get_caps( pad );
2935
2936                 MMPLAYER_CHECK_NULL( caps );
2937
2938                 /* clear  previous result*/
2939                 player->have_dynamic_pad = FALSE;
2940
2941                 str = gst_caps_get_structure(caps, 0);
2942
2943                 if ( ! str )
2944                 {
2945                         debug_error ("cannot get structure from capse.\n");
2946                         goto ERROR;
2947                 }
2948
2949                 name = gst_structure_get_name (str);
2950                 if ( ! name )
2951                 {
2952                         debug_error ("cannot get mimetype from structure.\n");
2953                         goto ERROR;
2954                 }
2955
2956                 if (strstr(name, "video"))
2957                 {
2958                         gint stype = 0;
2959                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
2960
2961                         if (stype == MM_DISPLAY_SURFACE_NULL)
2962                         {
2963                                 if (player->v_stream_caps)
2964                                 {
2965                                         gst_caps_unref(player->v_stream_caps);
2966                                         player->v_stream_caps = NULL;
2967                                 }
2968
2969                                 new_element = gst_element_factory_make("fakesink", NULL);
2970                                 player->num_dynamic_pad--;
2971                                 goto NEW_ELEMENT;
2972                         }
2973                 }
2974
2975                 /* clear  previous result*/
2976                 player->have_dynamic_pad = FALSE;
2977
2978                 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
2979                 {
2980                         debug_error("failed to autoplug for caps");
2981                         goto ERROR;
2982                 }
2983
2984                 /* check if there's dynamic pad*/
2985                 if( player->have_dynamic_pad )
2986                 {
2987                         debug_error("using pad caps assums there's no dynamic pad !\n");
2988                         debug_error("try with enalbing rtsp_do_typefinding\n");
2989                         goto ERROR;
2990                 }
2991
2992                 gst_caps_unref( caps );
2993                 caps = NULL;
2994         }
2995
2996         NEW_ELEMENT:
2997
2998         /* excute new_element if created*/
2999         if ( new_element )
3000         {
3001                 debug_log("adding new element to pipeline\n");
3002
3003                 /* set state to READY before add to bin */
3004                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
3005
3006                 /* add new element to the pipeline */
3007                 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
3008                 {
3009                         debug_error("failed to add autoplug element to bin\n");
3010                         goto ERROR;
3011                 }
3012
3013                 /* get pad from element */
3014                 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
3015                 if ( !sinkpad )
3016                 {
3017                         debug_error("failed to get sinkpad from autoplug element\n");
3018                         goto ERROR;
3019                 }
3020
3021                 /* link it */
3022                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
3023                 {
3024                         debug_error("failed to link autoplug element\n");
3025                         goto ERROR;
3026                 }
3027
3028                 gst_object_unref (sinkpad);
3029                 sinkpad = NULL;
3030
3031                 /* run. setting PLAYING here since streamming source is live source */
3032                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
3033         }
3034
3035         MMPLAYER_FLEAVE();
3036
3037         return;
3038
3039 STATE_CHANGE_FAILED:
3040 ERROR:
3041         /* FIXIT : take care if new_element has already added to pipeline */
3042         if ( new_element )
3043                 gst_object_unref(GST_OBJECT(new_element));
3044
3045         if ( sinkpad )
3046                 gst_object_unref(GST_OBJECT(sinkpad));
3047
3048         if ( caps )
3049                 gst_object_unref(GST_OBJECT(caps));
3050
3051         /* FIXIT : how to inform this error to MSL ????? */
3052         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
3053          * then post an error to application
3054          */
3055 }
3056
3057
3058
3059 /* FIXIT : check indent */
3060 static void
3061 __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
3062 {
3063   GstPad *sinkpad = NULL;
3064   GstCaps* caps = NULL;
3065   GstElement* new_element = NULL;
3066   enum MainElementID element_id = MMPLAYER_M_NUM;
3067
3068   mm_player_t* player = (mm_player_t*) data;
3069
3070   MMPLAYER_FENTER();
3071
3072   return_if_fail( element && pad );
3073   return_if_fail(  player &&
3074           player->pipeline &&
3075           player->pipeline->mainbin );
3076
3077   debug_log("stream count inc : %d\n", player->num_dynamic_pad);
3078
3079   {
3080     debug_log("using pad caps to autopluging instead of doing typefind\n");
3081     caps = gst_pad_get_caps( pad );
3082     MMPLAYER_CHECK_NULL( caps );
3083     /* clear  previous result*/
3084     player->have_dynamic_pad = FALSE;
3085     new_element = gst_element_factory_make("rtpmp2tdepay", "wfd_rtp_depay");
3086     if ( !new_element )
3087     {
3088       debug_error ( "failed to create wfd rtp depay element\n" );
3089       goto ERROR;
3090     }
3091     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
3092     /* add new element to the pipeline */
3093     if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
3094     {
3095       debug_log("failed to add autoplug element to bin\n");
3096       goto ERROR;
3097     }
3098     /* get pad from element */
3099     sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
3100     if ( !sinkpad )
3101     {
3102       debug_log("failed to get sinkpad from autoplug element\n");
3103       goto ERROR;
3104     }
3105     /* link it */
3106     if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
3107     {
3108       debug_log("failed to link autoplug element\n");
3109       goto ERROR;
3110     }
3111     gst_object_unref (sinkpad);
3112     sinkpad = NULL;
3113     pad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "src" );
3114     caps = gst_pad_get_caps( pad );
3115     MMPLAYER_CHECK_NULL( caps );
3116     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
3117     /* create typefind */
3118     new_element = gst_element_factory_make( "typefind", NULL );
3119     if ( ! new_element )
3120     {
3121       debug_log("failed to create typefind\n");
3122       goto ERROR;
3123     }
3124
3125     MMPLAYER_SIGNAL_CONNECT(   player,
3126                 G_OBJECT(new_element),
3127                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
3128                 "have-type",
3129                 G_CALLBACK(__mmplayer_typefind_have_type),
3130                 (gpointer)player);
3131
3132     player->have_dynamic_pad = FALSE;
3133   }
3134
3135   /* excute new_element if created*/
3136   if ( new_element )
3137   {
3138     debug_log("adding new element to pipeline\n");
3139
3140     /* set state to READY before add to bin */
3141     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
3142
3143     /* add new element to the pipeline */
3144     if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
3145     {
3146       debug_log("failed to add autoplug element to bin\n");
3147       goto ERROR;
3148     }
3149
3150     /* get pad from element */
3151     sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
3152     if ( !sinkpad )
3153     {
3154       debug_log("failed to get sinkpad from autoplug element\n");
3155       goto ERROR;
3156     }
3157
3158     /* link it */
3159     if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
3160     {
3161       debug_log("failed to link autoplug element\n");
3162       goto ERROR;
3163     }
3164
3165     gst_object_unref (sinkpad);
3166     sinkpad = NULL;
3167
3168     /* run. setting PLAYING here since streamming source is live source */
3169     MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
3170   }
3171
3172   /* store handle to futher manipulation */
3173   player->pipeline->mainbin[element_id].id = element_id;
3174   player->pipeline->mainbin[element_id].gst = new_element;
3175
3176   MMPLAYER_FLEAVE();
3177
3178   return;
3179
3180 STATE_CHANGE_FAILED:
3181 ERROR:
3182   /* FIXIT : take care if new_element has already added to pipeline */
3183   if ( new_element )
3184     gst_object_unref(GST_OBJECT(new_element));
3185
3186   if ( sinkpad )
3187     gst_object_unref(GST_OBJECT(sinkpad));
3188
3189   if ( caps )
3190     gst_object_unref(GST_OBJECT(caps));
3191
3192   /* FIXIT : how to inform this error to MSL ????? */
3193   /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
3194    * then post an error to application
3195    */
3196 }
3197
3198 static void
3199 __mmplayer_gst_selector_blocked (GstPad* pad, gboolean blocked, gpointer data)
3200 {
3201         debug_log ("pad blocked callback, blocked: %d", blocked);
3202 }
3203
3204 static void
3205 __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data)
3206 {
3207         mm_player_t* player = NULL;
3208         GstElement* pipeline = NULL;
3209         GstElement* selector = NULL;
3210         GstElement* fakesink = NULL;
3211         GstCaps* caps = NULL;
3212         GstStructure* str = NULL;
3213         const gchar* name = NULL;
3214         GstPad* sinkpad = NULL;
3215         GstPad* srcpad = NULL;
3216         gboolean first_track = FALSE;
3217
3218         enum MainElementID elemId = MMPLAYER_M_NUM;
3219
3220         /* check handles */
3221         player = (mm_player_t*)data;
3222
3223         return_if_fail (elem && pad);
3224         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3225
3226         //debug_log ("pad-added signal handling\n");
3227
3228         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3229
3230         /* get mimetype from caps */
3231         caps = gst_pad_get_caps (pad);
3232         if ( !caps )
3233         {
3234                 debug_error ("cannot get caps from pad.\n");
3235                 goto ERROR;
3236         }
3237
3238         str = gst_caps_get_structure (caps, 0);
3239         if ( ! str )
3240         {
3241                 debug_error ("cannot get structure from capse.\n");
3242                 goto ERROR;
3243         }
3244
3245         name = gst_structure_get_name (str);
3246         if ( ! name )
3247         {
3248                 debug_error ("cannot get mimetype from structure.\n");
3249                 goto ERROR;
3250         }
3251
3252         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3253         //debug_log ("detected mimetype : %s\n", name);
3254
3255         if (strstr(name, "video"))
3256         {
3257                 gint stype = 0;
3258                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
3259
3260                 /* don't make video because of not required, and not support multiple track */
3261                 if (stype == MM_DISPLAY_SURFACE_NULL)
3262                 {
3263                         debug_log ("no video sink by null surface or multiple track");
3264                         gchar *caps_str = gst_caps_to_string(caps);
3265                         if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
3266                         {
3267                                 player->set_mode.video_zc = TRUE;
3268                         }
3269                         MMPLAYER_FREEIF( caps_str );
3270
3271                         if (player->v_stream_caps)
3272                         {
3273                                 gst_caps_unref(player->v_stream_caps);
3274                                 player->v_stream_caps = NULL;
3275                         }
3276
3277                         debug_log ("create fakesink instead of videobin");
3278
3279                         /* fake sink */
3280                         fakesink = gst_element_factory_make ("fakesink", NULL);
3281                         if (fakesink == NULL)
3282                         {
3283                                 debug_error ("ERROR : fakesink create error\n");
3284                                 goto ERROR;
3285                         }
3286
3287                         player->video_fakesink = fakesink;
3288
3289                         gst_bin_add (GST_BIN(pipeline), fakesink);
3290
3291                         // link
3292                         sinkpad = gst_element_get_static_pad (fakesink, "sink");
3293
3294                         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3295                         {
3296                                 debug_warning ("failed to link fakesink\n");
3297                                 gst_object_unref (GST_OBJECT(fakesink));
3298                                 goto ERROR;
3299                         }
3300
3301                         if (player->set_mode.media_packet_video_stream)
3302                                 player->video_cb_probe_id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (__mmplayer_video_stream_probe), player);
3303
3304                         g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
3305                         g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
3306                         gst_element_set_state (fakesink, GST_STATE_PAUSED);
3307
3308                         goto DONE;
3309                 }
3310
3311                 debug_log ("video selector \n");
3312                 elemId = MMPLAYER_M_V_INPUT_SELECTOR;
3313         }
3314         else
3315         {
3316                 if (strstr(name, "audio"))
3317                 {
3318                         gint samplerate = 0;
3319                         gint channels = 0;
3320
3321                         debug_log ("audio selector \n");
3322                         elemId = MMPLAYER_M_A_INPUT_SELECTOR;
3323
3324                         gst_structure_get_int (str, "rate", &samplerate);
3325                         gst_structure_get_int (str, "channels", &channels);
3326
3327                         if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
3328                                 /* fake sink */
3329                                 fakesink = gst_element_factory_make ("fakesink", NULL);
3330                                 if (fakesink == NULL)
3331                                 {
3332                                         debug_error ("ERROR : fakesink create error\n");
3333                                         goto ERROR;
3334                                 }
3335
3336                                 gst_bin_add (GST_BIN(pipeline), fakesink);
3337
3338                                 /* link */
3339                                 sinkpad = gst_element_get_static_pad (fakesink, "sink");
3340
3341                                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3342                                 {
3343                                         debug_warning ("failed to link fakesink\n");
3344                                         gst_object_unref (GST_OBJECT(fakesink));
3345                                         goto ERROR;
3346                                 }
3347
3348                                 g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
3349                                 g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
3350                                 gst_element_set_state (fakesink, GST_STATE_PAUSED);
3351
3352                                 goto DONE;
3353                         }
3354                 }
3355                 else if (strstr(name, "text"))
3356                 {
3357                         debug_log ("text selector \n");
3358                         elemId = MMPLAYER_M_T_SUBMUX_INTERNAL;
3359                 }
3360                 else
3361                 {
3362                         debug_error ("wrong elem id \n");
3363                         goto ERROR;
3364                 }
3365         }
3366
3367         selector = player->pipeline->mainbin[elemId].gst;
3368
3369         if (selector == NULL)
3370         {
3371                 if (strstr(name, "audio") || strstr(name, "video")) {
3372                         selector = gst_element_factory_make ("input-selector", NULL);
3373                         debug_log ("Creating input-selector\n");
3374                         if (selector == NULL)
3375                         {
3376                                 debug_error ("ERROR : input-selector create error\n");
3377                                 goto ERROR;
3378                         }
3379                         g_object_set (selector, "sync-streams", TRUE, NULL);
3380                 }
3381                 else
3382                 {
3383                         if (player->textsink_linked)
3384                         {
3385                                 selector = gst_element_factory_make ("input-selector", "text-inselector");
3386                                 debug_log ("Creating input-selector\n");
3387                         }
3388                         else
3389                         {
3390                                 selector = gst_element_factory_make ("submux", "internal-submux");
3391                                 g_object_set (G_OBJECT (selector), "lang-list", player->subtitle_language_list, NULL);
3392                                 debug_log ("Creating submux\n");
3393                         }
3394                         if (selector == NULL)
3395                         {
3396                                 debug_error ("ERROR : input-selector create error\n");
3397                                 goto ERROR;
3398                         }
3399                         debug_log ("Created submux %p\n", selector);
3400                 }
3401                 gst_bin_add (GST_BIN(pipeline), selector);
3402                 gst_element_set_state (selector, GST_STATE_PAUSED);
3403
3404                 player->pipeline->mainbin[elemId].id = elemId;
3405                 player->pipeline->mainbin[elemId].gst = selector;
3406
3407                 first_track = TRUE;
3408                 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK;      // default
3409
3410                 srcpad = gst_element_get_static_pad (selector, "src");
3411
3412                 debug_log ("blocking %" GST_PTR_FORMAT, srcpad);
3413                 gst_pad_set_blocked_async (srcpad, TRUE, __mmplayer_gst_selector_blocked, NULL);
3414         }
3415         else
3416         {
3417                 debug_log ("input-selector is already created.\n");
3418                 selector = player->pipeline->mainbin[elemId].gst;
3419         }
3420
3421         // link
3422         debug_log ("Calling request pad with selector %p \n", selector);
3423         sinkpad = gst_element_get_request_pad (selector, "sink%d");
3424
3425         debug_log ("got pad %s:%s from selector", GST_DEBUG_PAD_NAME (sinkpad));
3426
3427         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3428         {
3429                 debug_warning ("failed to link selector\n");
3430                 gst_object_unref (GST_OBJECT(selector));
3431                 goto ERROR;
3432         }
3433
3434         if (first_track && (strstr(name, "audio") || strstr(name, "video")))
3435         {
3436                 debug_log ("this is first track --> active track \n");
3437                 g_object_set (selector, "active-pad", sinkpad, NULL);
3438         } else {
3439                 debug_log ("subtitle is of internal type \n");
3440                 if(!player->textsink_linked) {
3441                         g_object_set (selector, "is-internal", TRUE, NULL);
3442                 } else {
3443                         debug_log ("this is first track --> active track \n");
3444                         g_object_set (selector, "active-pad", sinkpad, NULL);
3445                 }
3446         }
3447
3448 DONE:
3449 ERROR:
3450
3451         if (caps)
3452         {
3453                 gst_caps_unref (caps);
3454         }
3455
3456         if (sinkpad)
3457         {
3458                 gst_object_unref (GST_OBJECT(sinkpad));
3459                 sinkpad = NULL;
3460         }
3461
3462         if (srcpad)
3463         {
3464                 gst_object_unref (GST_OBJECT(srcpad));
3465                 srcpad = NULL;
3466         }
3467
3468         return;
3469 }
3470
3471 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
3472 {
3473         #define DEFAULT_TRACK 0
3474         GstPad* srcpad = NULL;
3475         MMHandleType attrs = 0;
3476         gint active_index = 0;
3477
3478         // [link] input-selector :: textbin
3479         srcpad = gst_element_get_static_pad (text_selector, "src");
3480         if (!srcpad)
3481         {
3482                 debug_error("failed to get srcpad from selector\n");
3483                 return;
3484         }
3485
3486         debug_log ("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
3487
3488         active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
3489         if ((active_index != DEFAULT_TRACK) &&
3490                 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE))
3491         {
3492                 debug_warning("failed to change text track\n");
3493                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
3494         }
3495
3496         player->no_more_pad = TRUE;
3497         __mmplayer_gst_decode_callback (text_selector, srcpad, player);
3498
3499         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3500         gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3501
3502         debug_log("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3503
3504         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
3505                 player->has_closed_caption = TRUE;
3506
3507         attrs = MMPLAYER_GET_ATTRS(player);
3508         if ( attrs )
3509         {
3510                 mm_attrs_set_int_by_name(attrs, "content_text_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3511                 if (mmf_attrs_commit (attrs))
3512                         debug_error("failed to commit.\n");
3513         }
3514         else
3515         {
3516                 debug_error("cannot get content attribute");
3517         }
3518
3519         if (srcpad)
3520         {
3521                 gst_object_unref ( GST_OBJECT(srcpad) );
3522                 srcpad = NULL;
3523         }
3524 }
3525
3526 int _mmplayer_gst_set_audio_channel(MMHandleType hplayer, MMPlayerAudioChannel ch_idx)
3527 {
3528         int result = MM_ERROR_NONE;
3529
3530         mm_player_t* player = (mm_player_t*)hplayer;
3531         MMPlayerGstElement* mainbin = NULL;
3532         gchar* change_pad_name = NULL;
3533         GstPad* sinkpad = NULL;
3534         GstCaps* caps = NULL;
3535
3536         MMPLAYER_FENTER();
3537
3538         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3539
3540         debug_log ("Change Audio mode to %d\n", ch_idx);
3541         player->use_deinterleave = TRUE;
3542
3543         if ((!player->pipeline) || (!player->pipeline->mainbin))
3544         {
3545                 debug_log ("pre setting : %d\n", ch_idx);
3546
3547                 player->audio_mode.active_pad_index = ch_idx;
3548                 return result;
3549         }
3550
3551         mainbin = player->pipeline->mainbin;
3552
3553         if (mainbin[MMPLAYER_M_A_SELECTOR].gst == NULL)
3554         {
3555                 if (player->max_audio_channels < 2)
3556                 {
3557                         debug_log ("mono channel track only\n");
3558                         return result;
3559                 }
3560
3561                 debug_warning ("selector doesn't exist\n");
3562                 return result;  /* keep playing */
3563         }
3564
3565         debug_log ("total_ch_num : %d\n", player->audio_mode.total_track_num);
3566
3567         if (player->audio_mode.total_track_num < 2)
3568         {
3569                 debug_warning ("there is no another audio path\n");
3570                 return result;  /* keep playing */
3571         }
3572
3573         if ((ch_idx < 0) || (ch_idx >= player->audio_mode.total_track_num))
3574         {
3575                 debug_warning ("Not a proper ch_idx : %d \n", ch_idx);
3576                 return result;  /* keep playing */
3577         }
3578
3579         /*To get the new pad from the selector*/
3580         change_pad_name = g_strdup_printf ("sink%d", ch_idx);
3581         if (change_pad_name == NULL)
3582         {
3583                 debug_warning ("Pad does not exists\n");
3584                 goto ERROR;     /* keep playing */
3585         }
3586
3587         debug_log ("new active pad name: %s\n", change_pad_name);
3588
3589         sinkpad = gst_element_get_static_pad (mainbin[MMPLAYER_M_A_SELECTOR].gst, change_pad_name);
3590         if (sinkpad == NULL)
3591         {
3592                 //result = MM_ERROR_PLAYER_INTERNAL;
3593                 goto ERROR;     /* keep playing */
3594         }
3595
3596         debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3597         g_object_set (mainbin[MMPLAYER_M_A_SELECTOR].gst, "active-pad", sinkpad, NULL);
3598
3599         caps = GST_PAD_CAPS(sinkpad);
3600         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3601
3602         __mmplayer_set_audio_attrs (player, caps);
3603         player->audio_mode.active_pad_index = ch_idx;
3604
3605 ERROR:
3606
3607         if (sinkpad)
3608                 gst_object_unref (sinkpad);
3609
3610         MMPLAYER_FREEIF(change_pad_name);
3611
3612         MMPLAYER_FLEAVE();
3613         return result;
3614 }
3615
3616
3617
3618 static void
3619 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
3620 {
3621         mm_player_t* player = (mm_player_t*)data;
3622         GstElement* selector = NULL;
3623         GstElement* queue = NULL;
3624
3625         GstPad* srcpad = NULL;
3626         GstPad* sinkpad = NULL;
3627         gchar* caps_str= NULL;
3628
3629         MMPLAYER_FENTER();
3630         return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3631
3632         caps_str = gst_caps_to_string(GST_PAD_CAPS(pad));
3633         debug_log ("deinterleave new caps : %s\n", caps_str);
3634         MMPLAYER_FREEIF(caps_str);
3635
3636         if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL)
3637         {
3638                 debug_error ("ERROR : queue create error\n");
3639                 goto ERROR;
3640         }
3641
3642         g_object_set(G_OBJECT(queue),
3643                                 "max-size-buffers", 10,
3644                                 "max-size-bytes", 0,
3645                                 "max-size-time", (guint64)0,
3646                                 NULL);
3647
3648         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3649
3650         if (!selector)
3651         {
3652                 debug_error("there is no audio channel selector.\n");
3653                 goto ERROR;
3654         }
3655
3656         srcpad = gst_element_get_static_pad (queue, "src");
3657         sinkpad = gst_element_get_request_pad (selector, "sink%d");
3658
3659         debug_log ("link (%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
3660
3661         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3662         {
3663                 debug_warning ("failed to link deinterleave - selector\n");
3664                 goto ERROR;
3665         }
3666
3667         gst_element_set_state (queue, GST_STATE_PAUSED);
3668         player->audio_mode.total_track_num++;
3669
3670 ERROR:
3671
3672         if (srcpad)
3673         {
3674                 gst_object_unref ( GST_OBJECT(srcpad) );
3675                 srcpad = NULL;
3676         }
3677
3678         if (sinkpad)
3679         {
3680                 gst_object_unref ( GST_OBJECT(sinkpad) );
3681                 sinkpad = NULL;
3682         }
3683
3684         MMPLAYER_FLEAVE();
3685         return;
3686 }
3687
3688 static void
3689 __mmplayer_gst_deinterleave_no_more_pads (GstElement *elem, gpointer data)
3690 {
3691         mm_player_t* player = NULL;
3692         GstElement* selector = NULL;
3693         GstPad* sinkpad = NULL;
3694         gint active_index = 0;
3695         gchar* change_pad_name = NULL;
3696         GstCaps* caps = NULL;   // no need to unref
3697
3698         MMPLAYER_FENTER();
3699         player = (mm_player_t*) data;
3700
3701         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3702
3703         if (!selector)
3704         {
3705                 debug_error("there is no audio channel selector.\n");
3706                 goto ERROR;
3707         }
3708
3709         active_index = player->audio_mode.active_pad_index;
3710
3711         if (active_index != DEFAULT_AUDIO_CH)
3712         {
3713                 gint audio_ch = DEFAULT_AUDIO_CH;
3714
3715                 /*To get the new pad from the selector*/
3716                 change_pad_name = g_strdup_printf ("sink%d", active_index);
3717                 if (change_pad_name != NULL)
3718                 {
3719                         sinkpad = gst_element_get_static_pad (selector, change_pad_name);
3720                         if (sinkpad != NULL)
3721                         {
3722                                 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3723                                 g_object_set (selector, "active-pad", sinkpad, NULL);
3724
3725                                 audio_ch = active_index;
3726
3727                                 caps = GST_PAD_CAPS(sinkpad);
3728                                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3729
3730                                 __mmplayer_set_audio_attrs (player, caps);
3731                         }
3732                 }
3733
3734                 player->audio_mode.active_pad_index = audio_ch;
3735                 debug_log("audio LR info (0:stereo) = %d\n", player->audio_mode.active_pad_index);
3736         }
3737
3738 ERROR:
3739
3740         if (sinkpad)
3741                 gst_object_unref (sinkpad);
3742
3743         MMPLAYER_FLEAVE();
3744         return;
3745 }
3746
3747 static void
3748 __mmplayer_gst_build_deinterleave_path (GstElement *elem, GstPad *pad, gpointer data)
3749 {
3750         mm_player_t* player = NULL;
3751         MMPlayerGstElement *mainbin = NULL;
3752
3753         GstElement* tee = NULL;
3754         GstElement* stereo_queue = NULL;
3755         GstElement* mono_queue = NULL;
3756         GstElement* conv = NULL;
3757         GstElement* filter = NULL;
3758         GstElement* deinterleave = NULL;
3759         GstElement* selector = NULL;
3760
3761         GstPad* srcpad = NULL;
3762         GstPad* selector_srcpad = NULL;
3763         GstPad* sinkpad = NULL;
3764         GstCaps* caps = NULL;
3765
3766         MMPLAYER_FENTER();
3767
3768         /* check handles */
3769         player = (mm_player_t*) data;
3770
3771         return_if_fail( elem && pad );
3772         return_if_fail( player && player->pipeline && player->pipeline->mainbin );
3773
3774         mainbin = player->pipeline->mainbin;
3775
3776         /* tee */
3777         if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL)
3778         {
3779                 debug_error ("ERROR : tee create error\n");
3780                 goto ERROR;
3781         }
3782
3783         mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
3784         mainbin[MMPLAYER_M_A_TEE].gst = tee;
3785
3786         gst_element_set_state (tee, GST_STATE_PAUSED);
3787
3788         /* queue */
3789         srcpad = gst_element_get_request_pad (tee, "src%d");
3790         if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3791         {
3792                 debug_error ("ERROR : stereo queue create error\n");
3793                 goto ERROR;
3794         }
3795
3796         g_object_set(G_OBJECT(stereo_queue),
3797                                 "max-size-buffers", 10,
3798                                 "max-size-bytes", 0,
3799                                 "max-size-time", (guint64)0,
3800                                 NULL);
3801
3802         player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
3803         player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
3804
3805         if (srcpad)
3806         {
3807                 gst_object_unref (GST_OBJECT(srcpad));
3808                 srcpad = NULL;
3809         }
3810
3811         srcpad = gst_element_get_request_pad (tee, "src%d");
3812
3813         if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3814         {
3815                 debug_error ("ERROR : mono queue create error\n");
3816                 goto ERROR;
3817         }
3818
3819         g_object_set(G_OBJECT(mono_queue),
3820                                 "max-size-buffers", 10,
3821                                 "max-size-bytes", 0,
3822                                 "max-size-time", (guint64)0,
3823                                 NULL);
3824
3825         player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3826         player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3827
3828         gst_element_set_state (stereo_queue, GST_STATE_PAUSED);
3829         gst_element_set_state (mono_queue, GST_STATE_PAUSED);
3830
3831         /* audioconvert */
3832         srcpad = gst_element_get_static_pad (mono_queue, "src");
3833         if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL)
3834         {
3835                 debug_error ("ERROR : audioconvert create error\n");
3836                 goto ERROR;
3837         }
3838
3839         player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3840         player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3841
3842         /* caps filter */
3843         if (srcpad)
3844         {
3845                 gst_object_unref (GST_OBJECT(srcpad));
3846                 srcpad = NULL;
3847         }
3848         srcpad = gst_element_get_static_pad (conv, "src");
3849
3850         if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL)
3851         {
3852                 debug_error ("ERROR : capsfilter create error\n");
3853                 goto ERROR;
3854         }
3855
3856         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3857         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3858
3859         caps = gst_caps_from_string( "audio/x-raw-int, "
3860                                 "width = (int) 16, "
3861                                 "depth = (int) 16, "
3862                                 "channels = (int) 2");
3863
3864         g_object_set (GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL );
3865         gst_caps_unref( caps );
3866
3867         gst_element_set_state (conv, GST_STATE_PAUSED);
3868         gst_element_set_state (filter, GST_STATE_PAUSED);
3869
3870         /* deinterleave */
3871         if (srcpad)
3872         {
3873                 gst_object_unref (GST_OBJECT(srcpad));
3874                 srcpad = NULL;
3875         }
3876         srcpad = gst_element_get_static_pad (filter, "src");
3877
3878         if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL)
3879         {
3880                 debug_error ("ERROR : deinterleave create error\n");
3881                 goto ERROR;
3882         }
3883
3884         g_object_set (deinterleave, "keep-positions", TRUE, NULL);
3885
3886         MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3887                                                         G_CALLBACK (__mmplayer_gst_deinterleave_pad_added), player);
3888
3889         MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3890                                                         G_CALLBACK (__mmplayer_gst_deinterleave_no_more_pads), player);
3891
3892         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3893         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3894
3895         /* selector */
3896         selector = gst_element_factory_make ("input-selector", "audio-channel-selector");
3897         if (selector == NULL)
3898         {
3899                 debug_error ("ERROR : audio-selector create error\n");
3900                 goto ERROR;
3901         }
3902
3903         g_object_set (selector, "sync-streams", TRUE, NULL);
3904         gst_bin_add (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3905
3906         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3907         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3908
3909         selector_srcpad = gst_element_get_static_pad (selector, "src");
3910
3911         debug_log ("blocking %" GST_PTR_FORMAT, selector_srcpad);
3912         gst_pad_set_blocked_async (selector_srcpad, TRUE, __mmplayer_gst_selector_blocked, NULL);
3913
3914         if (srcpad)
3915         {
3916                 gst_object_unref (GST_OBJECT(srcpad));
3917                 srcpad = NULL;
3918         }
3919
3920         srcpad = gst_element_get_static_pad(stereo_queue, "src");
3921         sinkpad = gst_element_get_request_pad (selector, "sink%d");
3922
3923         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3924         {
3925                 debug_warning ("failed to link queue_stereo - selector\n");
3926                 goto ERROR;
3927         }
3928
3929         player->audio_mode.total_track_num++;
3930
3931         g_object_set (selector, "active-pad", sinkpad, NULL);
3932         gst_element_set_state (deinterleave, GST_STATE_PAUSED);
3933         gst_element_set_state (selector, GST_STATE_PAUSED);
3934
3935         __mmplayer_gst_decode_callback (selector, selector_srcpad, player);
3936
3937         debug_log ("unblocking %" GST_PTR_FORMAT, selector_srcpad);
3938         gst_pad_set_blocked_async (selector_srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3939
3940 ERROR:
3941         if (sinkpad)
3942         {
3943                 gst_object_unref (GST_OBJECT(sinkpad));
3944                 sinkpad = NULL;
3945         }
3946
3947         if (srcpad)
3948         {
3949                 gst_object_unref (GST_OBJECT(srcpad));
3950                 srcpad = NULL;
3951         }
3952
3953         if (selector_srcpad)
3954         {
3955                 gst_object_unref (GST_OBJECT(selector_srcpad));
3956                 selector_srcpad = NULL;
3957         }
3958
3959         MMPLAYER_FLEAVE();
3960         return;
3961 }
3962
3963 static void
3964 __mmplayer_gst_decode_no_more_pads (GstElement *elem, gpointer data)
3965 {
3966         mm_player_t* player = NULL;
3967         GstPad* srcpad = NULL;
3968         GstElement* video_selector = NULL;
3969         GstElement* audio_selector = NULL;
3970         GstElement* text_selector = NULL;
3971         MMHandleType attrs = 0;
3972         gint active_index = 0;
3973         GstFormat fmt  = GST_FORMAT_BYTES;
3974         gint64 dur_bytes = 0L;
3975
3976         player = (mm_player_t*) data;
3977
3978         debug_log("no-more-pad signal handling\n");
3979
3980         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3981                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
3982         {
3983                 debug_warning("no need to go more");
3984
3985                 if (player->pp_rebuilding)
3986                 {
3987                         player->pp_rebuilding = FALSE;
3988                         MMPLAYER_PLAYBACK_UNLOCK(player);
3989                 }
3990
3991                 return;
3992         }
3993
3994         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3995                 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3996                 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3997                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
3998         {
3999                 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
4000
4001                 if (NULL == player->streamer)
4002                 {
4003                         debug_warning("invalid state for buffering");
4004                         goto ERROR;
4005                 }
4006
4007                 gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
4008                 guint buffer_bytes = init_buffering_time * ESTIMATED_BUFFER_UNIT;
4009
4010                 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
4011                 debug_log("[Decodebin2] set use-buffering on Q2 (pre buffer time: %d sec, buffer size : %d)\n", (gint)init_buffering_time, buffer_bytes);
4012
4013                 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
4014
4015                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
4016                         debug_error("fail to get duration.\n");
4017
4018                 // enable use-buffering on queue2 instead of multiqueue (ex)audio only streaming
4019                 // use file information was already set on Q2 when it was created.
4020                 __mm_player_streaming_set_queue2(player->streamer,
4021                                                 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
4022                                                 TRUE,                                                           // use_buffering
4023                                                 buffer_bytes,
4024                                                 init_buffering_time,
4025                                                 1.0,                                                            // low percent
4026                                                 player->ini.http_buffering_limit,       // high percent
4027                                                 FALSE,
4028                                                 NULL,
4029                                                 ((dur_bytes>0)?((guint64)dur_bytes):0));
4030         }
4031
4032         video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
4033         audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
4034         text_selector = player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_INTERNAL].gst;
4035
4036         if (video_selector)
4037         {
4038                 // the first track can be played only. not support track changing yet.
4039                 // [link] input-selector :: videobin
4040                 srcpad = gst_element_get_static_pad (video_selector, "src");
4041                 if (!srcpad)
4042                 {
4043                         debug_error("failed to get srcpad from video selector\n");
4044                         goto ERROR;
4045                 }
4046
4047                 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
4048                 if ((!text_selector) && (!audio_selector))
4049                         player->no_more_pad = TRUE;
4050
4051                 __mmplayer_gst_decode_callback (video_selector, srcpad, player);
4052
4053                 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
4054                 gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
4055
4056                 debug_log("Total video tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].total_track_num);
4057
4058                 gst_object_unref ( GST_OBJECT(srcpad) );
4059                 srcpad = NULL;
4060         }
4061         else
4062         {
4063                 if ((player->pipeline->videobin) && (player->pipeline->videobin[MMPLAYER_V_BIN].gst))
4064                 {
4065                         debug_log ("There is no video track : remove videobin");
4066
4067                         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN );
4068                         __mmplayer_del_sink ( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
4069
4070                         MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->videobin, MMPLAYER_V_BIN );
4071                         MMPLAYER_FREEIF ( player->pipeline->videobin )
4072                 }
4073         }
4074
4075         if (audio_selector)
4076         {
4077                 #define DEFAULT_TRACK 0
4078                 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
4079                 if ((active_index != DEFAULT_TRACK) &&
4080                         (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE))
4081                 {
4082                         debug_warning("failed to change audio track\n");
4083                         player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
4084                 }
4085
4086                 // [link] input-selector :: audiobin
4087                 srcpad = gst_element_get_static_pad (audio_selector, "src");
4088                 if (!srcpad)
4089                 {
4090                         debug_error("failed to get srcpad from selector\n");
4091                         goto ERROR;
4092                 }
4093
4094                 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
4095                 if (!text_selector)
4096                         player->no_more_pad = TRUE;
4097
4098                 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2))
4099                 {
4100                         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
4101                         gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
4102
4103                         __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
4104                 }
4105                 else
4106                 {
4107                         __mmplayer_gst_decode_callback (audio_selector, srcpad, player);
4108
4109                         debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
4110                         gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
4111                 }
4112
4113                 debug_log("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
4114
4115                 attrs = MMPLAYER_GET_ATTRS(player);
4116                 if ( attrs )
4117                 {
4118                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
4119                         if (mmf_attrs_commit (attrs))
4120                                 debug_error("failed to commit.\n");
4121                 }
4122                 else
4123                 {
4124                         debug_error("cannot get content attribute");
4125                 }
4126         }
4127         else
4128         {
4129                 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst))
4130                 {
4131                         debug_log ("There is no audio track : remove audiobin");
4132
4133                         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN );
4134                         __mmplayer_del_sink ( player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst );
4135
4136                         MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->audiobin, MMPLAYER_A_BIN );
4137                         MMPLAYER_FREEIF ( player->pipeline->audiobin )
4138                 }
4139         }
4140
4141         if (text_selector)
4142         {
4143                 __mmplayer_handle_text_decode_path(player, text_selector);
4144         }
4145
4146         MMPLAYER_FLEAVE();
4147
4148 ERROR:
4149         if (srcpad)
4150         {
4151                 gst_object_unref ( GST_OBJECT(srcpad) );
4152                 srcpad = NULL;
4153         }
4154
4155         if (player->pp_rebuilding)
4156         {
4157                 player->pp_rebuilding = FALSE;
4158                 MMPLAYER_PLAYBACK_UNLOCK(player);
4159         }
4160 }
4161
4162 static void
4163 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // @
4164 {
4165         mm_player_t* player = NULL;
4166         MMHandleType attrs = 0;
4167         GstElement* pipeline = NULL;
4168         GstCaps* caps = NULL;
4169         gchar* caps_str = NULL;
4170         GstStructure* str = NULL;
4171         const gchar* name = NULL;
4172         GstPad* sinkpad = NULL;
4173         GstElement* sinkbin = NULL;
4174         gboolean reusing = FALSE;
4175         GstElement *text_selector = NULL;
4176
4177         /* check handles */
4178         player = (mm_player_t*) data;
4179
4180         return_if_fail( elem && pad );
4181         return_if_fail(player && player->pipeline && player->pipeline->mainbin);
4182
4183         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
4184
4185         attrs = MMPLAYER_GET_ATTRS(player);
4186         if ( !attrs )
4187         {
4188                 debug_error("cannot get content attribute\n");
4189                 goto ERROR;
4190         }
4191
4192         /* get mimetype from caps */
4193         caps = gst_pad_get_caps( pad );
4194         if ( !caps )
4195         {
4196                 debug_error("cannot get caps from pad.\n");
4197                 goto ERROR;
4198         }
4199         caps_str = gst_caps_to_string(caps);
4200
4201         str = gst_caps_get_structure( caps, 0 );
4202         if ( ! str )
4203         {
4204                 debug_error("cannot get structure from capse.\n");
4205                 goto ERROR;
4206         }
4207
4208         name = gst_structure_get_name(str);
4209         if ( ! name )
4210         {
4211                 debug_error("cannot get mimetype from structure.\n");
4212                 goto ERROR;
4213         }
4214
4215         //debug_log("detected mimetype : %s\n", name);
4216
4217         if (strstr(name, "audio"))
4218         {
4219                 if (player->pipeline->audiobin == NULL)
4220                 {
4221                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player))
4222                         {
4223                                 debug_error("failed to create audiobin. continuing without audio\n");
4224                                 goto ERROR;
4225                         }
4226
4227                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
4228                         debug_log("creating audiosink bin success\n");
4229                 }
4230                 else
4231                 {
4232                         reusing = TRUE;
4233                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
4234                         debug_log("reusing audiobin\n");
4235                         _mmplayer_update_content_attrs( player, ATTR_AUDIO);
4236                 }
4237
4238                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
4239                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
4240
4241                 player->audiosink_linked  = 1;
4242
4243                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
4244                 if ( !sinkpad )
4245                 {
4246                         debug_error("failed to get pad from sinkbin\n");
4247                         goto ERROR;
4248                 }
4249         }
4250         else if (strstr(name, "video"))
4251         {
4252                 if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
4253                 {
4254                         player->set_mode.video_zc = TRUE;
4255                 }
4256
4257                 if (player->pipeline->videobin == NULL)
4258                 {
4259                         /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
4260                         /* get video surface type */
4261                         int surface_type = 0;
4262                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
4263
4264                         if (surface_type == MM_DISPLAY_SURFACE_NULL)
4265                         {
4266                                 debug_log("not make videobin because it dose not want\n");
4267                                 goto ERROR;
4268                         }
4269
4270                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type) )
4271                         {
4272                                 debug_error("failed to create videobin. continuing without video\n");
4273                                 goto ERROR;
4274                         }
4275
4276                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
4277                         debug_log("creating videosink bin success\n");
4278                 }
4279                 else
4280                 {
4281                         reusing = TRUE;
4282                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
4283                         debug_log("re-using videobin\n");
4284                         _mmplayer_update_content_attrs( player, ATTR_VIDEO);
4285                 }
4286
4287                 /* FIXIT : track number shouldn't be hardcoded */
4288                 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 1);
4289                 player->videosink_linked  = 1;
4290
4291                 /* NOTE : intermediate code before doing H/W subtitle compositon */
4292                 if ( player->use_textoverlay && player->play_subtitle )
4293                 {
4294                         debug_log("using textoverlay for external subtitle");
4295                         /* check text bin has created well */
4296                         if ( player->pipeline && player->pipeline->textbin )
4297                         {
4298                                 /* get sinkpad from textoverlay */
4299                                 sinkpad = gst_element_get_static_pad(
4300                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
4301                                         "video_sink" );
4302                                 if ( ! sinkpad )
4303                                 {
4304                                         debug_error("failed to get sink pad from textoverlay");
4305                                         goto ERROR;
4306                                 }
4307
4308                                 /* link new pad with textoverlay first */
4309                                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
4310                                 {
4311                                         debug_error("failed to get pad from sinkbin\n");
4312                                         goto ERROR;
4313                                 }
4314
4315                                 gst_object_unref(sinkpad);
4316                                 sinkpad = NULL;
4317
4318                                 /* alright, override pad to textbin.src for futher link */
4319                                 pad = gst_element_get_static_pad(
4320                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
4321                                         "src" );
4322                                 if ( ! pad )
4323                                 {
4324                                         debug_error("failed to get sink pad from textoverlay");
4325                                         goto ERROR;
4326                                 }
4327                         }
4328                         else
4329                         {
4330                                 debug_error("should not reach here.");
4331                                 goto ERROR;
4332                         }
4333                 }
4334
4335                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
4336                 if ( !sinkpad )
4337                 {
4338                         debug_error("failed to get pad from sinkbin\n");
4339                         goto ERROR;
4340                 }
4341         }
4342         else if (strstr(name, "text"))
4343         {
4344                 if (player->pipeline->textbin == NULL)
4345                 {
4346                         MMPlayerGstElement* mainbin = NULL;
4347
4348                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
4349                         {
4350                                 debug_error("failed to create textbin. continuing without text\n");
4351                                 goto ERROR;
4352                         }
4353
4354                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
4355                         debug_log("creating textink bin success\n");
4356
4357                         /* FIXIT : track number shouldn't be hardcoded */
4358                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
4359
4360                         player->textsink_linked  = 1;
4361                         debug_msg("player->textsink_linked set to 1\n");
4362
4363                         sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "text_sink" );
4364                         if ( !sinkpad )
4365                         {
4366                                 debug_error("failed to get pad from sinkbin\n");
4367                                 goto ERROR;
4368                         }
4369
4370                         mainbin = player->pipeline->mainbin;
4371
4372                         if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst)
4373                         {
4374                           /* input selector */
4375                           text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
4376                           if ( !text_selector )
4377                           {
4378                             debug_error ( "failed to create subtitle input selector element\n" );
4379                             goto ERROR;
4380                           }
4381                           g_object_set (text_selector, "sync-streams", TRUE, NULL);
4382
4383                           mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
4384                           mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
4385
4386                           /* warm up */
4387                           if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_READY))
4388                           {
4389                             debug_error("failed to set state(READY) to sinkbin\n");
4390                             goto ERROR;
4391                           }
4392
4393                           if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector))
4394                           {
4395                             debug_warning("failed to add subtitle input selector\n");
4396                             goto ERROR;
4397                           }
4398
4399                           debug_log ("created element input-selector");
4400
4401                         }
4402                         else
4403                         {
4404                           debug_log ("already having subtitle input selector");
4405                           text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
4406                         }
4407                 }
4408                 else
4409                 {
4410                         if (!player->textsink_linked)
4411                         {
4412                                 debug_log("re-using textbin\n");
4413
4414                                 reusing = TRUE;
4415                                 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
4416
4417                                 player->textsink_linked  = 1;
4418                                 debug_msg("player->textsink_linked set to 1\n");
4419                         }
4420                         else
4421                         {
4422                                 debug_log("ignoring internal subtutle since external subtitle is available");
4423                         }
4424                 }
4425         }
4426         else
4427         {
4428                 debug_warning("unknown type of elementary stream! ignoring it...\n");
4429                 goto ERROR;
4430         }
4431
4432         if ( sinkbin )
4433         {
4434                 if(!reusing)
4435                 {
4436                         /* warm up */
4437                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_READY ) )
4438                         {
4439                                 debug_error("failed to set state(READY) to sinkbin\n");
4440                                 goto ERROR;
4441                         }
4442
4443                         /* Added for multi audio support to avoid adding audio bin again*/
4444                         /* add */
4445                         if ( FALSE == gst_bin_add( GST_BIN(pipeline), sinkbin ) )
4446                         {
4447                                 debug_error("failed to add sinkbin to pipeline\n");
4448                                 goto ERROR;
4449                         }
4450                 }
4451
4452                 if (text_selector)
4453                 {
4454                   GstPad *srcpad = NULL;
4455
4456                   srcpad =  gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst,"src");
4457                   if (!srcpad)
4458                   {
4459                     debug_error ("failed to get source pad");
4460                     goto ERROR;
4461                   }
4462
4463                   /* link input selector & textbin */
4464                   if (gst_pad_link(srcpad,sinkpad)!= 0)
4465                   {
4466                     debug_warning("failed to link input selector and textbin ghost pad\n");
4467                     goto ERROR;
4468                   }
4469
4470                   sinkpad = gst_element_get_request_pad (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "sink0");
4471                   if (sinkpad == NULL)
4472                   {
4473                     debug_error ("failed to get request pad from input selector");;
4474                     goto ERROR;
4475                   }
4476                 }
4477
4478                 /* link */
4479                 if (GST_PAD_LINK_OK != GST_PAD_LINK (pad, sinkpad))
4480                 {
4481                         debug_error("failed to get pad from sinkbin\n");
4482                         goto ERROR;
4483                 }
4484
4485                 if (!reusing)
4486                 {
4487                         /* run */
4488                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (sinkbin, GST_STATE_PAUSED))
4489                         {
4490                                 debug_error("failed to set state(PLAYING) to sinkbin\n");
4491                                 goto ERROR;
4492                         }
4493
4494                         if (text_selector)
4495                         {
4496                           if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_PAUSED))
4497                           {
4498                             debug_error("failed to set state(READY) to sinkbin\n");
4499                             goto ERROR;
4500                           }
4501                         }
4502                 }
4503
4504                 gst_object_unref (sinkpad);
4505                 sinkpad = NULL;
4506         }
4507
4508         debug_log ("linking sink bin success\n");
4509
4510         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
4511          * streaming task. if the task blocked, then buffer will not flow to the next element
4512          * ( autoplugging element ). so this is special hack for streaming. please try to remove it
4513          */
4514         /* dec stream count. we can remove fakesink if it's zero */
4515         if (player->num_dynamic_pad)
4516                 player->num_dynamic_pad--;
4517
4518         debug_log ("no more pads: %d stream count dec : %d (num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
4519
4520         if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
4521         {
4522                 __mmplayer_pipeline_complete (NULL, player);
4523         }
4524
4525         /* FIXIT : please leave a note why this code is needed */
4526         if(MMPLAYER_IS_WFD_STREAMING( player ))
4527         {
4528                 player->no_more_pad = TRUE;
4529         }
4530
4531 ERROR:
4532
4533         MMPLAYER_FREEIF(caps_str);
4534
4535         if ( caps )
4536                 gst_caps_unref( caps );
4537
4538         if ( sinkpad )
4539                 gst_object_unref(GST_OBJECT(sinkpad));
4540
4541         /* flusing out new attributes */
4542         if (  mmf_attrs_commit ( attrs ) )
4543         {
4544                 debug_error("failed to comit attributes\n");
4545         }
4546
4547         return;
4548 }
4549
4550 static gboolean
4551 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
4552 {
4553         int pro_value = 0; // in the case of expection, default will be returned.
4554         int dest_angle = rotation_angle;
4555         int rotation_type = -1;
4556         #define ROTATION_USING_SINK 0
4557         #define ROTATION_USING_CUSTOM 1
4558         #define ROTATION_USING_FLIP     2
4559
4560         return_val_if_fail(player, FALSE);
4561         return_val_if_fail(value, FALSE);
4562         return_val_if_fail(rotation_angle >= 0, FALSE);
4563
4564         if (rotation_angle >= 360)
4565         {
4566                 dest_angle = rotation_angle - 360;
4567         }
4568
4569         /* chech if supported or not */
4570         if ( dest_angle % 90 )
4571         {
4572                 debug_log("not supported rotation angle = %d", rotation_angle);
4573                 return FALSE;
4574         }
4575
4576         /*
4577           * xvimagesink only     (A)
4578           * custom_convert - no xv (e.g. memsink, evasimagesink  (B)
4579           * videoflip - avsysmemsink (C)
4580           */
4581         if (player->set_mode.video_zc)
4582         {
4583                 if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
4584                 {
4585                         rotation_type = ROTATION_USING_CUSTOM;
4586                 }
4587                 else // A
4588                 {
4589                         rotation_type = ROTATION_USING_SINK;
4590                 }
4591         }
4592         else
4593         {
4594                 int surface_type = 0;
4595                 rotation_type = ROTATION_USING_FLIP;
4596
4597                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
4598                 debug_log("check display surface type attribute: %d", surface_type);
4599
4600                 if ((surface_type == MM_DISPLAY_SURFACE_X) ||
4601                         (surface_type == MM_DISPLAY_SURFACE_EVAS && !strcmp(player->ini.videosink_element_evas, "evaspixmapsink")))
4602                 {
4603                         rotation_type = ROTATION_USING_SINK;
4604                 }
4605                 else
4606                 {
4607                         rotation_type = ROTATION_USING_FLIP; //C
4608                 }
4609
4610                 debug_log("using %d type for rotation", rotation_type);
4611         }
4612
4613         /* get property value for setting */
4614         switch(rotation_type)
4615         {
4616                 case ROTATION_USING_SINK: // xvimagesink, pixmap
4617                         {
4618                                 switch (dest_angle)
4619                                 {
4620                                         case 0:
4621                                                 break;
4622                                         case 90:
4623                                                 pro_value = 3; // clockwise 90
4624                                                 break;
4625                                         case 180:
4626                                                 pro_value = 2;
4627                                                 break;
4628                                         case 270:
4629                                                 pro_value = 1; // counter-clockwise 90
4630                                                 break;
4631                                 }
4632                         }
4633                         break;
4634                 case ROTATION_USING_CUSTOM:
4635                         {
4636                                 gchar *ename = NULL;
4637                                 ename = GST_PLUGIN_FEATURE_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
4638
4639                                 if (g_strrstr(ename, "fimcconvert"))
4640                                 {
4641                                         switch (dest_angle)
4642                                         {
4643                                                 case 0:
4644                                                         break;
4645                                                 case 90:
4646                                                         pro_value = 90; // clockwise 90
4647                                                         break;
4648                                                 case 180:
4649                                                         pro_value = 180;
4650                                                         break;
4651                                                 case 270:
4652                                                         pro_value = 270; // counter-clockwise 90
4653                                                         break;
4654                                         }
4655                                 }
4656                         }
4657                         break;
4658                 case ROTATION_USING_FLIP: // videoflip
4659                         {
4660                                         switch (dest_angle)
4661                                         {
4662
4663                                                 case 0:
4664                                                         break;
4665                                                 case 90:
4666                                                         pro_value = 1; // clockwise 90
4667                                                         break;
4668                                                 case 180:
4669                                                         pro_value = 2;
4670                                                         break;
4671                                                 case 270:
4672                                                         pro_value = 3; // counter-clockwise 90
4673                                                         break;
4674                                         }
4675                         }
4676                         break;
4677         }
4678
4679         debug_log("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
4680
4681         *value = pro_value;
4682
4683         return TRUE;
4684 }
4685
4686 int
4687 _mmplayer_update_video_param(mm_player_t* player) // @
4688 {
4689         MMHandleType attrs = 0;
4690         int surface_type = 0;
4691         int org_angle = 0; // current supported angle values are 0, 90, 180, 270
4692         int user_angle = 0;
4693         int user_angle_type= 0;
4694         int rotation_value = 0;
4695
4696         MMPLAYER_FENTER();
4697
4698         /* check video sinkbin is created */
4699         return_val_if_fail ( player &&
4700                 player->pipeline &&
4701                 player->pipeline->videobin &&
4702                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
4703                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4704                 MM_ERROR_PLAYER_NOT_INITIALIZED );
4705
4706         attrs = MMPLAYER_GET_ATTRS(player);
4707         if ( !attrs )
4708         {
4709                 debug_error("cannot get content attribute");
4710                 return MM_ERROR_PLAYER_INTERNAL;
4711         }
4712
4713         /* update user roation */
4714         mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
4715
4716         /* get angle with user type */
4717         switch(user_angle_type)
4718         {
4719                 case MM_DISPLAY_ROTATION_NONE:
4720                         user_angle = 0;
4721                         break;
4722                 case MM_DISPLAY_ROTATION_90: // counter-clockwise 90
4723                         user_angle = 270;
4724                         break;
4725                 case MM_DISPLAY_ROTATION_180:
4726                         user_angle = 180;
4727                         break;
4728                 case MM_DISPLAY_ROTATION_270: // clockwise 90
4729                         user_angle = 90;
4730                         break;
4731         }
4732
4733         /* get original orientation */
4734         if (player->v_stream_caps)
4735         {
4736                 GstStructure *str = NULL;
4737
4738                 str = gst_caps_get_structure (player->v_stream_caps, 0);
4739                 if ( !gst_structure_get_int (str, "orientation", &org_angle))
4740                 {
4741                         debug_log ("missing 'orientation' field in video caps");
4742                 }
4743         }
4744
4745         debug_log("check user angle: %d, orientation: %d", user_angle, org_angle);
4746
4747         /* check video stream callback is used */
4748         if(!player->set_mode.media_packet_video_stream && player->use_video_stream )
4749         {
4750                 if (player->set_mode.video_zc)
4751                 {
4752                         gchar *ename = NULL;
4753                         int width = 0;
4754                         int height = 0;
4755
4756                         mm_attrs_get_int_by_name(attrs, "display_width", &width);
4757                         mm_attrs_get_int_by_name(attrs, "display_height", &height);
4758
4759                         /* resize video frame with requested values for fimcconvert */
4760                         ename = GST_PLUGIN_FEATURE_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
4761
4762                         if (ename && g_strrstr(ename, "fimcconvert"))
4763                         {
4764                                 if (width)
4765                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
4766
4767                                 if (height)
4768                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
4769
4770                                 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
4771                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
4772
4773                                 /* get rotation value to set */
4774                                 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4775
4776                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "rotate", rotation_value, NULL);
4777
4778                                 debug_log("updating fimcconvert - r[%d], w[%d], h[%d]", rotation_value, width, height);
4779                         }
4780                 }
4781                 else
4782                 {
4783                         debug_log("using video stream callback with memsink. player handle : [%p]", player);
4784
4785                         /* get rotation value to set */
4786                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4787
4788                         g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
4789                 }
4790
4791                 return MM_ERROR_NONE;
4792         }
4793
4794         /* update display surface */
4795         mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
4796         debug_log("check display surface type attribute: %d", surface_type);
4797
4798         /* configuring display */
4799         switch ( surface_type )
4800         {
4801                 case MM_DISPLAY_SURFACE_X:
4802                 {
4803                         /* ximagesink or xvimagesink */
4804                         void *xid = NULL;
4805                         double zoom = 0;
4806                         int display_method = 0;
4807                         int roi_x = 0;
4808                         int roi_y = 0;
4809                         int roi_w = 0;
4810                         int roi_h = 0;
4811                         int src_crop_x = 0;
4812                         int src_crop_y = 0;
4813                         int src_crop_w = 0;
4814                         int src_crop_h = 0;
4815                         int force_aspect_ratio = 0;
4816                         gboolean visible = TRUE;
4817
4818                         /* common case if using x surface */
4819                         mm_attrs_get_data_by_name(attrs, "display_overlay", &xid);
4820                         if ( xid )
4821                         {
4822                                 int xwin_id = 0;
4823                                 xwin_id = *(int*)xid;
4824                                 debug_log("set video param : xid %d", *(int*)xid);
4825                                 if (xwin_id)
4826                                 {
4827                                         gst_x_overlay_set_xwindow_id( GST_X_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)xid );
4828                                 }
4829                         }
4830                         else
4831                         {
4832                                 /* FIXIT : is it error case? */
4833                                 debug_warning("still we don't have xid on player attribute. create it's own surface.");
4834                         }
4835
4836                         /* if xvimagesink */
4837                         if (!strcmp(player->ini.videosink_element_x,"xvimagesink"))
4838                         {
4839                                 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
4840                                 mm_attrs_get_double_by_name(attrs, "display_zoom", &zoom);
4841                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4842                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_x", &src_crop_x);
4843                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_y", &src_crop_y);
4844                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_width", &src_crop_w);
4845                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_height", &src_crop_h);
4846                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
4847                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
4848                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
4849                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
4850                                 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4851                                 #define DEFAULT_DISPLAY_MODE    2       // TV only, PRI_VIDEO_OFF_AND_SEC_VIDEO_FULL_SCREEN
4852
4853                                 /* setting for cropping media source */
4854                                 if (src_crop_w && src_crop_h)
4855                                 {
4856                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4857                                                 "src-crop-x", src_crop_x,
4858                                                 "src-crop-y", src_crop_y,
4859                                                 "src-crop-w", src_crop_w,
4860                                                 "src-crop-h", src_crop_h,
4861                                                 NULL );
4862                                 }
4863
4864                                 /* setting for ROI mode */
4865                                 if (display_method == 5)        // 5 for ROI mode
4866                                 {
4867                                         int roi_mode = 0;
4868                                         mm_attrs_get_int_by_name(attrs, "display_roi_mode", &roi_mode);
4869                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4870                                                 "dst-roi-mode", roi_mode,
4871                                                 "dst-roi-x", roi_x,
4872                                                 "dst-roi-y", roi_y,
4873                                                 "dst-roi-w", roi_w,
4874                                                 "dst-roi-h", roi_h,
4875                                                 NULL );
4876                                         /* get rotation value to set,
4877                                            do not use org_angle because ROI mode in xvimagesink needs both a rotation value and an orientation value */
4878                                         __mmplayer_get_property_value_for_rotation(player, user_angle, &rotation_value);
4879                                 }
4880                                 else
4881                                 {
4882                                         /* get rotation value to set */
4883                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4884                                 }
4885
4886                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4887                                         "force-aspect-ratio", force_aspect_ratio,
4888                                         "zoom", (float)zoom,
4889                                         "orientation", org_angle/90, // setting for orientation of media, it is used for ROI/ZOOM feature in xvimagesink
4890                                         "rotate", rotation_value,
4891                                         "handle-events", TRUE,
4892                                         "display-geometry-method", display_method,
4893                                         "draw-borders", FALSE,
4894                                         "visible", visible,
4895                                         "display-mode", DEFAULT_DISPLAY_MODE,
4896                                         NULL );
4897
4898                                 debug_log("set video param : zoom %lf, rotate %d, method %d visible %d", zoom, rotation_value, display_method, visible);
4899                                 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 );
4900                                 debug_log("set video param : force aspect ratio %d, display mode %d", force_aspect_ratio, DEFAULT_DISPLAY_MODE);
4901                         }
4902                 }
4903                 break;
4904                 case MM_DISPLAY_SURFACE_EVAS:
4905                 {
4906                         void *object = NULL;
4907                         int scaling = 0;
4908                         gboolean visible = TRUE;
4909                         int display_method = 0;
4910
4911                         /* common case if using evas surface */
4912                         mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
4913                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4914                         mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
4915                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4916
4917                         /* if evasimagesink */
4918                         if (!strcmp(player->ini.videosink_element_evas,"evasimagesink"))
4919                         {
4920                                 if (object)
4921                                 {
4922                                         /* if it is evasimagesink, we are not supporting rotation */
4923                                         if (user_angle_type!=MM_DISPLAY_ROTATION_NONE)
4924                                         {
4925                                                 mm_attrs_set_int_by_name(attrs, "display_rotation", MM_DISPLAY_ROTATION_NONE);
4926                                                 if (mmf_attrs_commit (attrs)) /* return -1 if error */
4927                                                         debug_error("failed to commit\n");
4928                                                 debug_warning("unsupported feature");
4929                                                 return MM_ERROR_NOT_SUPPORT_API;
4930                                         }
4931                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4932                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4933                                                         "evas-object", object,
4934                                                         "visible", visible,
4935                                                         "display-geometry-method", display_method,
4936                                                         "rotate", rotation_value,
4937                                                         NULL);
4938                                         debug_log("set video param : method %d", display_method);
4939                                         debug_log("set video param : evas-object %x, visible %d", object, visible);
4940                                         debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
4941                                 }
4942                                 else
4943                                 {
4944                                         debug_error("no evas object");
4945                                         return MM_ERROR_PLAYER_INTERNAL;
4946                                 }
4947
4948
4949                                 /* if evasimagesink using converter */
4950                                 if (player->set_mode.video_zc && player->pipeline->videobin[MMPLAYER_V_CONV].gst)
4951                                 {
4952                                         int width = 0;
4953                                         int height = 0;
4954                                         int no_scaling = !scaling;
4955
4956                                         mm_attrs_get_int_by_name(attrs, "display_width", &width);
4957                                         mm_attrs_get_int_by_name(attrs, "display_height", &height);
4958
4959                                         /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
4960                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
4961                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-buffer-num", 5, NULL);
4962
4963                                         if (no_scaling)
4964                                         {
4965                                                 /* no-scaling order to fimcconvert, original width, height size of media src will be passed to sink plugin */
4966                                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst,
4967                                                                 "dst-width", 0, /* setting 0, output video width will be media src's width */
4968                                                                 "dst-height", 0, /* setting 0, output video height will be media src's height */
4969                                                                 NULL);
4970                                         }
4971                                         else
4972                                         {
4973                                                 /* scaling order to fimcconvert */
4974                                                 if (width)
4975                                                 {
4976                                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
4977                                                 }
4978                                                 if (height)
4979                                                 {
4980                                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
4981                                                 }
4982                                                 debug_log("set video param : video frame scaling down to width(%d) height(%d)", width, height);
4983                                         }
4984                                         debug_log("set video param : display_evas_do_scaling %d", scaling);
4985                                 }
4986                         }
4987
4988                         /* if evaspixmapsink */
4989                         if (!strcmp(player->ini.videosink_element_evas,"evaspixmapsink"))
4990                         {
4991                                 if (object)
4992                                 {
4993                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4994                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4995                                                         "evas-object", object,
4996                                                         "visible", visible,
4997                                                         "display-geometry-method", display_method,
4998                                                         "rotate", rotation_value,
4999                                                         NULL);
5000                                         debug_log("set video param : method %d", display_method);
5001                                         debug_log("set video param : evas-object %x, visible %d", object, visible);
5002                                         debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
5003                                 }
5004                                 else
5005                                 {
5006                                         debug_error("no evas object");
5007                                         return MM_ERROR_PLAYER_INTERNAL;
5008                                 }
5009
5010                                 int display_method = 0;
5011                                 int roi_x = 0;
5012                                 int roi_y = 0;
5013                                 int roi_w = 0;
5014                                 int roi_h = 0;
5015                                 int origin_size = !scaling;
5016
5017                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
5018                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
5019                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
5020                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
5021                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
5022
5023                                 /* get rotation value to set */
5024                                 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
5025
5026                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5027                                         "origin-size", origin_size,
5028                                         "rotate", rotation_value,
5029                                         "dst-roi-x", roi_x,
5030                                         "dst-roi-y", roi_y,
5031                                         "dst-roi-w", roi_w,
5032                                         "dst-roi-h", roi_h,
5033                                         "display-geometry-method", display_method,
5034                                         NULL );
5035
5036                                 debug_log("set video param : method %d", display_method);
5037                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
5038                                                                 roi_x, roi_y, roi_w, roi_h );
5039                                 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
5040                         }
5041                 }
5042                 break;
5043                 case MM_DISPLAY_SURFACE_X_EXT:  /* NOTE : this surface type is used for the videoTexture(canvasTexture) overlay */
5044                 {
5045                         void *pixmap_id_cb = NULL;
5046                         void *pixmap_id_cb_user_data = NULL;
5047                         int display_method = 0;
5048                         gboolean visible = TRUE;
5049
5050                         /* if xvimagesink */
5051                         if (strcmp(player->ini.videosink_element_x,"xvimagesink"))
5052                         {
5053                                 debug_error("videosink is not xvimagesink");
5054                                 return MM_ERROR_PLAYER_INTERNAL;
5055                         }
5056
5057                         /* get information from attributes */
5058                         mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
5059                         mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
5060                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
5061                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
5062
5063                         if ( pixmap_id_cb )
5064                         {
5065                                 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
5066                                 if (pixmap_id_cb_user_data)
5067                                 {
5068                                         debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
5069                                 }
5070                         }
5071                         else
5072                         {
5073                                 debug_error("failed to set pixmap-id-callback");
5074                                 return MM_ERROR_PLAYER_INTERNAL;
5075                         }
5076                         /* get rotation value to set */
5077                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
5078
5079                         debug_log("set video param : rotate %d, method %d, visible %d", rotation_value, display_method, visible);
5080
5081                         /* set properties of videosink plugin */
5082                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5083                                 "display-geometry-method", display_method,
5084                                 "draw-borders", FALSE,
5085                                 "visible", visible,
5086                                 "rotate", rotation_value,
5087                                 "pixmap-id-callback", pixmap_id_cb,
5088                                 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
5089                                 NULL );
5090                 }
5091                 break;
5092                 case MM_DISPLAY_SURFACE_NULL:
5093                 {
5094                         /* do nothing */
5095                 }
5096                 break;
5097         }
5098
5099         MMPLAYER_FLEAVE();
5100
5101         return MM_ERROR_NONE;
5102 }
5103
5104 static int
5105 __mmplayer_gst_element_link_bucket(GList* element_bucket) // @
5106 {
5107         GList* bucket = element_bucket;
5108         MMPlayerGstElement* element = NULL;
5109         MMPlayerGstElement* prv_element = NULL;
5110         gint successful_link_count = 0;
5111
5112         MMPLAYER_FENTER();
5113
5114         return_val_if_fail(element_bucket, -1);
5115
5116         prv_element = (MMPlayerGstElement*)bucket->data;
5117         bucket = bucket->next;
5118
5119         for ( ; bucket; bucket = bucket->next )
5120         {
5121                 element = (MMPlayerGstElement*)bucket->data;
5122
5123                 if ( element && element->gst )
5124                 {
5125                         if ( GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst)) )
5126                         {
5127                                 debug_log("linking [%s] to [%s] success\n",
5128                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
5129                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
5130                                 successful_link_count ++;
5131                         }
5132                         else
5133                         {
5134                                 debug_log("linking [%s] to [%s] failed\n",
5135                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
5136                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
5137                                 return -1;
5138                         }
5139                 }
5140
5141                 prv_element = element;
5142         }
5143
5144         MMPLAYER_FLEAVE();
5145
5146         return successful_link_count;
5147 }
5148
5149 static int
5150 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket) // @
5151 {
5152         GList* bucket = element_bucket;
5153         MMPlayerGstElement* element = NULL;
5154         int successful_add_count = 0;
5155
5156         MMPLAYER_FENTER();
5157
5158         return_val_if_fail(element_bucket, 0);
5159         return_val_if_fail(bin, 0);
5160
5161         for ( ; bucket; bucket = bucket->next )
5162         {
5163                 element = (MMPlayerGstElement*)bucket->data;
5164
5165                 if ( element && element->gst )
5166                 {
5167                         if( !gst_bin_add(bin, GST_ELEMENT(element->gst)) )
5168                         {
5169                                 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
5170                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
5171                                         GST_ELEMENT_NAME(GST_ELEMENT(bin) ) );
5172                                 return 0;
5173                         }
5174                         successful_add_count ++;
5175                 }
5176         }
5177
5178         MMPLAYER_FLEAVE();
5179
5180         return successful_add_count;
5181 }
5182
5183
5184
5185 /**
5186  * This function is to create audio pipeline for playing.
5187  *
5188  * @param       player          [in]    handle of player
5189  *
5190  * @return      This function returns zero on success.
5191  * @remark
5192  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
5193  */
5194 #define MMPLAYER_CREATEONLY_ELEMENT(x_bin, x_id, x_factory, x_name) \
5195 x_bin[x_id].id = x_id;\
5196 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5197 if ( ! x_bin[x_id].gst )\
5198 {\
5199         debug_error("failed to create %s \n", x_factory);\
5200         goto ERROR;\
5201 }\
5202
5203 #define MMPLAYER_CREATE_ELEMENT_ADD_BIN(x_bin, x_id, x_factory, x_name, y_bin, x_player) \
5204 x_bin[x_id].id = x_id;\
5205 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5206 if ( ! x_bin[x_id].gst )\
5207 {\
5208         debug_error("failed to create %s \n", x_factory);\
5209         goto ERROR;\
5210 }\
5211 else\
5212 {\
5213         if (x_player->ini.set_dump_element_flag)\
5214                 __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
5215 }\
5216 if( !gst_bin_add(GST_BIN(y_bin), GST_ELEMENT(x_bin[x_id].gst)))\
5217 {\
5218         debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",\
5219                 GST_ELEMENT_NAME(GST_ELEMENT(x_bin[x_id].gst)),\
5220                 GST_ELEMENT_NAME(GST_ELEMENT(y_bin) ) );\
5221         goto ERROR;\
5222 }\
5223
5224 /* macro for code readability. just for sinkbin-creation functions */
5225 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
5226 do \
5227 { \
5228         x_bin[x_id].id = x_id;\
5229         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5230         if ( ! x_bin[x_id].gst )\
5231         {\
5232                 debug_error("failed to create %s \n", x_factory);\
5233                 goto ERROR;\
5234         }\
5235         else\
5236         {\
5237                 if (x_player->ini.set_dump_element_flag)\
5238                         __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
5239         }\
5240         if ( x_add_bucket )\
5241                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
5242 } while(0);
5243
5244 /**
5245   * AUDIO PIPELINE
5246   * - Local playback    : audiotp !audioconvert ! volume ! capsfilter ! audioeffect ! audioeffect_sec ! audiosink
5247   * - Streaming         : audiotp !audioconvert !volume ! audiosink
5248   * - PCM extraction : audiotp !audioconvert ! audioresample ! capsfilter ! fakesink
5249   */
5250 static int
5251 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
5252 {
5253         MMPlayerGstElement* first_element = NULL;
5254         MMPlayerGstElement* audiobin = NULL;
5255         MMHandleType attrs = 0;
5256         GstPad *pad = NULL;
5257         GstPad *ghostpad = NULL;
5258         GList* element_bucket = NULL;
5259         gboolean link_audio_sink_now = TRUE;
5260         int i =0;
5261
5262         MMPLAYER_FENTER();
5263
5264         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5265
5266         /* alloc handles */
5267         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
5268         if ( ! audiobin )
5269         {
5270                 debug_error("failed to allocate memory for audiobin\n");
5271                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5272         }
5273
5274         attrs = MMPLAYER_GET_ATTRS(player);
5275
5276         /* create bin */
5277         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
5278         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
5279         if ( !audiobin[MMPLAYER_A_BIN].gst )
5280         {
5281                 debug_error("failed to create audiobin\n");
5282                 goto ERROR;
5283         }
5284
5285         /* take it */
5286         player->pipeline->audiobin = audiobin;
5287
5288         player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
5289
5290         /* Adding audiotp plugin for reverse trickplay feature */
5291         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
5292
5293         /* converter */
5294         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
5295
5296         /* resampler */
5297         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER,  player->ini.name_of_audio_resampler, "audio resampler", TRUE, player);
5298
5299         if (player->set_mode.pcm_extraction) // pcm extraction only and no sound output
5300         {
5301                 int dst_samplerate = 0;
5302                 int dst_channels = 0;
5303                 int dst_depth = 0;
5304                 char *caps_str = NULL;
5305                 GstCaps* caps = NULL;
5306
5307                 /* get conf. values */
5308                 mm_attrs_multiple_get(player->attrs,
5309                                         NULL,
5310                                         "pcm_extraction_samplerate", &dst_samplerate,
5311                                         "pcm_extraction_channels", &dst_channels,
5312                                         "pcm_extraction_depth", &dst_depth,
5313                                         NULL);
5314
5315                 /* capsfilter */
5316                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
5317                 caps = gst_caps_new_simple ("audio/x-raw-int",
5318                                 "rate", G_TYPE_INT, dst_samplerate,
5319                                 "channels", G_TYPE_INT, dst_channels,
5320                                 "depth", G_TYPE_INT, dst_depth,
5321                                 NULL);
5322                 caps_str = gst_caps_to_string(caps);
5323                 debug_log("new caps : %s\n", caps_str);
5324
5325                 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5326
5327                 /* clean */
5328                 gst_caps_unref( caps );
5329                 MMPLAYER_FREEIF( caps_str );
5330
5331                 /* fake sink */
5332                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
5333
5334                 /* set sync */
5335                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
5336         }
5337         else // normal playback
5338         {
5339                 typedef enum
5340                 {
5341                         GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE = 0,
5342                         GST_BASE_AUDIO_SINK_SLAVE_SKEW,
5343                         GST_BASE_AUDIO_SINK_SLAVE_NONE
5344                 } GstBaseAudioSinkSlaveMethod;
5345
5346                 //GstCaps* caps = NULL;
5347                 gint channels = 0;
5348
5349                 /* for logical volume control */
5350                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
5351                 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
5352
5353                 if (player->sound.mute)
5354                 {
5355                         debug_log("mute enabled\n");
5356                         g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
5357                 }
5358
5359 #if 0
5360                 /*capsfilter */
5361                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
5362                 caps = gst_caps_from_string( "audio/x-raw-int, "
5363                                         "endianness = (int) LITTLE_ENDIAN, "
5364                                         "signed = (boolean) true, "
5365                                         "width = (int) 16, "
5366                                         "depth = (int) 16" );
5367                 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5368                 gst_caps_unref( caps );
5369 #endif
5370
5371                 /* chech if multi-chennels */
5372                 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)
5373                 {
5374                         GstPad *srcpad = NULL;
5375                         GstCaps *caps = NULL;
5376
5377                         if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src")))
5378                         {
5379                                 if ((caps = gst_pad_get_caps(srcpad)))
5380                                 {
5381                                         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5382                                         GstStructure *str = gst_caps_get_structure(caps, 0);
5383                                         if (str)
5384                                                 gst_structure_get_int (str, "channels", &channels);
5385                                         gst_caps_unref(caps);
5386                                 }
5387                                 gst_object_unref(srcpad);
5388                         }
5389                 }
5390
5391                 /* audio effect element. if audio effect is enabled */
5392                 if ( (strcmp(player->ini.name_of_audio_effect, ""))
5393                         && (channels <= 2)
5394                         && player->ini.use_audio_effect_custom)
5395                 {
5396                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.name_of_audio_effect, "audio effect filter", TRUE, player);
5397
5398                         debug_log("audio effect config. bypass = %d, effect type  = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
5399
5400                         if ( (!player->bypass_audio_effect)
5401                                 && player->ini.use_audio_effect_custom)
5402                         {
5403                                 if ( MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type )
5404                                 {
5405                                         if (!_mmplayer_audio_effect_custom_apply(player))
5406                                         {
5407                                                 debug_msg("apply audio effect(custom) setting success\n");
5408                                         }
5409                                 }
5410                         }
5411
5412                         if ( (strcmp(player->ini.name_of_audio_effect_sec, ""))
5413                                 && (player->set_mode.rich_audio) )
5414                         {
5415                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.name_of_audio_effect_sec, "audio effect filter", TRUE, player);
5416                         }
5417                 }
5418                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
5419                 {
5420                         if (player->set_mode.rich_audio && channels <= 2)
5421                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VSP, "audiovsp", "x-speed", TRUE, player);
5422                 }
5423
5424                 /* create audio sink */
5425                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.name_of_audiosink, "audiosink", link_audio_sink_now, player);
5426
5427                 /* qos on */
5428                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);     /* qos on */
5429                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_BASE_AUDIO_SINK_SLAVE_NONE, NULL);
5430
5431                 /* FIXIT : using system clock. isn't there another way? */
5432                 if (player->videodec_linked)
5433                 {
5434                         debug_log("provide clock for movie = %s", (player->ini.provide_clock_for_movie)?"audio_clock":"sys_clock");
5435                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_movie,  NULL);
5436                 }
5437                 else
5438                 {
5439                         debug_log("provide clock for music = %s", (player->ini.provide_clock_for_music)?"audio_clock":"sys_clock");
5440                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_music,  NULL);
5441                 }
5442
5443                 if ( g_strrstr(player->ini.name_of_audiosink, "avsysaudiosink") || g_strrstr(player->ini.name_of_audiosink, "pulsesink") )
5444                 {
5445                         gint volume_type = 0;
5446                         gint audio_route = 0;
5447                         gint sound_priority = FALSE;
5448                         gint route_path = 0;
5449                         gint latency_mode = 0;
5450                         gint close_handle = 0;
5451
5452                         /* set volume table
5453                          * It should be set after player creation through attribute.
5454                          * But, it can not be changed during playing.
5455                          */
5456                         mm_attrs_get_int_by_name(attrs, "sound_volume_type", &volume_type);
5457                         mm_attrs_get_int_by_name(attrs, "sound_route", &audio_route);
5458                         mm_attrs_get_int_by_name(attrs, "sound_priority", &sound_priority);
5459                         mm_attrs_get_int_by_name(attrs, "sound_spk_out_only", &route_path);
5460                         mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
5461
5462                         if (player->sm.user_route_policy != 0) {
5463                                 route_path = player->sm.user_route_policy;
5464                         }
5465
5466                         g_object_set(audiobin[MMPLAYER_A_SINK].gst,
5467                                         "volumetype", volume_type,
5468                                         "audio-route", audio_route,
5469                                         "priority", sound_priority,
5470                                         "user-route", route_path,
5471                                         "latency", latency_mode,
5472                                         "close-handle-on-prepare", close_handle,
5473                                         NULL);
5474
5475                         debug_log("audiosink property status...volume type:%d, route:%d, priority=%d, user-route=%d, latency=%d, close-resource=%d\n",
5476                                 volume_type, audio_route, sound_priority, route_path, latency_mode, close_handle);
5477                 }
5478
5479                 /* Antishock can be enabled when player is resumed by soundCM.
5480                  * But, it's not used in MMS, setting and etc.
5481                  * Because, player start seems like late.
5482                  */
5483                 __mmplayer_set_antishock( player , FALSE );
5484         }
5485
5486         __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
5487
5488         /* adding created elements to bin */
5489         debug_log("adding created elements to bin\n");
5490         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket ))
5491         {
5492                 debug_error("failed to add elements\n");
5493                 goto ERROR;
5494         }
5495
5496         /* linking elements in the bucket by added order. */
5497         debug_log("Linking elements in the bucket by added order.\n");
5498         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5499         {
5500                 debug_error("failed to link elements\n");
5501                 goto ERROR;
5502         }
5503
5504         /* get first element's sinkpad for creating ghostpad */
5505         first_element = (MMPlayerGstElement *)element_bucket->data;
5506
5507         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5508         if ( ! pad )
5509         {
5510                 debug_error("failed to get pad from first element of audiobin\n");
5511                 goto ERROR;
5512         }
5513
5514         ghostpad = gst_ghost_pad_new("sink", pad);
5515         if ( ! ghostpad )
5516         {
5517                 debug_error("failed to create ghostpad\n");
5518                 goto ERROR;
5519         }
5520
5521         if ( FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad) )
5522         {
5523                 debug_error("failed to add ghostpad to audiobin\n");
5524                 goto ERROR;
5525         }
5526
5527         gst_object_unref(pad);
5528
5529         g_list_free(element_bucket);
5530
5531         mm_attrs_set_int_by_name(attrs, "content_audio_found", TRUE);
5532
5533         MMPLAYER_FLEAVE();
5534
5535         return MM_ERROR_NONE;
5536
5537 ERROR:
5538
5539         debug_log("ERROR : releasing audiobin\n");
5540
5541         if ( pad )
5542                 gst_object_unref(GST_OBJECT(pad));
5543
5544         if ( ghostpad )
5545                 gst_object_unref(GST_OBJECT(ghostpad));
5546
5547         g_list_free( element_bucket );
5548
5549         /* release element which are not added to bin */
5550         for ( i = 1; i < MMPLAYER_A_NUM; i++ )  /* NOTE : skip bin */
5551         {
5552                 if ( audiobin[i].gst )
5553                 {
5554                         GstObject* parent = NULL;
5555                         parent = gst_element_get_parent( audiobin[i].gst );
5556
5557                         if ( !parent )
5558                         {
5559                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
5560                                 audiobin[i].gst = NULL;
5561                         }
5562                         else
5563                         {
5564                                 gst_object_unref(GST_OBJECT(parent));
5565                         }
5566                 }
5567         }
5568
5569         /* release audiobin with it's childs */
5570         if ( audiobin[MMPLAYER_A_BIN].gst )
5571         {
5572                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
5573         }
5574
5575         MMPLAYER_FREEIF( audiobin );
5576
5577         player->pipeline->audiobin = NULL;
5578
5579         return MM_ERROR_PLAYER_INTERNAL;
5580 }
5581
5582 static gboolean
5583 __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data)
5584 {
5585         mm_player_t* player = (mm_player_t*) u_data;
5586         gint size;
5587         guint8 *data;
5588
5589         data = GST_BUFFER_DATA(buffer);
5590         size = GST_BUFFER_SIZE(buffer);
5591
5592         if (player->audio_stream_cb && size && data)
5593                 player->audio_stream_cb((void *)data, size, player->audio_stream_cb_user_param);
5594
5595         return TRUE;
5596 }
5597
5598 static gboolean
5599 __mmplayer_video_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer user_data)
5600 {
5601         GstCaps *caps = NULL;
5602         MMPlayerVideoStreamDataType stream;
5603         MMPlayerMPlaneImage *scmn_imgb = NULL;
5604         GstStructure *structure = NULL;
5605         unsigned int fourcc = 0;
5606         mm_player_t* player = (mm_player_t*)user_data;
5607
5608         caps = gst_buffer_get_caps(buffer);
5609         if (caps == NULL) {
5610                 debug_error( "Caps is NULL." );
5611                 return TRUE;
5612         }
5613
5614         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5615
5616         /* clear stream data structure */
5617         memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
5618
5619         structure = gst_caps_get_structure( caps, 0 );
5620         gst_structure_get_int(structure, "width", &(stream.width));
5621         gst_structure_get_int(structure, "height", &(stream.height));
5622         gst_structure_get_fourcc(structure, "format", &fourcc);
5623         stream.format = util_get_pixtype(fourcc);
5624         gst_caps_unref( caps );
5625         caps = NULL;
5626
5627     /*
5628         debug_log( "Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
5629                         GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format );
5630     */
5631
5632         if (stream.width == 0 || stream.height == 0) {
5633                 debug_error("Wrong condition!!");
5634                 return TRUE;
5635         }
5636
5637         /* set size and timestamp */
5638         stream.length_total = GST_BUFFER_SIZE(buffer);
5639         stream.timestamp = (unsigned int)(GST_BUFFER_TIMESTAMP(buffer)/1000000); /* nano sec -> mili sec */
5640
5641         //check zero-copy
5642         if (player->set_mode.video_zc
5643                 && player->set_mode.media_packet_video_stream
5644                 && GST_BUFFER_MALLOCDATA(buffer)) {
5645                 scmn_imgb = (MMPlayerMPlaneImage *)GST_BUFFER_MALLOCDATA(buffer);
5646         }
5647
5648         /* set tbm bo */
5649         if (scmn_imgb) {
5650                 /* copy pointer of tbm bo, stride, elevation */
5651                 memcpy(stream.bo, scmn_imgb->bo, sizeof(void *) * MM_PLAYER_IMGB_MPLANE_MAX);
5652                 memcpy(stream.stride, scmn_imgb->s, sizeof(int) * MM_PLAYER_IMGB_MPLANE_MAX);
5653                 memcpy(stream.elevation, scmn_imgb->e, sizeof(int) * MM_PLAYER_IMGB_MPLANE_MAX);
5654
5655                 /*
5656                 int i = 0;
5657                 for (i = 0 ; i < BUFFER_MAX_PLANE_NUM ; i++) {
5658                         debug_log("w %d, h %d, s %d, e %d, bo %p",
5659                                         scmn_imgb->w[i],scmn_imgb->h[i],scmn_imgb->s[i],scmn_imgb->e[i],
5660                                         scmn_imgb->bo[i]);
5661                         if(scmn_imgb->bo[i])
5662                                 debug_log("bo size %d", tbm_bo_size(scmn_imgb->bo[i]));
5663                 }
5664                 */
5665
5666                 /* set gst buffer */
5667                 stream.internal_buffer = buffer;
5668         } else {
5669                 stream.data = GST_BUFFER_DATA(buffer);
5670         }
5671
5672         if (player->video_stream_cb) {
5673                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
5674         }
5675
5676         return TRUE;
5677 }
5678
5679 static int
5680 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket, gboolean use_video_stream)
5681 {
5682         gchar* video_csc = "ffmpegcolorspace"; // default colorspace converter
5683         GList* element_bucket = *bucket;
5684
5685         return_val_if_fail(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5686
5687         MMPLAYER_FENTER();
5688
5689         if (!player->set_mode.media_packet_video_stream && use_video_stream)
5690         {
5691                 if (player->set_mode.video_zc && strlen(player->ini.name_of_video_converter) > 0)
5692                 {
5693                         video_csc = player->ini.name_of_video_converter;
5694                 }
5695
5696                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5697                 debug_log("using video converter: %s", video_csc);
5698
5699                 if ( !player->set_mode.video_zc)
5700                 {
5701                         GstStructure *str = NULL;
5702                         gint width = 0;         //width of video
5703                         gint height = 0;                //height of video
5704                         GstCaps* video_caps = NULL;
5705                         GstStructure *structure = NULL;
5706
5707                         /* rotator, scaler and capsfilter */
5708                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5709                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "video scaler", TRUE, player);
5710                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CAPS, "capsfilter", "videocapsfilter", TRUE, player);
5711
5712                         /* get video stream caps parsed by demuxer */
5713                         str = gst_caps_get_structure (player->v_stream_caps, 0);
5714                         if ( !str )
5715                         {
5716                                 debug_error("cannot get structure");
5717                                 goto ERROR;
5718                         }
5719
5720                         mm_attrs_get_int_by_name(player->attrs, "display_width", &width);
5721
5722                         if (width) {
5723                                 structure = gst_structure_new("video/x-raw-rgb", "width", G_TYPE_INT, width, NULL);
5724                         }
5725
5726                         mm_attrs_get_int_by_name(player->attrs, "display_height", &height);
5727
5728                         if (height ) {
5729                                 if (structure) {
5730                                         gst_structure_set (structure, "height", G_TYPE_INT, height, NULL);
5731                                 }else {
5732                                         structure = gst_structure_new("video/x-raw-rgb", "height", G_TYPE_INT, height, NULL);
5733                                 }
5734                         }
5735
5736                         if (width ||height) {
5737                                 video_caps = gst_caps_new_full(structure, NULL);
5738                                 gst_structure_free(structure);
5739
5740                                 g_object_set (GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_CAPS].gst), "caps", video_caps, NULL );
5741                                 MMPLAYER_LOG_GST_CAPS_TYPE(video_caps);
5742                                 gst_caps_unref(video_caps);
5743                         }
5744                 }
5745         }
5746         else
5747         {
5748                 MMDisplaySurfaceType surface_type = MM_DISPLAY_SURFACE_NULL;
5749                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", (int *)&surface_type);
5750
5751                 if (player->set_mode.video_zc)
5752                 {
5753                         if ( (surface_type == MM_DISPLAY_SURFACE_EVAS) && ( !strcmp(player->ini.videosink_element_evas, "evasimagesink")) )
5754                         {
5755                                 video_csc = player->ini.name_of_video_converter;
5756                         }
5757                         else
5758                         {
5759                                 video_csc = "";
5760                         }
5761                 }
5762
5763                 if (video_csc && (strcmp(video_csc, "")))
5764                 {
5765                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5766                         debug_log("using video converter: %s", video_csc);
5767                 }
5768
5769                 /* set video rotator */
5770                 if ( !player->set_mode.video_zc )
5771                         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5772
5773                 /* videoscaler */
5774                 #if !defined(__arm__)
5775                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "videoscaler", TRUE, player);
5776                 #endif
5777         }
5778
5779         *bucket = element_bucket;
5780         MMPLAYER_FLEAVE();
5781         return MM_ERROR_NONE;
5782
5783 ERROR:
5784         *bucket = NULL;
5785         MMPLAYER_FLEAVE();
5786         return MM_ERROR_PLAYER_INTERNAL;
5787 }
5788
5789 /**
5790  * This function is to create video pipeline.
5791  *
5792  * @param       player          [in]    handle of player
5793  *              caps            [in]    src caps of decoder
5794  *              surface_type    [in]    surface type for video rendering
5795  *
5796  * @return      This function returns zero on success.
5797  * @remark
5798  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5799  */
5800 /**
5801   * VIDEO PIPELINE
5802   * - x surface (arm/x86) : xvimagesink
5803   * - evas surface  (arm) : evaspixmapsink
5804   *                         fimcconvert ! evasimagesink
5805   * - evas surface  (x86) : videoconvertor ! videoflip ! evasimagesink
5806   */
5807 static int
5808 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5809 {
5810         GstPad *pad = NULL;
5811         MMHandleType attrs;
5812         GList*element_bucket = NULL;
5813         MMPlayerGstElement* first_element = NULL;
5814         MMPlayerGstElement* videobin = NULL;
5815         gchar *videosink_element = NULL;
5816
5817         MMPLAYER_FENTER();
5818
5819         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5820
5821         /* alloc handles */
5822         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5823         if ( !videobin )
5824         {
5825                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5826         }
5827
5828         player->pipeline->videobin = videobin;
5829
5830         attrs = MMPLAYER_GET_ATTRS(player);
5831         if ( !attrs )
5832         {
5833                 debug_error("cannot get content attribute");
5834                 return MM_ERROR_PLAYER_INTERNAL;
5835         }
5836
5837         /* create bin */
5838         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
5839         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
5840         if ( !videobin[MMPLAYER_V_BIN].gst )
5841         {
5842                 debug_error("failed to create videobin");
5843                 goto ERROR;
5844         }
5845
5846         if( player->use_video_stream ) // video stream callback, so send raw video data to application
5847         {
5848                 debug_log("using memsink\n");
5849
5850                 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, TRUE) != MM_ERROR_NONE)
5851                         goto ERROR;
5852
5853                 /* finally, create video sink. output will be BGRA8888. */
5854                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, "avsysmemsink", "videosink", TRUE, player);
5855
5856                 MMPLAYER_SIGNAL_CONNECT( player,
5857                                                                          videobin[MMPLAYER_V_SINK].gst,
5858                                                                          MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5859                                                                          "video-stream",
5860                                                                          G_CALLBACK(__mmplayer_videostream_cb),
5861                                                                          player );
5862         }
5863         else // render video data using sink plugin like xvimagesink
5864         {
5865                 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, FALSE) != MM_ERROR_NONE)
5866                         goto ERROR;
5867
5868                 /* set video sink */
5869                 switch (surface_type)
5870                 {
5871                         case MM_DISPLAY_SURFACE_X:
5872                                 if (strlen(player->ini.videosink_element_x) > 0)
5873                                         videosink_element = player->ini.videosink_element_x;
5874                                 else
5875                                         goto ERROR;
5876                                 break;
5877                         case MM_DISPLAY_SURFACE_EVAS:
5878                                 if (strlen(player->ini.videosink_element_evas) > 0)
5879                                         videosink_element = player->ini.videosink_element_evas;
5880                                 else
5881                                         goto ERROR;
5882                                 break;
5883                         case MM_DISPLAY_SURFACE_X_EXT:
5884                         {
5885                                 void *pixmap_id_cb = NULL;
5886                                 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
5887                                 if (pixmap_id_cb) /* this is used for the videoTextue(canvasTexture) overlay */
5888                                 {
5889                                         videosink_element = player->ini.videosink_element_x;
5890                                 }
5891                                 else
5892                                 {
5893                                         debug_error("something wrong.. callback function for getting pixmap id is null");
5894                                         goto ERROR;
5895                                 }
5896                                 break;
5897                         }
5898                         case MM_DISPLAY_SURFACE_NULL:
5899                                 if (strlen(player->ini.videosink_element_fake) > 0)
5900                                         videosink_element = player->ini.videosink_element_fake;
5901                                 else
5902                                         goto ERROR;
5903                                 break;
5904                         default:
5905                                 debug_error("unidentified surface type");
5906                                 goto ERROR;
5907                 }
5908
5909                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, videosink_element, TRUE, player);
5910                 debug_log("selected videosink name: %s", videosink_element);
5911                 if(surface_type==MM_DISPLAY_SURFACE_X)
5912                 {
5913                         MMPLAYER_SIGNAL_CONNECT( player,
5914                                                                         videobin[MMPLAYER_V_SINK].gst,
5915                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5916                                                                         "display-status",
5917                                                                         G_CALLBACK(__mmplayer_display_status_cb),
5918                                                                         player );
5919                         MMPLAYER_SIGNAL_CONNECT( player,
5920                                                                         videobin[MMPLAYER_V_SINK].gst,
5921                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5922                                                                         "external-resolution",
5923                                                                         G_CALLBACK(__mmplayer_external_resolution_cb),
5924                                                                         player );
5925                         MMPLAYER_SIGNAL_CONNECT( player,
5926                                                                         videobin[MMPLAYER_V_SINK].gst,
5927                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5928                                                                         "hided-window",
5929                                                                         G_CALLBACK(__mmplayer_hided_window_cb),
5930                                                                         player );
5931                         MMPLAYER_SIGNAL_CONNECT( player,
5932                                                                         videobin[MMPLAYER_V_SINK].gst,
5933                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5934                                                                         "quick-panel-on",
5935                                                                         G_CALLBACK(__mmplayer_quick_panel_on_cb),
5936                                                                         player );
5937                         MMPLAYER_SIGNAL_CONNECT( player,
5938                                                                         videobin[MMPLAYER_V_SINK].gst,
5939                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5940                                                                         "multiwindow-active",
5941                                                                         G_CALLBACK(__mmplayer_multiwindow_active_cb),
5942                                                                         player );
5943                 }
5944                 /* connect signal handlers for sink plug-in */
5945                 switch (surface_type) {
5946                         case MM_DISPLAY_SURFACE_X_EXT:
5947                                 MMPLAYER_SIGNAL_CONNECT( player,
5948                                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5949                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5950                                                                                 "frame-render-error",
5951                                                                                 G_CALLBACK(__mmplayer_videoframe_render_error_cb),
5952                                                                                 player );
5953                                 debug_log("videoTexture usage, connect a signal handler for pixmap rendering error");
5954                                 break;
5955                         default:
5956                                 break;
5957                 }
5958         }
5959
5960         if ( _mmplayer_update_video_param(player) != MM_ERROR_NONE)
5961                 goto ERROR;
5962
5963         /* store it as it's sink element */
5964         __mmplayer_add_sink( player, videobin[MMPLAYER_V_SINK].gst );
5965
5966         /* adding created elements to bin */
5967         if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket) )
5968         {
5969                 debug_error("failed to add elements\n");
5970                 goto ERROR;
5971         }
5972
5973         /* Linking elements in the bucket by added order */
5974         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5975         {
5976                 debug_error("failed to link elements\n");
5977                 goto ERROR;
5978         }
5979
5980         /* get first element's sinkpad for creating ghostpad */
5981         first_element = (MMPlayerGstElement *)element_bucket->data;
5982         if ( !first_element )
5983         {
5984                 debug_error("failed to get first element from bucket\n");
5985                 goto ERROR;
5986         }
5987
5988         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5989         if ( !pad )
5990         {
5991                 debug_error("failed to get pad from first element\n");
5992                 goto ERROR;
5993         }
5994
5995         /* create ghostpad */
5996         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
5997         if ( FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
5998         {
5999                 debug_error("failed to add ghostpad to videobin\n");
6000                 goto ERROR;
6001         }
6002         gst_object_unref(pad);
6003
6004         /* done. free allocated variables */
6005         g_list_free(element_bucket);
6006
6007         mm_attrs_set_int_by_name(attrs, "content_video_found", TRUE);
6008
6009         MMPLAYER_FLEAVE();
6010
6011         return MM_ERROR_NONE;
6012
6013 ERROR:
6014         debug_error("ERROR : releasing videobin\n");
6015
6016         g_list_free( element_bucket );
6017
6018         if (pad)
6019                 gst_object_unref(GST_OBJECT(pad));
6020
6021         /* release videobin with it's childs */
6022         if ( videobin[MMPLAYER_V_BIN].gst )
6023         {
6024                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
6025         }
6026
6027
6028         MMPLAYER_FREEIF( videobin );
6029
6030         player->pipeline->videobin = NULL;
6031
6032         return MM_ERROR_PLAYER_INTERNAL;
6033 }
6034
6035 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
6036 {
6037         GList *element_bucket = NULL;
6038         MMPlayerGstElement *textbin = player->pipeline->textbin;
6039
6040         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_FAKE_QUEUE, "queue", "text_f_queue", TRUE, player);
6041         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
6042         MMPLAYER_SIGNAL_CONNECT( player,
6043                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
6044                                                         MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
6045                                                         "handoff",
6046                                                         G_CALLBACK(__mmplayer_update_subtitle),
6047                                                         (gpointer)player );
6048
6049         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
6050         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
6051         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
6052
6053         if (!player->play_subtitle)
6054         {
6055                 debug_log ("add textbin sink as sink element of whole pipeline.\n");
6056                 __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
6057         }
6058
6059         /* adding created elements to bin */
6060         debug_log("adding created elements to bin\n");
6061         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
6062         {
6063                 debug_error("failed to add elements\n");
6064                 goto ERROR;
6065         }
6066
6067         /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
6068         GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_IS_SINK);
6069         GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_IS_SINK);
6070
6071         /* linking elements in the bucket by added order. */
6072         debug_log("Linking elements in the bucket by added order.\n");
6073         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
6074         {
6075                 debug_error("failed to link elements\n");
6076                 goto ERROR;
6077         }
6078
6079         /* done. free allocated variables */
6080         g_list_free(element_bucket);
6081
6082         if (textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst)
6083         {
6084                 GstPad *pad = NULL;
6085                 GstPad *ghostpad = NULL;
6086
6087                 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst), "sink");
6088                 if (!pad)
6089                 {
6090                         debug_error("failed to get video pad of textbin\n");
6091                         return MM_ERROR_PLAYER_INTERNAL;
6092                 }
6093
6094                 ghostpad = gst_ghost_pad_new("text_sink", pad);
6095                 gst_object_unref(pad);
6096
6097                 if (!ghostpad)
6098                 {
6099                         debug_error("failed to create ghostpad of textbin\n");
6100                         goto ERROR;
6101                 }
6102
6103                 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad))
6104                 {
6105                         debug_error("failed to add ghostpad to textbin\n");
6106                         goto ERROR;
6107                 }
6108         }
6109
6110         return MM_ERROR_NONE;
6111
6112 ERROR:
6113         g_list_free(element_bucket);
6114
6115         return MM_ERROR_PLAYER_INTERNAL;
6116 }
6117
6118 static int __mmplayer_gst_create_text_pipeline(mm_player_t* player)
6119 {
6120         MMPlayerGstElement *textbin = NULL;
6121         GList *element_bucket = NULL;
6122         GstPad *pad = NULL;
6123         GstPad *ghostpad = NULL;
6124         gint i = 0;
6125
6126         MMPLAYER_FENTER();
6127
6128         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6129
6130         /* alloc handles */
6131         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
6132         if ( ! textbin )
6133         {
6134                 debug_error("failed to allocate memory for textbin\n");
6135                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
6136         }
6137
6138         /* create bin */
6139         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
6140         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
6141         if ( !textbin[MMPLAYER_T_BIN].gst )
6142         {
6143                 debug_error("failed to create textbin\n");
6144                 goto ERROR;
6145         }
6146
6147         /* take it */
6148         player->pipeline->textbin = textbin;
6149
6150         /* fakesink */
6151         if (player->use_textoverlay)
6152         {
6153                 debug_log ("use textoverlay for displaying \n");
6154
6155                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_TEXT_QUEUE, "queue", "text_t_queue", textbin[MMPLAYER_T_BIN].gst, player);
6156
6157                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_QUEUE, "queue", "text_v_queue", textbin[MMPLAYER_T_BIN].gst, player);
6158
6159                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_CONVERTER, "fimcconvert", "text_v_converter", textbin[MMPLAYER_T_BIN].gst, player);
6160
6161                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_OVERLAY, "textoverlay", "text_overlay", textbin[MMPLAYER_T_BIN].gst, player);
6162
6163                 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_QUEUE].gst, "src", textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "sink"))
6164                 {
6165                         debug_error("failed to link queue and converter\n");
6166                         goto ERROR;
6167                 }
6168
6169                 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "video_sink"))
6170                 {
6171                         debug_error("failed to link queue and textoverlay\n");
6172                         goto ERROR;
6173                 }
6174
6175                 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_QUEUE].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "text_sink"))
6176                 {
6177                         debug_error("failed to link queue and textoverlay\n");
6178                         goto ERROR;
6179                 }
6180
6181                 if (textbin[MMPLAYER_T_TEXT_QUEUE].gst)
6182                 {
6183                         pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_TEXT_QUEUE].gst), "sink");
6184                         if (!pad)
6185                         {
6186                                 debug_error("failed to get src pad of textbin\n");
6187                                 goto ERROR;
6188                         }
6189
6190                         ghostpad = gst_ghost_pad_new("sink", pad);
6191                         if (!ghostpad)
6192                         {
6193                                 debug_error("failed to create ghostpad of textbin\n");
6194                                 goto ERROR;
6195                         }
6196
6197                         if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad))
6198                         {
6199                                 debug_error("failed to add ghostpad to textbin\n");
6200                                 goto ERROR;
6201                         }
6202                 }
6203         }
6204         else
6205         {
6206                 int surface_type = 0;
6207                 GstCaps* caps = NULL;
6208
6209                 debug_log ("use subtitle message for displaying \n");
6210
6211                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
6212
6213                 switch(surface_type)
6214                 {
6215                         case MM_DISPLAY_SURFACE_X:
6216                         {
6217                                 /* check whether external subtitle supported or not  */
6218                                 if (!player->ini.external_subtitle)
6219                                 {
6220                                         debug_log ("not supported external subtitle\n");
6221                                         if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE)
6222                                         {
6223                                                 debug_error("failed to make plain text elements\n");
6224                                                 goto ERROR;
6225                                         }
6226                                         break;
6227                                 }
6228
6229                                 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEE, "tee", "text_tee", TRUE, player);
6230                                 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_FAKE_QUEUE, "queue", "text_f_queue", TRUE, player);
6231                                 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst),
6232                                                                                 "max-size-time", (guint64)0,
6233                                                                                 "max-size-bytes", (guint)0,
6234                                                                                 "max-size-buffers", (guint)5,
6235                                                                                 NULL);
6236
6237                                 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_FAKE_IDENTITY, "identity", "text_f_identity", TRUE, player);
6238                                 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst), "signal-handoffs", FALSE, NULL);
6239
6240                                 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
6241                                 MMPLAYER_SIGNAL_CONNECT( player,
6242                                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
6243                                                                                 MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
6244                                                                         "handoff",
6245                                                                         G_CALLBACK(__mmplayer_update_subtitle),
6246                                                                         (gpointer)player );
6247
6248                                 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", FALSE, NULL);
6249                                 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
6250                                 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
6251
6252                                 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_QUEUE, "queue", "text_queue", TRUE, player);
6253                                 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_QUEUE].gst),
6254                                                                                 "max-size-time", (guint64)0,
6255                                                                                 "max-size-bytes", (guint)0,
6256                                                                                 "max-size-buffers", (guint)5,
6257                                                                                 NULL);
6258
6259                                 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_IDENTITY, "identity", "text_identity", TRUE, player);
6260                                 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_IDENTITY].gst), "signal-handoffs", FALSE, NULL);
6261
6262                                 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_RENDER, "subrender", "text_subrender", TRUE, player);
6263
6264                                 if (player->font_desc == NULL)
6265                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_RENDER].gst), "font-desc", "Tizen 42", NULL);
6266                                 else
6267                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_RENDER].gst), "font-desc", player->font_desc, NULL);
6268
6269                                 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_RENDER].gst), "font-color", player->font_color, NULL);
6270                                 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_RENDER].gst), "font-bg-color", player->font_bg_color, NULL);
6271
6272                                 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_CAPSFILTER, "capsfilter", "text_capsfilter", TRUE, player);
6273                                 caps = gst_caps_from_string( "video/x-raw-rgb, "
6274                                 "width = (int) [ 1, MAX ], "
6275                                 "height = (int) [ 1, MAX ], "
6276                                 "framerate = (fraction) [ 0, MAX ], "
6277                                 "subtitle = (boolean) true" );
6278                                 g_object_set (G_OBJECT(textbin[MMPLAYER_T_CAPSFILTER].gst), "caps", caps, NULL );
6279                                 gst_caps_unref( caps );
6280                                 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_VIDEO_SINK, "xvimagesink", "text_xvimagesink", TRUE, player);
6281                                 g_object_set(G_OBJECT(textbin[MMPLAYER_T_VIDEO_SINK].gst), "subpicture", TRUE, NULL);
6282
6283                                 player->display_stat = util_get_is_connected_external_display();
6284
6285                                 if(player->display_stat == MMPLAYER_DISPLAY_STATUS_UNKNOWN_ACTIVE)
6286                                 {
6287                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_RENDER].gst), "external-width", player->ini.mirroring_width, NULL);
6288                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_RENDER].gst), "external-height", player->ini.mirroring_height, NULL);
6289                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_VIDEO_SINK].gst), "external-width", player->ini.mirroring_width, NULL);
6290                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_VIDEO_SINK].gst), "external-height", player->ini.mirroring_height, NULL);
6291                                 }
6292                                 g_object_set(G_OBJECT(textbin[MMPLAYER_T_VIDEO_SINK].gst), "show-preroll-frame", FALSE, NULL);
6293
6294                                 /* if connected with external display */
6295                                 if ((player->display_stat == MMPLAYER_DISPLAY_STATUS_HDMI_ACTIVE) ||
6296                                         (player->display_stat == MMPLAYER_DISPLAY_STATUS_UNKNOWN_ACTIVE)) {
6297                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst), "drop-probability", (gfloat)1.0, NULL);
6298                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_IDENTITY].gst), "drop-probability", (gfloat)0.0, NULL);
6299                                         debug_warning ("connected with external display");
6300                                 } else {
6301                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst), "drop-probability", (gfloat)0.0, NULL);
6302                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_IDENTITY].gst), "drop-probability", (gfloat)1.0, NULL);
6303                                         g_object_set(G_OBJECT(textbin[MMPLAYER_T_VIDEO_SINK].gst), "async", FALSE, NULL);
6304                                         g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", FALSE, NULL);
6305
6306                                         debug_warning ("non-connected status");
6307                                 }
6308                                 if (!player->play_subtitle)
6309                                 {
6310                                         debug_log ("add textbin sink as sink element of whole pipeline.\n");
6311                                         __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
6312                                         __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_VIDEO_SINK].gst));
6313                                 }
6314
6315                                 /* adding created elements to bin */
6316                                 if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
6317                                 {
6318                                         debug_error("failed to add elements\n");
6319                                         goto ERROR;
6320                                 }
6321
6322                                 /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
6323                                 GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_IS_SINK);
6324                                 GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_IS_SINK);
6325                                 GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_VIDEO_SINK].gst, GST_ELEMENT_IS_SINK);
6326
6327                                 /* linking elements in the bucket by added order. */
6328                                 GstPad *pad, *rpad;
6329
6330                                 rpad = gst_element_get_request_pad(textbin[MMPLAYER_T_TEE].gst, "src%d");
6331                                 pad = gst_element_get_static_pad(textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst, "sink");
6332                                 gst_pad_link(rpad, pad);
6333                                 gst_object_unref(rpad);
6334                                 gst_object_unref(pad);
6335
6336                                 rpad = gst_element_get_request_pad(textbin[MMPLAYER_T_TEE].gst, "src%d");
6337                                 pad = gst_element_get_static_pad(textbin[MMPLAYER_T_TEXT_QUEUE].gst, "sink");
6338                                 gst_pad_link(rpad, pad);
6339                                 gst_object_unref(rpad);
6340                                 gst_object_unref(pad);
6341
6342                                 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst, "src", textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "sink")) {
6343                                         debug_error ("fake queue and identity could not be linked.\n");
6344                                         goto ERROR;
6345                                 }
6346                                 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "src", textbin[MMPLAYER_T_FAKE_SINK].gst, "sink")) {
6347                                         debug_error ("indentity and fake sink could not be linked.\n");
6348                                         goto ERROR;
6349                                 }
6350                                 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_QUEUE].gst, "src", textbin[MMPLAYER_T_TEXT_IDENTITY].gst, "sink")) {
6351                                         debug_error ("queue and identity could not be linked.\n");
6352                                         goto ERROR;
6353                                 }
6354                                 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_IDENTITY].gst, "src", textbin[MMPLAYER_T_RENDER].gst, "sink")) {
6355                                         debug_error ("identity and subrender could not be linked.\n");
6356                                         goto ERROR;
6357                                 }
6358                                 if (!gst_element_link_pads (textbin[MMPLAYER_T_RENDER].gst, "src", textbin[MMPLAYER_T_CAPSFILTER].gst, "sink")) {
6359                                         debug_error ("subrender and capsfilter could not be linked.\n");
6360                                         goto ERROR;
6361                                 }
6362                                 if (!gst_element_link_pads (textbin[MMPLAYER_T_CAPSFILTER].gst, "src", textbin[MMPLAYER_T_VIDEO_SINK].gst, "sink")) {
6363                                         debug_error ("capsfilter and xvimagesink could not be linked.\n");
6364                                         goto ERROR;
6365                                 }
6366
6367                                 /* done. free allocated variables */
6368                                 g_list_free(element_bucket);
6369                                 if (textbin[MMPLAYER_T_TEE].gst)
6370                                 {
6371                                         pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_TEE].gst), "sink");
6372                                         if (!pad)
6373                                         {
6374                                                 debug_error("failed to get text pad of textbin\n");
6375                                                 goto ERROR;
6376                                         }
6377
6378                                         ghostpad = gst_ghost_pad_new("text_sink", pad);
6379                                         if (!ghostpad)
6380                                         {
6381                                                 debug_error("failed to create ghostpad of textbin\n");
6382                                                 goto ERROR;
6383                                         }
6384
6385                                         if ( FALSE == gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad) )
6386                                         {
6387                                                 debug_error("failed to add ghostpad to textbin\n");
6388                                                 goto ERROR;
6389                                         }
6390                                 }
6391
6392                                 break;
6393                         }
6394
6395                         case MM_DISPLAY_SURFACE_EVAS:
6396                         case MM_DISPLAY_SURFACE_GL:
6397                         case MM_DISPLAY_SURFACE_NULL:
6398                         case MM_DISPLAY_SURFACE_X_EXT:
6399                                 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE)
6400                                 {
6401                                         debug_error("failed to make plain text elements\n");
6402                                         goto ERROR;
6403                                 }
6404                                 break;
6405
6406                         default:
6407                                 break;
6408                 }
6409         }
6410         gst_object_unref(pad);
6411
6412         MMPLAYER_FLEAVE();
6413
6414         return MM_ERROR_NONE;
6415
6416 ERROR:
6417
6418         debug_log("ERROR : releasing textbin\n");
6419
6420         if ( pad )
6421                 gst_object_unref(GST_OBJECT(pad));
6422
6423         if ( ghostpad )
6424                 gst_object_unref(GST_OBJECT(ghostpad));
6425
6426         g_list_free( element_bucket );
6427
6428         /* release element which are not added to bin */
6429         for ( i = 1; i < MMPLAYER_T_NUM; i++ )  /* NOTE : skip bin */
6430         {
6431                 if ( textbin[i].gst )
6432                 {
6433                         GstObject* parent = NULL;
6434                         parent = gst_element_get_parent( textbin[i].gst );
6435
6436                         if ( !parent )
6437                         {
6438                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
6439                                 textbin[i].gst = NULL;
6440                         }
6441                         else
6442                         {
6443                                 gst_object_unref(GST_OBJECT(parent));
6444                         }
6445                 }
6446         }
6447
6448         /* release textbin with it's childs */
6449         if ( textbin[MMPLAYER_T_BIN].gst )
6450         {
6451                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
6452         }
6453
6454         MMPLAYER_FREEIF( textbin );
6455
6456         player->pipeline->textbin = NULL;
6457
6458         return MM_ERROR_PLAYER_INTERNAL;
6459 }
6460
6461
6462 static int
6463 __mmplayer_gst_create_subtitle_src(mm_player_t* player)
6464 {
6465         MMPlayerGstElement* mainbin = NULL;
6466         MMHandleType attrs = 0;
6467         GstElement *subsrc = NULL;
6468         GstElement *subparse = NULL;
6469         gchar *subtitle_uri =NULL;
6470         const gchar *charset = NULL;
6471         GstPad *sinkpad = NULL;
6472         GstPad *srcpad = NULL;
6473         GstPad *pad = NULL;
6474
6475         MMPLAYER_FENTER();
6476
6477         /* get mainbin */
6478         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
6479
6480         mainbin = player->pipeline->mainbin;
6481
6482         attrs = MMPLAYER_GET_ATTRS(player);
6483         if ( !attrs )
6484         {
6485                 debug_error("cannot get content attribute\n");
6486                 return MM_ERROR_PLAYER_INTERNAL;
6487         }
6488
6489         mm_attrs_get_string_by_name ( attrs, "subtitle_uri", &subtitle_uri );
6490         if ( !subtitle_uri || strlen(subtitle_uri) < 1)
6491         {
6492                 debug_error("subtitle uri is not proper filepath.\n");
6493                 return MM_ERROR_PLAYER_INVALID_URI;
6494         }
6495         debug_log("subtitle file path is [%s].\n", subtitle_uri);
6496
6497
6498         /* create the subtitle source */
6499         subsrc = gst_element_factory_make("filesrc", "subtitle_source");
6500         if ( !subsrc )
6501         {
6502                 debug_error ( "failed to create filesrc element\n" );
6503                 goto ERROR;
6504         }
6505         g_object_set(G_OBJECT (subsrc), "location", subtitle_uri, NULL);
6506
6507         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6508         mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
6509
6510         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc))
6511         {
6512                 debug_warning("failed to add queue\n");
6513                 goto ERROR;
6514         }
6515
6516         /* subparse */
6517         subparse = gst_element_factory_make("submux", "external-submux");
6518         if ( !subparse )
6519         {
6520                 debug_error ( "failed to create subparse element\n" );
6521                 goto ERROR;
6522         }
6523
6524         charset = util_get_charset(subtitle_uri);
6525         if (charset)
6526         {
6527                 debug_log ("detected charset is %s\n", charset );
6528                 g_object_set (G_OBJECT (subparse), "subtitle-encoding", charset, NULL);
6529         }
6530
6531         mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].id = MMPLAYER_M_T_SUBMUX_EXTERNAL;
6532         mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst = subparse;
6533
6534         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse))
6535         {
6536                 debug_warning("failed to add subparse\n");
6537                 goto ERROR;
6538         }
6539         sinkpad = gst_element_get_request_pad (subparse, "sink%d");
6540         srcpad =  gst_element_get_pad(subsrc,"src");
6541
6542         /* link filesrc & submux */
6543         if (gst_pad_link (srcpad, sinkpad) != 0)
6544         {
6545                 debug_warning("failed to link subsrc and subparse\n");
6546                 goto ERROR;
6547         }
6548
6549         player->play_subtitle = TRUE;
6550         player->adjust_subtitle_pos = 0;
6551
6552         debug_log ("play subtitle using subtitle file\n");
6553
6554         if (player->pipeline->textbin == NULL)
6555         {
6556                 /* if textbin is null, assuming input selector also not created */
6557                 GstElement *selector = NULL;
6558
6559                 /* input selector */
6560                 selector = gst_element_factory_make("input-selector", "subtitle_inselector");
6561                 if (!selector)
6562                 {
6563                         debug_error ( "failed to create subtitle input selector element\n" );
6564                         goto ERROR;
6565                 }
6566                 g_object_set (selector, "sync-streams", TRUE, NULL);
6567
6568                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
6569                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = selector;
6570
6571                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector))
6572                 {
6573                         debug_warning("failed to add subtitle input selector\n");
6574                         goto ERROR;
6575                 }
6576
6577                 if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
6578                 {
6579                         debug_error("failed to create textbin. continuing without text\n");
6580                         goto ERROR;
6581                 }
6582
6583                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst)))
6584                 {
6585                         debug_warning("failed to add textbin\n");
6586                         goto ERROR;
6587                 }
6588
6589                 debug_log ("link text input selector and textbin ghost pad");
6590                 if (!gst_element_link_pads (mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink"))
6591                 {
6592                         debug_warning("failed to link subparse and textbin\n");
6593                         goto ERROR;
6594                 }
6595
6596                 sinkpad = gst_element_get_request_pad (mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "sink%d");
6597                 if (sinkpad == NULL)
6598                 {
6599                         debug_error ("failed to get request pad");;
6600                         goto ERROR;
6601                 }
6602
6603                 debug_log ("Set Active Pad - %s\n", GST_DEBUG_PAD_NAME(sinkpad));
6604                 g_object_set (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "active-pad", sinkpad, NULL);
6605
6606                 player->textsink_linked  = 1;
6607                 player->external_text_idx = 0;
6608                 debug_msg("player->textsink_linked set to 1\n");
6609         }
6610         else
6611         {
6612                 debug_log("text bin has been created. reuse it.");
6613
6614                 sinkpad = gst_element_get_request_pad (mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "sink%d");
6615                 if (sinkpad == NULL)
6616                 {
6617                         debug_error ("failed to get request pad");;
6618                         goto ERROR;
6619                 }
6620
6621                 player->external_text_idx = 1;
6622         }
6623
6624         srcpad =  gst_element_get_pad (subparse,"src");
6625
6626         /* link submux & input selector */
6627         if (gst_pad_link (srcpad, sinkpad) != 0)
6628         {
6629                 debug_warning("failed to link submux and input selector\n");
6630                 goto ERROR;
6631         }
6632
6633         pad = gst_element_get_static_pad (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
6634
6635         if (!pad)
6636         {
6637                 debug_error("failed to get sink pad from textsink to probe data");
6638                 return MM_ERROR_PLAYER_INTERNAL;
6639         }
6640
6641         gst_pad_add_buffer_probe(pad, G_CALLBACK(__mmplayer_subtitle_adjust_position_probe), player);
6642         gst_object_unref(pad);
6643         pad=NULL;
6644
6645
6646         MMPLAYER_FLEAVE();
6647
6648         return MM_ERROR_NONE;
6649
6650 ERROR:
6651         return MM_ERROR_PLAYER_INTERNAL;
6652 }
6653
6654 gboolean
6655 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
6656 {
6657         mm_player_t* player = (mm_player_t*) data;
6658         MMMessageParamType msg = {0, };
6659         GstClockTime duration = 0;
6660         guint8 *text = NULL;
6661         guint text_size = 0;
6662         gboolean ret = TRUE;
6663
6664         MMPLAYER_FENTER();
6665
6666         return_val_if_fail ( player, FALSE );
6667         return_val_if_fail ( buffer, FALSE );
6668
6669         text = GST_BUFFER_DATA(buffer);
6670         text_size = GST_BUFFER_SIZE(buffer);
6671         duration = GST_BUFFER_DURATION(buffer);
6672
6673         if ( player->set_mode.subtitle_off )
6674         {
6675                 debug_log("subtitle is OFF.\n" );
6676                 return TRUE;
6677         }
6678
6679         if ( !text || (text_size == 0))
6680         {
6681                 debug_log("There is no subtitle to be displayed.\n" );
6682                 return TRUE;
6683         }
6684
6685         msg.data = (void *) text;
6686         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
6687
6688         debug_log("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
6689
6690         MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
6691
6692         MMPLAYER_FLEAVE();
6693
6694         return ret;
6695 }
6696
6697 static gboolean
6698 __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstBuffer *buffer, gpointer u_data)
6699 {
6700         mm_player_t *player = (mm_player_t *) u_data;
6701         GstClockTime cur_timestamp = 0;
6702         gint64 adjusted_timestamp = 0;
6703
6704         return_val_if_fail ( player, FALSE );
6705         return_val_if_fail ( buffer, FALSE );
6706
6707         if ( player->set_mode.subtitle_off )
6708         {
6709                 debug_log("subtitle is OFF.\n" );
6710                 return TRUE;
6711         }
6712
6713         if (player->adjust_subtitle_pos == 0 )
6714         {
6715                 debug_log("nothing to do");
6716                 return TRUE;
6717         }
6718
6719         cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
6720
6721         adjusted_timestamp = (gint64) cur_timestamp + ((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
6722
6723         if ( adjusted_timestamp < 0)
6724         {
6725                 debug_log("adjusted_timestamp under zero");
6726                 MMPLAYER_FLEAVE();
6727                 return FALSE;
6728         }
6729
6730         GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
6731         debug_log("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
6732                                 GST_TIME_ARGS(cur_timestamp),
6733                                 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
6734
6735         return TRUE;
6736 }
6737 static int      __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
6738 {
6739         MMPLAYER_FENTER();
6740
6741         /* check player and subtitlebin are created */
6742         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6743         return_val_if_fail ( player->play_subtitle, MM_ERROR_NOT_SUPPORT_API );
6744
6745         if (position == 0)
6746         {
6747                 debug_log ("nothing to do\n");
6748                 MMPLAYER_FLEAVE();
6749                 return MM_ERROR_NONE;
6750         }
6751
6752         switch (format)
6753         {
6754                 case MM_PLAYER_POS_FORMAT_TIME:
6755                 {
6756                         /* check current postion */
6757                         player->adjust_subtitle_pos = position;
6758
6759                         debug_log("save adjust_subtitle_pos in player") ;
6760                 }
6761                 break;
6762
6763                 default:
6764                 {
6765                         debug_warning("invalid format.\n");
6766                         MMPLAYER_FLEAVE();
6767                         return MM_ERROR_INVALID_ARGUMENT;
6768                 }
6769         }
6770
6771         MMPLAYER_FLEAVE();
6772
6773         return MM_ERROR_NONE;
6774 }
6775
6776 static void
6777 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data) // @
6778 {
6779         GstElement *appsrc = element;
6780         tBuffer *buf = (tBuffer *)user_data;
6781         GstBuffer *buffer = NULL;
6782         GstFlowReturn ret = GST_FLOW_OK;
6783         gint len = size;
6784
6785         return_if_fail ( element );
6786         return_if_fail ( buf );
6787
6788         buffer = gst_buffer_new ();
6789         if(buffer == NULL)
6790                 return;
6791
6792         if (buf->offset >= buf->len)
6793         {
6794                 debug_log("call eos appsrc\n");
6795                 g_signal_emit_by_name (appsrc, "end-of-stream", &ret);
6796                 return;
6797         }
6798
6799         if ( buf->len - buf->offset < size)
6800         {
6801                 len = buf->len - buf->offset + buf->offset;
6802         }
6803
6804         GST_BUFFER_DATA(buffer) = (guint8*)(buf->buf + buf->offset);
6805         GST_BUFFER_SIZE(buffer) = len;
6806         GST_BUFFER_OFFSET(buffer) = buf->offset;
6807         GST_BUFFER_OFFSET_END(buffer) = buf->offset + len;
6808
6809         //debug_log("feed buffer %p, offset %u-%u length %u\n", buffer, buf->offset, buf->len,len);
6810         g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
6811
6812         buf->offset += len;
6813 }
6814
6815 static gboolean
6816 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data) // @
6817 {
6818         tBuffer *buf = (tBuffer *)user_data;
6819
6820         return_val_if_fail ( buf, FALSE );
6821
6822         buf->offset  = (int)size;
6823
6824         return TRUE;
6825 }
6826
6827 static void
6828 __gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data) // @
6829 {
6830        mm_player_t *player  = (mm_player_t*)user_data;
6831
6832         return_if_fail ( player );
6833
6834         debug_msg("app-src: feed data\n");
6835
6836         if(player->need_data_cb)
6837                 player->need_data_cb(size, player->buffer_cb_user_param);
6838 }
6839
6840 static gboolean
6841 __gst_appsrc_seek_data(GstElement *element, guint64 offset, gpointer user_data) // @
6842 {
6843         mm_player_t *player  = (mm_player_t*)user_data;
6844
6845         return_val_if_fail ( player, FALSE );
6846
6847         debug_msg("app-src: seek data\n");
6848
6849         if(player->seek_data_cb)
6850                 player->seek_data_cb(offset, player->buffer_cb_user_param);
6851
6852         return TRUE;
6853 }
6854
6855
6856 static gboolean
6857 __gst_appsrc_enough_data(GstElement *element, gpointer user_data) // @
6858 {
6859         mm_player_t *player  = (mm_player_t*)user_data;
6860
6861         return_val_if_fail ( player, FALSE );
6862
6863         debug_msg("app-src: enough data:%p\n", player->enough_data_cb);
6864
6865         if(player->enough_data_cb)
6866                 player->enough_data_cb(player->buffer_cb_user_param);
6867
6868         return TRUE;
6869 }
6870
6871 int
6872 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
6873 {
6874         mm_player_t* player = (mm_player_t*)hplayer;
6875         GstBuffer *buffer = NULL;
6876         GstFlowReturn gst_ret = GST_FLOW_OK;
6877         int ret = MM_ERROR_NONE;
6878
6879         MMPLAYER_FENTER();
6880
6881         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6882
6883         /* check current state */
6884 //      MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
6885
6886
6887         /* NOTE : we should check and create pipeline again if not created as we destroy
6888          * whole pipeline when stopping in streamming playback
6889          */
6890         if ( ! player->pipeline )
6891         {
6892                 if ( MM_ERROR_NONE != __gst_realize( player ) )
6893                 {
6894                         debug_error("failed to realize before starting. only in streamming\n");
6895                         return MM_ERROR_PLAYER_INTERNAL;
6896                 }
6897         }
6898
6899         debug_msg("app-src: pushing data\n");
6900
6901         if ( buf == NULL )
6902         {
6903                 debug_error("buf is null\n");
6904                 return MM_ERROR_NONE;
6905         }
6906
6907         buffer = gst_buffer_new ();
6908         if(buffer == NULL)
6909                 return MM_ERROR_PLAYER_INTERNAL;
6910
6911         if (size <= 0)
6912         {
6913                 debug_log("call eos appsrc\n");
6914                 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
6915                 return MM_ERROR_NONE;
6916         }
6917
6918         GST_BUFFER_DATA(buffer) = (guint8*)(buf);
6919         GST_BUFFER_SIZE(buffer) = size;
6920
6921         debug_log("feed buffer %p, length %u\n", buf, size);
6922         g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
6923
6924         MMPLAYER_FLEAVE();
6925
6926         return ret;
6927 }
6928
6929 /* if retval is FALSE, it will be dropped for perfomance. */
6930 static gboolean
6931 __mmplayer_check_useful_message(mm_player_t *player, GstMessage * message)
6932 {
6933         gboolean retval = FALSE;
6934
6935         if ( !(player->pipeline && player->pipeline->mainbin) )
6936         {
6937                 debug_error("player pipeline handle is null");
6938                 return TRUE;
6939         }
6940
6941         switch (GST_MESSAGE_TYPE (message))
6942         {
6943                 case GST_MESSAGE_TAG:
6944                 case GST_MESSAGE_EOS:
6945                 case GST_MESSAGE_ERROR:
6946                 case GST_MESSAGE_WARNING:
6947                 case GST_MESSAGE_CLOCK_LOST:
6948                 case GST_MESSAGE_NEW_CLOCK:
6949                 case GST_MESSAGE_ELEMENT:
6950                 case GST_MESSAGE_DURATION:
6951                 case GST_MESSAGE_ASYNC_START:
6952                         retval = TRUE;
6953                         break;
6954                 case GST_MESSAGE_ASYNC_DONE:
6955                 case GST_MESSAGE_STATE_CHANGED:
6956                         /* we only handle messages from pipeline */
6957                         if(( message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst ) && (!player->pp_rebuilding))
6958                                 retval = TRUE;
6959                         else
6960                                 retval = FALSE;
6961                         break;
6962                 case GST_MESSAGE_BUFFERING:
6963                 {
6964                         gint buffer_percent = 0;
6965
6966                         gst_message_parse_buffering (message, &buffer_percent);
6967
6968                         if ((MMPLAYER_IS_STREAMING(player)) &&
6969                                 (player->streamer) &&
6970                                 (player->streamer->is_buffering == TRUE) &&
6971                                 (buffer_percent == MAX_BUFFER_PERCENT))
6972                         {
6973                                 debug_log (">>> [%s] Buffering DONE is detected !!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
6974                                 player->streamer->is_buffering_done = TRUE;
6975                         }
6976
6977                         retval = TRUE;
6978                         break;
6979                 }
6980                 default:
6981                         retval = FALSE;
6982                         break;
6983         }
6984
6985         return retval;
6986 }
6987
6988 static GstBusSyncReply
6989 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
6990 {
6991         mm_player_t *player = (mm_player_t *)data;
6992         GstBusSyncReply reply = GST_BUS_DROP;
6993
6994         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
6995         {
6996                 debug_error("player pipeline handle is null");
6997                 return GST_BUS_PASS;
6998         }
6999
7000         if (!__mmplayer_check_useful_message(player, message))
7001         {
7002                 gst_message_unref (message);
7003                 return GST_BUS_DROP;
7004         }
7005
7006         switch (GST_MESSAGE_TYPE (message))
7007         {
7008                 case GST_MESSAGE_STATE_CHANGED:
7009                         /* post directly for fast launch */
7010                         if (player->sync_handler) {
7011                                 __mmplayer_gst_callback(NULL, message, player);
7012                                 reply = GST_BUS_DROP;
7013                         }
7014                         else {
7015                                 reply = GST_BUS_PASS;
7016                         }
7017                         break;
7018                 case GST_MESSAGE_TAG:
7019                         __mmplayer_gst_extract_tag_from_msg(player, message);
7020                         break;
7021                 case GST_MESSAGE_DURATION:
7022                         __mmplayer_gst_handle_duration(player, message);
7023                         break;
7024                 case GST_MESSAGE_ASYNC_DONE:
7025                         /* NOTE:Don't call gst_callback directly
7026                          * because previous frame can be showed even though this message is received for seek.
7027                          */
7028                 default:
7029                         reply = GST_BUS_PASS;
7030                         break;
7031         }
7032
7033         if (reply == GST_BUS_DROP)
7034                 gst_message_unref (message);
7035
7036         return reply;
7037 }
7038
7039 /**
7040  * This function is to create  audio or video pipeline for playing.
7041  *
7042  * @param       player          [in]    handle of player
7043  *
7044  * @return      This function returns zero on success.
7045  * @remark
7046  * @see
7047  */
7048 static int
7049 __mmplayer_gst_create_pipeline(mm_player_t* player) // @
7050 {
7051         GstBus  *bus = NULL;
7052         MMPlayerGstElement *mainbin = NULL;
7053         MMHandleType attrs = 0;
7054         GstElement* element = NULL;
7055         GList* element_bucket = NULL;
7056         gboolean need_state_holder = TRUE;
7057         gint i = 0;
7058
7059         MMPLAYER_FENTER();
7060
7061         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7062
7063         /* get profile attribute */
7064         attrs = MMPLAYER_GET_ATTRS(player);
7065         if ( !attrs )
7066         {
7067                 debug_error("cannot get content attribute\n");
7068                 goto INIT_ERROR;
7069         }
7070
7071         /* create pipeline handles */
7072         if ( player->pipeline )
7073         {
7074                 debug_warning("pipeline should be released before create new one\n");
7075                 goto INIT_ERROR;
7076         }
7077
7078         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0( sizeof(MMPlayerGstPipelineInfo) );
7079         if (player->pipeline == NULL)
7080                 goto INIT_ERROR;
7081
7082         memset( player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo) );
7083
7084
7085         /* create mainbin */
7086         mainbin = (MMPlayerGstElement*) g_malloc0( sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM );
7087         if (mainbin == NULL)
7088                 goto INIT_ERROR;
7089
7090         memset( mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
7091
7092         /* create pipeline */
7093         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
7094         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
7095         if ( ! mainbin[MMPLAYER_M_PIPE].gst )
7096         {
7097                 debug_error("failed to create pipeline\n");
7098                 goto INIT_ERROR;
7099         }
7100         player->demux_pad_index = 0;
7101         player->subtitle_language_list = NULL;
7102
7103         player->font_color = player->ini.font_color;
7104         player->font_bg_color = player->ini.font_background_color;
7105
7106         player->display_stat = MMPLAYER_DISPLAY_STATUS_NULL;
7107         player->is_subtitle_force_drop = FALSE;
7108         player->last_multiwin_status = FALSE;
7109
7110         /* create source element */
7111         switch ( player->profile.uri_type )
7112         {
7113                 /* rtsp streamming */
7114                 case MM_PLAYER_URI_TYPE_URL_RTSP:
7115                 {
7116                         gint network_bandwidth;
7117                         gchar *user_agent, *wap_profile;
7118
7119                         element = gst_element_factory_make(player->ini.name_of_rtspsrc, "streaming_source");
7120
7121                         if ( !element )
7122                         {
7123                                 debug_error("failed to create streaming source element\n");
7124                                 break;
7125                         }
7126
7127                         debug_log("using streamming source [%s].\n", player->ini.name_of_rtspsrc);
7128
7129                         /* make it zero */
7130                         network_bandwidth = 0;
7131                         user_agent = wap_profile = NULL;
7132
7133                         /* get attribute */
7134                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
7135                         mm_attrs_get_string_by_name ( attrs,"streaming_wap_profile", &wap_profile );
7136                         mm_attrs_get_int_by_name ( attrs, "streaming_network_bandwidth", &network_bandwidth );
7137
7138                         secure_debug_log("user_agent : %s\n", user_agent);
7139                         secure_debug_log("wap_profile : %s\n", wap_profile);
7140                         debug_log("network_bandwidth : %d\n", network_bandwidth);
7141                         debug_log("buffering time : %d\n", player->ini.rtsp_buffering_time);
7142                         debug_log("rebuffering time : %d\n", player->ini.rtsp_rebuffering_time);
7143
7144                         /* setting property to streaming source */
7145                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7146                         g_object_set(G_OBJECT(element), "bandwidth", network_bandwidth, NULL);
7147                         g_object_set(G_OBJECT(element), "buffering_time", player->ini.rtsp_buffering_time, NULL);
7148                         g_object_set(G_OBJECT(element), "rebuffering_time", player->ini.rtsp_rebuffering_time, NULL);
7149                         if ( user_agent )
7150                                 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
7151                         if ( wap_profile )
7152                                 g_object_set(G_OBJECT(element), "wap_profile", wap_profile, NULL);
7153
7154                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7155                                 G_CALLBACK (__mmplayer_gst_rtp_dynamic_pad), player );
7156                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
7157                                 G_CALLBACK (__mmplayer_gst_rtp_no_more_pads), player );
7158
7159                         player->use_decodebin = FALSE;
7160                 }
7161                 break;
7162
7163                 /* WFD streamming */
7164                 case MM_PLAYER_URI_TYPE_URL_WFD:
7165                 {
7166                         element = gst_element_factory_make("wfdrtspsrc", "wfd_source");
7167                         if ( !element )
7168                         {
7169                                 debug_error("failed to create wfd streaming source element\n");
7170                                 break;
7171                         }
7172                         debug_log("using wfd streamming source wfdrtspsrc.\n");
7173                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7174                         g_object_set(G_OBJECT(element), "debug", TRUE, NULL);
7175                         g_object_set(G_OBJECT(element), "latency", 0, NULL);
7176                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7177                                G_CALLBACK (__mmplayer_gst_wfd_dynamic_pad), player );
7178
7179                         player->use_decodebin = FALSE;
7180                 }
7181                 break;
7182
7183                 /* http streaming*/
7184                 case MM_PLAYER_URI_TYPE_URL_HTTP:
7185                 {
7186                         gchar *user_agent, *proxy, *cookies, **cookie_list;
7187                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
7188                         user_agent = proxy = cookies = NULL;
7189                         cookie_list = NULL;
7190                         gint mode = MM_PLAYER_PD_MODE_NONE;
7191
7192                         mm_attrs_get_int_by_name ( attrs, "pd_mode", &mode );
7193
7194                         player->pd_mode = mode;
7195
7196                         debug_log("http playback, PD mode : %d\n", player->pd_mode);
7197
7198                         if ( ! MMPLAYER_IS_HTTP_PD(player) )
7199                         {
7200                                 element = gst_element_factory_make(player->ini.name_of_httpsrc, "http_streaming_source");
7201                                 if ( !element )
7202                                 {
7203                                         debug_error("failed to create http streaming source element[%s].\n", player->ini.name_of_httpsrc);
7204                                         break;
7205                                 }
7206                                 debug_log("using http streamming source [%s].\n", player->ini.name_of_httpsrc);
7207
7208                                 /* get attribute */
7209                                 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
7210                                 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
7211                                 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
7212                                 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
7213
7214                                 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
7215                                         (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
7216                                 {
7217                                         debug_log("get timeout from ini\n");
7218                                         http_timeout = player->ini.http_timeout;
7219                                 }
7220
7221                                 /* get attribute */
7222                                 secure_debug_log("location : %s\n", player->profile.uri);
7223                                 secure_debug_log("cookies : %s\n", cookies);
7224                                 secure_debug_log("proxy : %s\n", proxy);
7225                                 secure_debug_log("user_agent :  %s\n",  user_agent);
7226                                 debug_log("timeout : %d\n",  http_timeout);
7227
7228                                 /* setting property to streaming source */
7229                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7230                                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
7231                                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
7232
7233                                 /* check if prosy is vailid or not */
7234                                 if ( util_check_valid_url ( proxy ) )
7235                                         g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
7236                                 /* parsing cookies */
7237                                 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
7238                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
7239                                 if ( user_agent )
7240                                         g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
7241
7242                                 if ( MMPLAYER_URL_HAS_DASH_SUFFIX(player) )
7243                                 {
7244                                         debug_warning("it's dash. and it's still experimental feature.");
7245                                 }
7246                                 else if (MMPLAYER_URL_HAS_HLS_SUFFIX(player) )
7247                                 {
7248                                         debug_warning("it's hls. using decodebin");
7249                                 }
7250                         }
7251                         else // progressive download
7252                         {
7253                                 gchar* location = NULL;
7254
7255                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
7256                                 {
7257                                         gchar *path = NULL;
7258
7259                                         mm_attrs_get_string_by_name ( attrs, "pd_location", &path );
7260
7261                                         MMPLAYER_FREEIF(player->pd_file_save_path);
7262
7263                                         debug_log("PD Location : %s\n", path);
7264
7265                                         if ( path )
7266                                         {
7267                                                 player->pd_file_save_path = g_strdup(path);
7268                                         }
7269                                         else
7270                                         {
7271                                                 debug_error("can't find pd location so, it should be set \n");
7272                                                 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
7273                                         }
7274                                 }
7275
7276                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
7277                                 if ( !element )
7278                                 {
7279                                         debug_error("failed to create PD push source element[%s].\n", "pdpushsrc");
7280                                         break;
7281                                 }
7282
7283                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
7284                                         g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
7285                                 else
7286                                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7287
7288                                 g_object_get(element, "location", &location, NULL);
7289                                 debug_log("PD_LOCATION [%s].\n", location);
7290                                 if (location)
7291                                         g_free (location);
7292                         }
7293                 }
7294                 break;
7295
7296                 /* file source */
7297                 case MM_PLAYER_URI_TYPE_FILE:
7298                 {
7299
7300 #ifdef ENABLE_DRMSRC
7301
7302                         char* drmsrc = player->ini.name_of_drmsrc;
7303
7304                         debug_log("using [%s] for 'file://' handler.\n", drmsrc);
7305
7306                         element = gst_element_factory_make(drmsrc, "source");
7307                         if ( !element )
7308                         {
7309                                 debug_error("failed to create %s\n", drmsrc);
7310                                 break;
7311                         }
7312 #else
7313                         debug_log("using filesrc for 'file://' handler.\n");
7314
7315                         element = gst_element_factory_make("filesrc", "source");
7316
7317                         if ( !element )
7318                         {
7319                                 debug_error("failed to create filesrc\n");
7320                                 break;
7321                         }
7322 #endif
7323                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
7324                         //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL);
7325                 }
7326                 break;
7327
7328                 case MM_PLAYER_URI_TYPE_SS:
7329                 {
7330                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
7331                         element = gst_element_factory_make("souphttpsrc", "http streaming source");
7332                         if ( !element )
7333                         {
7334                                 debug_error("failed to create http streaming source element[%s]", player->ini.name_of_httpsrc);
7335                                 break;
7336                         }
7337
7338                         mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
7339
7340                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
7341                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
7342                         {
7343                                 debug_log("get timeout from ini\n");
7344                                 http_timeout = player->ini.http_timeout;
7345                         }
7346
7347                         /* setting property to streaming source */
7348                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7349                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
7350                 }
7351                 break;
7352
7353                 /* appsrc */
7354                 case MM_PLAYER_URI_TYPE_BUFF:
7355                 {
7356                         guint64 stream_type = GST_APP_STREAM_TYPE_STREAM;
7357
7358                         debug_log("mem src is selected\n");
7359
7360                         element = gst_element_factory_make("appsrc", "buff-source");
7361                         if ( !element )
7362                         {
7363                                 debug_error("failed to create appsrc element\n");
7364                                 break;
7365                         }
7366
7367                         g_object_set( element, "stream-type", stream_type, NULL );
7368                         //g_object_set( element, "size", player->mem_buf.len, NULL );
7369                         //g_object_set( element, "blocksize", (guint64)20480, NULL );
7370
7371                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7372                                 G_CALLBACK(__gst_appsrc_seek_data), player);
7373                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7374                                 G_CALLBACK(__gst_appsrc_feed_data), player);
7375                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7376                                 G_CALLBACK(__gst_appsrc_enough_data), player);
7377                 }
7378                 break;
7379
7380                 /* appsrc */
7381                 case MM_PLAYER_URI_TYPE_MEM:
7382                 {
7383                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
7384
7385                         debug_log("mem src is selected\n");
7386
7387                         element = gst_element_factory_make("appsrc", "mem-source");
7388                         if ( !element )
7389                         {
7390                                 debug_error("failed to create appsrc element\n");
7391                                 break;
7392                         }
7393
7394                         g_object_set( element, "stream-type", stream_type, NULL );
7395                         g_object_set( element, "size", player->mem_buf.len, NULL );
7396                         g_object_set( element, "blocksize", (guint64)20480, NULL );
7397
7398                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7399                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->mem_buf );
7400                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7401                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->mem_buf );
7402                 }
7403                 break;
7404                 case MM_PLAYER_URI_TYPE_URL:
7405                 break;
7406
7407                 case MM_PLAYER_URI_TYPE_TEMP:
7408                 break;
7409
7410                 case MM_PLAYER_URI_TYPE_NONE:
7411                 default:
7412                 break;
7413         }
7414
7415         /* check source element is OK */
7416         if ( ! element )
7417         {
7418                 debug_error("no source element was created.\n");
7419                 goto INIT_ERROR;
7420         }
7421
7422         /* take source element */
7423         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
7424         mainbin[MMPLAYER_M_SRC].gst = element;
7425         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
7426
7427         if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL))
7428         {
7429                 player->streamer = __mm_player_streaming_create();
7430                 __mm_player_streaming_initialize(player->streamer);
7431         }
7432
7433         if ( MMPLAYER_IS_HTTP_PD(player) )
7434         {
7435                 gdouble pre_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
7436
7437                 debug_log ("Picked queue2 element(pre buffer : %d sec)....\n", pre_buffering_time);
7438                 element = gst_element_factory_make("queue2", "queue2");
7439                 if ( !element )
7440                 {
7441                         debug_error ( "failed to create http streaming buffer element\n" );
7442                         goto INIT_ERROR;
7443                 }
7444
7445                 /* take it */
7446                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
7447                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
7448                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
7449
7450                 pre_buffering_time = (pre_buffering_time > 0)?(pre_buffering_time):(player->ini.http_buffering_time);
7451
7452                 __mm_player_streaming_set_queue2(player->streamer,
7453                                 element,
7454                                 TRUE,
7455                                 player->ini.http_max_size_bytes,
7456                                 pre_buffering_time,
7457                                 1.0,
7458                                 player->ini.http_buffering_limit,
7459                                 FALSE,
7460                                 NULL,
7461                                 0);
7462         }
7463
7464         /* create autoplugging element if src element is not a rtsp src */
7465         if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
7466                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_WFD))
7467         {
7468                 element = NULL;
7469                 enum MainElementID elemId = MMPLAYER_M_NUM;
7470
7471                 if ((player->use_decodebin) &&
7472                         ((MMPLAYER_IS_HTTP_PD(player)) ||
7473                          (!MMPLAYER_IS_HTTP_STREAMING(player))))
7474                 {
7475                         elemId = MMPLAYER_M_AUTOPLUG;
7476                         element = __mmplayer_create_decodebin(player);
7477                         need_state_holder = FALSE;
7478                 }
7479                 else
7480                 {
7481                         elemId = MMPLAYER_M_TYPEFIND;
7482                         element = gst_element_factory_make("typefind", "typefinder");
7483                         MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
7484                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
7485                 }
7486
7487
7488                 /* check autoplug element is OK */
7489                 if ( ! element )
7490                 {
7491                         debug_error("can not create element (%d)\n", elemId);
7492                         goto INIT_ERROR;
7493                 }
7494
7495                 mainbin[elemId].id = elemId;
7496                 mainbin[elemId].gst = element;
7497
7498                 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
7499         }
7500
7501         /* add elements to pipeline */
7502         if( !__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket))
7503         {
7504                 debug_error("Failed to add elements to pipeline\n");
7505                 goto INIT_ERROR;
7506         }
7507
7508
7509         /* linking elements in the bucket by added order. */
7510         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
7511         {
7512                 debug_error("Failed to link some elements\n");
7513                 goto INIT_ERROR;
7514         }
7515
7516
7517         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
7518         if ( need_state_holder )
7519         {
7520                 /* create */
7521                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
7522                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make ("fakesink", "state-holder");
7523
7524                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
7525                 {
7526                         debug_error ("fakesink element could not be created\n");
7527                         goto INIT_ERROR;
7528                 }
7529                 GST_OBJECT_FLAG_UNSET (mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_IS_SINK);
7530
7531                 /* take ownership of fakesink. we are reusing it */
7532                 gst_object_ref( mainbin[MMPLAYER_M_SRC_FAKESINK].gst );
7533
7534                 /* add */
7535                 if ( FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
7536                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst) )
7537                 {
7538                         debug_error("failed to add fakesink to bin\n");
7539                         goto INIT_ERROR;
7540                 }
7541         }
7542
7543         /* now we have completed mainbin. take it */
7544         player->pipeline->mainbin = mainbin;
7545
7546         /* connect bus callback */
7547         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
7548         if ( !bus )
7549         {
7550                 debug_error ("cannot get bus from pipeline.\n");
7551                 goto INIT_ERROR;
7552         }
7553
7554         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
7555
7556         player->context.thread_default = g_main_context_get_thread_default();
7557
7558         if (NULL == player->context.thread_default)
7559         {
7560                 player->context.thread_default = g_main_context_default();
7561                 debug_log("thread-default context is the global default context");
7562         }
7563         debug_warning("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
7564
7565         /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
7566         if ( __mmplayer_check_subtitle ( player ) )
7567         {
7568                 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
7569                         debug_error("fail to create subtitle src\n");
7570         }
7571
7572         /* set sync handler to get tag synchronously */
7573         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player);
7574
7575         /* finished */
7576         gst_object_unref(GST_OBJECT(bus));
7577         g_list_free(element_bucket);
7578
7579         MMPLAYER_FLEAVE();
7580
7581         return MM_ERROR_NONE;
7582
7583 INIT_ERROR:
7584
7585         __mmplayer_gst_destroy_pipeline(player);
7586         g_list_free(element_bucket);
7587
7588         /* release element which are not added to bin */
7589         for ( i = 1; i < MMPLAYER_M_NUM; i++ )  /* NOTE : skip pipeline */
7590         {
7591                 if ( mainbin[i].gst )
7592                 {
7593                         GstObject* parent = NULL;
7594                         parent = gst_element_get_parent( mainbin[i].gst );
7595
7596                         if ( !parent )
7597                         {
7598                                 gst_object_unref(GST_OBJECT(mainbin[i].gst));
7599                                 mainbin[i].gst = NULL;
7600                         }
7601                         else
7602                         {
7603                                 gst_object_unref(GST_OBJECT(parent));
7604                         }
7605                 }
7606         }
7607
7608         /* release pipeline with it's childs */
7609         if ( mainbin[MMPLAYER_M_PIPE].gst )
7610         {
7611                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7612         }
7613
7614         MMPLAYER_FREEIF( player->pipeline );
7615         MMPLAYER_FREEIF( mainbin );
7616
7617         return MM_ERROR_PLAYER_INTERNAL;
7618 }
7619
7620 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
7621 {
7622         GSource *source = NULL;
7623
7624         MMPLAYER_FENTER();
7625
7626         source = g_main_context_find_source_by_id (context, source_id);
7627
7628         if (source != NULL)
7629         {
7630                 debug_warning("context: %p, source id: %d, source: %p", context, source_id, source);
7631                 g_source_destroy(source);
7632         }
7633
7634         MMPLAYER_FLEAVE();
7635 }
7636
7637 static int
7638 __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
7639 {
7640         gint timeout = 0;
7641         int ret = MM_ERROR_NONE;
7642
7643         MMPLAYER_FENTER();
7644
7645         return_val_if_fail ( player, MM_ERROR_INVALID_HANDLE );
7646
7647         /* cleanup stuffs */
7648         MMPLAYER_FREEIF(player->type);
7649         player->have_dynamic_pad = FALSE;
7650         player->no_more_pad = FALSE;
7651         player->num_dynamic_pad = 0;
7652         player->demux_pad_index = 0;
7653         player->subtitle_language_list = NULL;
7654         player->use_deinterleave = FALSE;
7655         player->pp_rebuilding = FALSE;
7656         player->max_audio_channels = 0;
7657         player->video_share_api_delta = 0;
7658         player->video_share_clock_delta = 0;
7659         player->video_hub_download_mode = 0;
7660
7661         MMPLAYER_FREEIF(player->font_desc);
7662         player->font_color = 0;
7663         player->font_bg_color = 0;
7664
7665         __mmplayer_post_proc_reset(player);
7666
7667         if (player->streamer)
7668         {
7669                 __mm_player_streaming_deinitialize (player->streamer);
7670                 __mm_player_streaming_destroy(player->streamer);
7671                 player->streamer = NULL;
7672         }
7673
7674         /* cleanup unlinked mime type */
7675         MMPLAYER_FREEIF(player->unlinked_audio_mime);
7676         MMPLAYER_FREEIF(player->unlinked_video_mime);
7677         MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
7678
7679         /* cleanup running stuffs */
7680         __mmplayer_cancel_eos_timer( player );
7681
7682         /* remove sound cb */
7683         if ( MM_ERROR_NONE != mm_sound_remove_active_device_changed_callback(MM_PLAYER_NAME))
7684         {
7685                 debug_error("failed to mm_sound_remove_active_device_changed_callback");
7686         }
7687
7688         /* cleanup gst stuffs */
7689         if ( player->pipeline )
7690         {
7691                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
7692                 GstTagList* tag_list = player->pipeline->tag_list;
7693
7694                 /* first we need to disconnect all signal hander */
7695                 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_ALL );
7696
7697                 /* disconnecting bus watch */
7698                 if ( player->bus_watcher )
7699                         __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
7700                 player->bus_watcher = 0;
7701
7702                 if ( mainbin )
7703                 {
7704                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
7705                         MMPlayerGstElement* videobin = player->pipeline->videobin;
7706                         MMPlayerGstElement* textbin = player->pipeline->textbin;
7707                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mainbin[MMPLAYER_M_PIPE].gst));
7708                         gst_bus_set_sync_handler (bus, NULL, NULL);
7709                         gst_object_unref(bus);
7710
7711                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7712                         ret = __mmplayer_gst_set_state ( player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout );
7713                         if ( ret != MM_ERROR_NONE )
7714                         {
7715                                 debug_error("fail to change state to NULL\n");
7716                                 return MM_ERROR_PLAYER_INTERNAL;
7717                         }
7718
7719                         debug_warning("succeeded in chaning state to NULL\n");
7720
7721                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7722
7723                         /* free fakesink */
7724                         if ( mainbin[MMPLAYER_M_SRC_FAKESINK].gst )
7725                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
7726
7727                         /* free avsysaudiosink
7728                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
7729                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
7730                         */
7731                         MMPLAYER_FREEIF( audiobin );
7732                         MMPLAYER_FREEIF( videobin );
7733                         MMPLAYER_FREEIF( textbin );
7734                         MMPLAYER_FREEIF( mainbin );
7735                 }
7736
7737                 if ( tag_list )
7738                         gst_tag_list_free(tag_list);
7739
7740                 MMPLAYER_FREEIF( player->pipeline );
7741         }
7742         MMPLAYER_FREEIF(player->album_art);
7743
7744         if (player->v_stream_caps)
7745         {
7746                 gst_caps_unref(player->v_stream_caps);
7747                 player->v_stream_caps = NULL;
7748         }
7749
7750         if ( player->sink_elements )
7751                 g_list_free ( player->sink_elements );
7752         player->sink_elements = NULL;
7753
7754         debug_warning("finished destroy pipeline\n");
7755
7756         MMPLAYER_FLEAVE();
7757
7758         return ret;
7759 }
7760
7761 static int __gst_realize(mm_player_t* player) // @
7762 {
7763         gint timeout = 0;
7764         int ret = MM_ERROR_NONE;
7765
7766         MMPLAYER_FENTER();
7767
7768         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7769
7770         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7771
7772         ret = __mmplayer_gst_create_pipeline(player);
7773         if ( ret )
7774         {
7775                 debug_error("failed to create pipeline\n");
7776                 return ret;
7777         }
7778
7779         /* set pipeline state to READY */
7780         /* NOTE : state change to READY must be performed sync. */
7781         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7782         ret = __mmplayer_gst_set_state(player,
7783                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
7784
7785         if ( ret != MM_ERROR_NONE )
7786         {
7787                 /* return error if failed to set state */
7788                 debug_error("failed to set READY state");
7789                 return ret;
7790         }
7791         else
7792         {
7793                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
7794         }
7795
7796         /* create dot before error-return. for debugging */
7797         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-realize" );
7798
7799         MMPLAYER_FLEAVE();
7800
7801         return ret;
7802 }
7803
7804 static int __gst_unrealize(mm_player_t* player) // @
7805 {
7806         int ret = MM_ERROR_NONE;
7807
7808         MMPLAYER_FENTER();
7809
7810         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7811
7812         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
7813         MMPLAYER_PRINT_STATE(player);
7814
7815         /* release miscellaneous information */
7816         __mmplayer_release_misc( player );
7817
7818         /* destroy pipeline */
7819         ret = __mmplayer_gst_destroy_pipeline( player );
7820         if ( ret != MM_ERROR_NONE )
7821         {
7822                 debug_error("failed to destory pipeline\n");
7823                 return ret;
7824         }
7825
7826         /* release miscellaneous information.
7827            these info needs to be released after pipeline is destroyed. */
7828         __mmplayer_release_misc_post( player );
7829
7830         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
7831
7832         MMPLAYER_FLEAVE();
7833
7834         return ret;
7835 }
7836
7837 static int __gst_pending_seek ( mm_player_t* player )
7838 {
7839         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7840         int ret = MM_ERROR_NONE;
7841
7842         MMPLAYER_FENTER();
7843
7844         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7845
7846         if ( !player->pending_seek.is_pending )
7847         {
7848                 debug_log("pending seek is not reserved. nothing to do.\n" );
7849                 return ret;
7850         }
7851
7852         /* check player state if player could pending seek or not. */
7853         current_state = MMPLAYER_CURRENT_STATE(player);
7854
7855         if ( current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING  )
7856         {
7857                 debug_warning("try to pending seek in %s state, try next time. \n",
7858                         MMPLAYER_STATE_GET_NAME(current_state));
7859                 return ret;
7860         }
7861
7862         debug_log("trying to play from (%lu) pending position\n", player->pending_seek.pos);
7863
7864         ret = __gst_set_position ( player, player->pending_seek.format, player->pending_seek.pos, FALSE );
7865
7866         if ( MM_ERROR_NONE != ret )
7867                 debug_error("failed to seek pending postion. just keep staying current position.\n");
7868
7869         player->pending_seek.is_pending = FALSE;
7870
7871         MMPLAYER_FLEAVE();
7872
7873         return ret;
7874 }
7875
7876 static int __gst_start(mm_player_t* player) // @
7877 {
7878         gboolean sound_extraction = 0;
7879         int ret = MM_ERROR_NONE;
7880
7881         MMPLAYER_FENTER();
7882
7883         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7884
7885         /* get sound_extraction property */
7886         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
7887
7888         /* NOTE : if SetPosition was called before Start. do it now */
7889         /* streaming doesn't support it. so it should be always sync */
7890         /* !! create one more api to check if there is pending seek rather than checking variables */
7891         if ( (player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player))
7892         {
7893                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
7894                 ret = __gst_pause(player, FALSE);
7895                 if ( ret != MM_ERROR_NONE )
7896                 {
7897                         debug_error("failed to set state to PAUSED for pending seek\n");
7898                         return ret;
7899                 }
7900
7901                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
7902
7903                 if ( sound_extraction )
7904                 {
7905                         debug_log("setting pcm extraction\n");
7906
7907                         ret = __mmplayer_set_pcm_extraction(player);
7908                         if ( MM_ERROR_NONE != ret )
7909                         {
7910                                 debug_warning("failed to set pcm extraction\n");
7911                                 return ret;
7912                         }
7913                 }
7914                 else
7915                 {
7916                         if ( MM_ERROR_NONE != __gst_pending_seek(player) )
7917                         {
7918                                 debug_warning("failed to seek pending postion. starting from the begin of content.\n");
7919                         }
7920                 }
7921         }
7922
7923         debug_log("current state before doing transition");
7924         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7925         MMPLAYER_PRINT_STATE(player);
7926
7927         /* set pipeline state to PLAYING  */
7928         ret = __mmplayer_gst_set_state(player,
7929                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
7930         if (ret == MM_ERROR_NONE)
7931         {
7932                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7933         }
7934         else
7935         {
7936                 debug_error("failed to set state to PLAYING");
7937                 return ret;
7938         }
7939
7940         /* generating debug info before returning error */
7941         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-start" );
7942
7943         MMPLAYER_FLEAVE();
7944
7945         return ret;
7946 }
7947
7948 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
7949 {
7950         MMPLAYER_FENTER();
7951
7952         return_if_fail(player
7953                 && player->pipeline
7954                 && player->pipeline->audiobin
7955                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
7956
7957         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
7958
7959         usleep(time);
7960
7961         MMPLAYER_FLEAVE();
7962 }
7963
7964 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
7965 {
7966         MMPLAYER_FENTER();
7967
7968         return_if_fail(player
7969                 && player->pipeline
7970                 && player->pipeline->audiobin
7971                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
7972
7973         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
7974
7975         MMPLAYER_FLEAVE();
7976 }
7977
7978 static int __gst_stop(mm_player_t* player) // @
7979 {
7980         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
7981         MMHandleType attrs = 0;
7982         gboolean fadedown = FALSE;
7983         gboolean rewind = FALSE;
7984         gint timeout = 0;
7985         int ret = MM_ERROR_NONE;
7986         GstState state;
7987
7988         MMPLAYER_FENTER();
7989
7990         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7991         return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7992
7993         debug_log("current state before doing transition");
7994         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7995         MMPLAYER_PRINT_STATE(player);
7996
7997         attrs = MMPLAYER_GET_ATTRS(player);
7998         if ( !attrs )
7999         {
8000                 debug_error("cannot get content attribute\n");
8001                 return MM_ERROR_PLAYER_INTERNAL;
8002         }
8003
8004         mm_attrs_get_int_by_name(attrs, "sound_fadedown", &fadedown);
8005
8006         /* enable fadedown */
8007         if (fadedown || player->sm.by_asm_cb)
8008                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8009
8010         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
8011         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
8012
8013         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_BUFF ||
8014                 player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS)
8015         {
8016                 state = GST_STATE_READY;
8017         }
8018         else
8019         {
8020                 state = GST_STATE_PAUSED;
8021
8022                 if ( ! MMPLAYER_IS_STREAMING(player) ||
8023                         (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked)) {
8024                         rewind = TRUE;
8025                 }
8026         }
8027
8028         /* set gst state */
8029         ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, FALSE, timeout );
8030
8031         /* disable fadeout */
8032         if (fadedown || player->sm.by_asm_cb)
8033                 __mmplayer_undo_sound_fadedown(player);
8034
8035         /* return if set_state has failed */
8036         if ( ret != MM_ERROR_NONE )
8037         {
8038                 debug_error("failed to set state.\n");
8039                 return ret;
8040         }
8041
8042         /* rewind */
8043         if ( rewind )
8044         {
8045                 if ( ! __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8046                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
8047                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE) )
8048                 {
8049                         debug_warning("failed to rewind\n");
8050                         ret = MM_ERROR_PLAYER_SEEK;
8051                 }
8052         }
8053
8054         /* initialize */
8055         player->sent_bos = FALSE;
8056
8057         /* wait for seek to complete */
8058         change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
8059         if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL )
8060         {
8061                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
8062         }
8063         else
8064         {
8065                 debug_error("fail to stop player.\n");
8066                 ret = MM_ERROR_PLAYER_INTERNAL;
8067                 __mmplayer_dump_pipeline_state(player);
8068         }
8069
8070         /* generate dot file if enabled */
8071         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-stop" );
8072
8073         MMPLAYER_FLEAVE();
8074
8075         return ret;
8076 }
8077
8078 int __gst_pause(mm_player_t* player, gboolean async) // @
8079 {
8080         int ret = MM_ERROR_NONE;
8081
8082         MMPLAYER_FENTER();
8083
8084         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
8085         return_val_if_fail(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
8086
8087         debug_log("current state before doing transition");
8088         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
8089         MMPLAYER_PRINT_STATE(player);
8090
8091         /* set pipeline status to PAUSED */
8092         player->ignore_asyncdone = TRUE;
8093
8094         ret = __mmplayer_gst_set_state(player,
8095                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
8096
8097         player->ignore_asyncdone = FALSE;
8098
8099         if ( FALSE == async )
8100         {
8101                 if ( ret != MM_ERROR_NONE )
8102                 {
8103                         GstMessage *msg = NULL;
8104                         GTimer *timer = NULL;
8105                         gdouble MAX_TIMEOUT_SEC = 3;
8106
8107                         debug_error("failed to set state to PAUSED");
8108
8109                         timer = g_timer_new();
8110                         g_timer_start(timer);
8111
8112                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
8113                         gboolean got_msg = FALSE;
8114                         /* check if gst error posted or not */
8115                         do
8116                         {
8117                                 msg = gst_bus_timed_pop(bus, GST_SECOND /2);
8118                                 if (msg)
8119                                 {
8120                                         if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR)
8121                                         {
8122                                                 GError *error = NULL;
8123
8124                                                 /* parse error code */
8125                                                 gst_message_parse_error(msg, &error, NULL);
8126
8127                                                 if ( gst_structure_has_name ( msg->structure, "streaming_error" ) )
8128                                                 {
8129                                                         /* Note : the streaming error from the streaming source is handled
8130                                                          *   using __mmplayer_handle_streaming_error.
8131                                                          */
8132                                                         __mmplayer_handle_streaming_error ( player, msg );
8133
8134                                                 }
8135                                                 else if (error)
8136                                                 {
8137                                                         debug_error("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
8138
8139                                                         if (error->domain == GST_STREAM_ERROR)
8140                                                         {
8141                                                                 ret = __gst_handle_stream_error( player, error, msg );
8142                                                         }
8143                                                         else if (error->domain == GST_RESOURCE_ERROR)
8144                                                         {
8145                                                                 ret = __gst_handle_resource_error( player, error->code );
8146                                                         }
8147                                                         else if (error->domain == GST_LIBRARY_ERROR)
8148                                                         {
8149                                                                 ret = __gst_handle_library_error( player, error->code );
8150                                                         }
8151                                                         else if (error->domain == GST_CORE_ERROR)
8152                                                         {
8153                                                                 ret = __gst_handle_core_error( player, error->code );
8154                                                         }
8155                                                 }
8156
8157                                                 got_msg = TRUE;
8158                                                 player->msg_posted = TRUE;
8159                                         }
8160                                         gst_message_unref(msg);
8161                                 }
8162                         } while (!got_msg && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
8163                         /* clean */
8164                         gst_object_unref(bus);
8165                         g_timer_stop (timer);
8166                         g_timer_destroy (timer);
8167
8168                         return ret;
8169                 }
8170                 else if ( (!player->pipeline->videobin) && (!player->pipeline->audiobin) )
8171                 {
8172                         if (MMPLAYER_IS_RTSP_STREAMING(player))
8173                                 return ret;
8174                         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
8175                 }
8176                 else if ( ret== MM_ERROR_NONE)
8177                 {
8178                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
8179                 }
8180         }
8181
8182         /* generate dot file before returning error */
8183         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-pause" );
8184
8185         MMPLAYER_FLEAVE();
8186
8187         return ret;
8188 }
8189
8190 int __gst_resume(mm_player_t* player, gboolean async) // @
8191 {
8192         int ret = MM_ERROR_NONE;
8193         gint timeout = 0;
8194
8195         MMPLAYER_FENTER();
8196
8197         return_val_if_fail(player && player->pipeline,
8198                 MM_ERROR_PLAYER_NOT_INITIALIZED);
8199
8200         debug_log("current state before doing transition");
8201         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
8202         MMPLAYER_PRINT_STATE(player);
8203
8204         /* generate dot file before returning error */
8205         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
8206
8207         __mmplayer_set_antishock( player , FALSE );
8208
8209         if ( async )
8210                 debug_log("do async state transition to PLAYING.\n");
8211
8212         /* set pipeline state to PLAYING */
8213         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8214
8215         ret = __mmplayer_gst_set_state(player,
8216                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout );
8217         if (ret != MM_ERROR_NONE)
8218         {
8219                 debug_error("failed to set state to PLAYING\n");
8220                 return ret;
8221         }
8222         else
8223         {
8224                 if (async == FALSE)
8225                 {
8226                         // MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING );
8227                         debug_log("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
8228                         ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
8229                 }
8230         }
8231
8232         /* generate dot file before returning error */
8233         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
8234
8235         MMPLAYER_FLEAVE();
8236
8237         return ret;
8238 }
8239
8240 static int
8241 __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called) // @
8242 {
8243         GstFormat fmt  = GST_FORMAT_TIME;
8244         unsigned long dur_msec = 0;
8245         gint64 dur_nsec = 0;
8246         gint64 pos_nsec = 0;
8247         gboolean ret = TRUE;
8248         gboolean accurated = FALSE;
8249         GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
8250
8251         MMPLAYER_FENTER();
8252         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8253         return_val_if_fail ( !MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP );
8254
8255         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
8256                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED )
8257                 goto PENDING;
8258
8259         /* check duration */
8260         /* NOTE : duration cannot be zero except live streaming.
8261          *              Since some element could have some timing problemn with quering duration, try again.
8262          */
8263         if ( !player->duration )
8264         {
8265                 if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec ))
8266                 {
8267                         goto SEEK_ERROR;
8268                 }
8269                 player->duration = dur_nsec;
8270         }
8271
8272         if ( player->duration )
8273         {
8274                 dur_msec = GST_TIME_AS_MSECONDS(player->duration);
8275         }
8276         else
8277         {
8278                 debug_error("could not get the duration. fail to seek.\n");
8279                 goto SEEK_ERROR;
8280         }
8281
8282         debug_log("playback rate: %f\n", player->playback_rate);
8283
8284         mm_attrs_get_int_by_name(player->attrs,"accurate_seek", &accurated);
8285         if (accurated)
8286         {
8287                 seek_flags |= GST_SEEK_FLAG_ACCURATE;
8288         }
8289         else
8290         {
8291                 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
8292         }
8293
8294         /* do seek */
8295         switch ( format )
8296         {
8297                 case MM_PLAYER_POS_FORMAT_TIME:
8298                 {
8299                         /* check position is valid or not */
8300                         if ( position > dur_msec )
8301                                 goto INVALID_ARGS;
8302
8303                         debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec);
8304
8305                         if (player->doing_seek)
8306                         {
8307                                 debug_log("not completed seek");
8308                                 return MM_ERROR_PLAYER_DOING_SEEK;
8309                         }
8310
8311                         if ( !internal_called)
8312                                 player->doing_seek = TRUE;
8313
8314                         pos_nsec = position * G_GINT64_CONSTANT(1000000);
8315
8316                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked))
8317                         {
8318                                 gint64 cur_time = 0;
8319                                 GstFormat format = GST_FORMAT_TIME;
8320
8321                                 /* get current position */
8322                                 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &cur_time);
8323
8324                                 /* flush */
8325                                 GstEvent *event = gst_event_new_seek (1.0,
8326                                                                 GST_FORMAT_TIME,
8327                                                                 (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
8328                                                                 GST_SEEK_TYPE_SET, cur_time,
8329                                                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
8330                                 if(event) {
8331                                         __gst_send_event_to_sink(player, event);
8332                                 }
8333
8334                                 __gst_pause( player, FALSE );
8335                         }
8336
8337                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8338                                                         GST_FORMAT_TIME, seek_flags,
8339                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
8340                         if ( !ret  )
8341                         {
8342                                 debug_error("failed to set position. dur[%lu]  pos[%lu]  pos_msec[%llu]\n", dur_msec, position, pos_nsec);
8343                                 goto SEEK_ERROR;
8344                         }
8345                 }
8346                 break;
8347
8348                 case MM_PLAYER_POS_FORMAT_PERCENT:
8349                 {
8350                         debug_log("seeking to (%lu)%% \n", position);
8351
8352                         if (player->doing_seek)
8353                         {
8354                                 debug_log("not completed seek");
8355                                 return MM_ERROR_PLAYER_DOING_SEEK;
8356                         }
8357
8358                         if ( !internal_called)
8359                                 player->doing_seek = TRUE;
8360
8361                         /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
8362                         pos_nsec = (gint64) ( ( position * player->duration ) / 100 );
8363                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8364                                                         GST_FORMAT_TIME, seek_flags,
8365                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
8366                         if ( !ret  )
8367                         {
8368                                 debug_error("failed to set position. dur[%lud]  pos[%lud]  pos_msec[%llud]\n", dur_msec, position, pos_nsec);
8369                                 goto SEEK_ERROR;
8370                         }
8371                 }
8372                 break;
8373
8374                 default:
8375                         goto INVALID_ARGS;
8376
8377         }
8378
8379         /* NOTE : store last seeking point to overcome some bad operation
8380           *      ( returning zero when getting current position ) of some elements
8381           */
8382         player->last_position = pos_nsec;
8383
8384         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
8385         if ( player->playback_rate > 1.0 )
8386                 _mmplayer_set_playspeed ( (MMHandleType)player, player->playback_rate );
8387
8388         MMPLAYER_FLEAVE();
8389         return MM_ERROR_NONE;
8390
8391 PENDING:
8392         player->pending_seek.is_pending = TRUE;
8393         player->pending_seek.format = format;
8394         player->pending_seek.pos = position;
8395
8396         debug_warning("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n",
8397                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
8398
8399         return MM_ERROR_NONE;
8400
8401 INVALID_ARGS:
8402         debug_error("invalid arguments, position : %ld  dur : %ld format : %d \n", position, dur_msec, format);
8403         return MM_ERROR_INVALID_ARGUMENT;
8404
8405 SEEK_ERROR:
8406         player->doing_seek = FALSE;
8407         return MM_ERROR_PLAYER_SEEK;
8408 }
8409
8410 #define TRICKPLAY_OFFSET GST_MSECOND
8411
8412 static int
8413 __gst_get_position(mm_player_t* player, int format, unsigned long* position) // @
8414 {
8415         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
8416         GstFormat fmt = GST_FORMAT_TIME;
8417         signed long long pos_msec = 0;
8418         gboolean ret = TRUE;
8419
8420         return_val_if_fail( player && position && player->pipeline && player->pipeline->mainbin,
8421                 MM_ERROR_PLAYER_NOT_INITIALIZED );
8422
8423         current_state = MMPLAYER_CURRENT_STATE(player);
8424
8425         /* NOTE : query position except paused state to overcome some bad operation
8426          * please refer to below comments in details
8427          */
8428         if ( current_state != MM_PLAYER_STATE_PAUSED )
8429         {
8430                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &pos_msec);
8431         }
8432
8433         /* NOTE : get last point to overcome some bad operation of some elements
8434          * ( returning zero when getting current position in paused state
8435          * and when failed to get postion during seeking
8436          */
8437         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
8438                 || ( ! ret ))
8439                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
8440         {
8441                 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
8442
8443                 if(player->playback_rate < 0.0)
8444                         pos_msec = player->last_position - TRICKPLAY_OFFSET;
8445                 else
8446                         pos_msec = player->last_position;
8447
8448                 if (!ret)
8449                         pos_msec = player->last_position;
8450                 else
8451                         player->last_position = pos_msec;
8452
8453                 debug_log("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
8454
8455         }
8456         else
8457         {
8458                 if (player->duration > 0 && pos_msec > player->duration) {
8459                         pos_msec = player->duration;
8460                 }
8461
8462                 if (player->sm.keep_last_pos) {
8463                         debug_log("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position));
8464                         pos_msec = player->last_position;
8465                 }
8466                 else {
8467                         player->last_position = pos_msec;
8468                 }
8469         }
8470
8471         switch (format) {
8472                 case MM_PLAYER_POS_FORMAT_TIME:
8473                         *position = GST_TIME_AS_MSECONDS(pos_msec);
8474                         break;
8475
8476                 case MM_PLAYER_POS_FORMAT_PERCENT:
8477                 {
8478                         gint64 dur = 0;
8479                         gint64 pos = 0;
8480
8481                         dur = player->duration / GST_SECOND;
8482                         if (dur <= 0)
8483                         {
8484                                 debug_log ("duration is [%d], so returning position 0\n",dur);
8485                                 *position = 0;
8486                         }
8487                         else
8488                         {
8489                                 pos = pos_msec / GST_SECOND;
8490                                 *position = pos * 100 / dur;
8491                         }
8492                         break;
8493                 }
8494                 default:
8495                         return MM_ERROR_PLAYER_INTERNAL;
8496         }
8497
8498         return MM_ERROR_NONE;
8499 }
8500
8501
8502 static int      __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
8503 {
8504 #define STREAMING_IS_FINISHED   0
8505 #define BUFFERING_MAX_PER       100
8506
8507         GstQuery *query = NULL;
8508
8509         return_val_if_fail( player &&
8510                                                 player->pipeline &&
8511                                                 player->pipeline->mainbin,
8512                                                 MM_ERROR_PLAYER_NOT_INITIALIZED );
8513
8514         return_val_if_fail( start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT );
8515
8516         if (!MMPLAYER_IS_HTTP_STREAMING ( player ))
8517         {
8518                 /* and rtsp is not ready yet. */
8519                 debug_warning ( "it's only used for http streaming case.\n" );
8520                 return MM_ERROR_NONE;
8521         }
8522
8523         *start_pos = 0;
8524         *stop_pos = 0;
8525
8526         switch ( format )
8527         {
8528                 case MM_PLAYER_POS_FORMAT_PERCENT :
8529                 {
8530                         gint start_per = -1, stop_per = -1;
8531                         gint64 buffered_total = 0;
8532
8533                         unsigned long position = 0;
8534                         guint curr_size_bytes = 0;
8535                         gint64 buffering_left = -1;
8536                         gint buffered_sec = -1;
8537
8538                         gint64 content_duration = player->duration;
8539                         guint64 content_size = player->http_content_size;
8540
8541                         if (content_duration > 0)
8542                         {
8543                                 if (!__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position))
8544                                 {
8545                                         debug_log ("[Time] pos %d ms / dur %d sec / %lld bytes", position, (guint)(content_duration/GST_SECOND), content_size);
8546                                         start_per = 100 * (position*GST_MSECOND) / content_duration;
8547
8548                                         /* buffered size info from multiqueue */
8549                                         if (player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst)
8550                                         {
8551                                                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst), "curr-size-bytes", &curr_size_bytes, NULL);
8552                                                 debug_log ("[MQ] curr_size_bytes = %d", curr_size_bytes);
8553
8554                                                 buffered_total += curr_size_bytes;
8555                                         }
8556
8557                                         /* buffered size info from queue2 */
8558                                         if (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
8559                                         {
8560                                                 query = gst_query_new_buffering ( GST_FORMAT_BYTES );
8561                                                 if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query))
8562                                                 {
8563                                                         GstBufferingMode mode;
8564                                                         gint byte_in_rate = 0, byte_out_rate = 0;
8565                                                         gint64 start_byte = 0, stop_byte = 0;
8566                                                         guint num_of_ranges = 0;
8567                                                         guint idx = 0;
8568
8569                                                         num_of_ranges = gst_query_get_n_buffering_ranges(query);
8570                                                         for ( idx=0 ; idx<num_of_ranges ; idx++ )
8571                                                         {
8572                                                                 gst_query_parse_nth_buffering_range (query, idx, &start_byte, &stop_byte);
8573                                                                 debug_log ("[Q2][range %d] %lld ~ %lld\n", idx, start_byte, stop_byte);
8574
8575                                                                 buffered_total += (stop_byte - start_byte);
8576                                                         }
8577
8578                                                         gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, &buffering_left);
8579                                                         debug_log ("[Q2] in_rate %d, out_rate %d, left %lld\n", byte_in_rate, byte_out_rate, buffering_left);
8580                                                 }
8581                                                 gst_query_unref (query);
8582                                         }
8583
8584                                         if (buffering_left == STREAMING_IS_FINISHED)
8585                                         {
8586                                                 stop_per = BUFFERING_MAX_PER;
8587                                         }
8588                                         else
8589                                         {
8590                                                 guint dur_sec = (guint)(content_duration/GST_SECOND);
8591                                                 guint avg_byterate = (dur_sec>0)?((guint)(content_size/dur_sec)):(0);
8592
8593                                                 if (avg_byterate > 0)
8594                                                         buffered_sec = (gint)(buffered_total/avg_byterate);
8595                                                 else if (player->total_maximum_bitrate > 0)
8596                                                         buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_maximum_bitrate);
8597                                                 else if (player->total_bitrate > 0)
8598                                                         buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_bitrate);
8599
8600                                                 if ((buffered_sec >= 0) && (dur_sec > 0))
8601                                                         stop_per = start_per + (100 * buffered_sec / dur_sec);
8602                                         }
8603
8604                                         debug_log ("[Buffered Total] %lld bytes, %d sec, per %d~%d\n", buffered_total, buffered_sec, start_per, stop_per);
8605                                 }
8606                         }
8607
8608                         if (((buffered_total == 0) || (start_per < 0) || (stop_per < 0)) &&
8609                                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
8610                         {
8611                                 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
8612                                 if ( gst_element_query ( player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query ) )
8613                                 {
8614                                         GstFormat format;
8615                                         gint64 range_start_per = -1, range_stop_per = -1;
8616
8617                                         gst_query_parse_buffering_range ( query, &format, &range_start_per, &range_stop_per, NULL );
8618
8619                                         debug_log ("[Q2] range start %" G_GINT64_FORMAT " ~ stop %" G_GINT64_FORMAT "\n",  range_start_per , range_stop_per);
8620
8621                                         if (range_start_per != -1)
8622                                                 start_per = (gint)(100 * range_start_per / GST_FORMAT_PERCENT_MAX);
8623
8624                                         if (range_stop_per != -1)
8625                                                 stop_per = (gint)(100 * range_stop_per / GST_FORMAT_PERCENT_MAX);
8626                                 }
8627                                 gst_query_unref (query);
8628                         }
8629
8630                         if ( start_per > 0)
8631                                 *start_pos = (start_per < 100)?(start_per):(100);
8632                         else
8633                                 *start_pos = 0;
8634
8635                         if ( stop_per > 0)
8636                                 *stop_pos = (stop_per < 100)?(stop_per):(100);
8637                         else
8638                                 *stop_pos = 0;
8639
8640                         break;
8641                 }
8642                 case MM_PLAYER_POS_FORMAT_TIME :
8643                         debug_warning ( "Time format is not supported yet.\n" );
8644                         break;
8645
8646                 default :
8647                         break;
8648         }
8649
8650         debug_log("current buffer position : %lu~%lu \n", *start_pos, *stop_pos );
8651
8652         return MM_ERROR_NONE;
8653 }
8654
8655 static int
8656 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param) // @
8657 {
8658         MMPLAYER_FENTER();
8659
8660         if ( !player )
8661         {
8662                 debug_warning("set_message_callback is called with invalid player handle\n");
8663                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
8664         }
8665
8666         player->msg_cb = callback;
8667         player->msg_cb_param = user_param;
8668
8669         debug_log("msg_cb : 0x%x     msg_cb_param : 0x%x\n", (guint)callback, (guint)user_param);
8670
8671         MMPLAYER_FLEAVE();
8672
8673         return MM_ERROR_NONE;
8674 }
8675
8676 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
8677 {
8678         int ret = MM_ERROR_PLAYER_INVALID_URI;
8679         char *path = NULL;
8680
8681         MMPLAYER_FENTER();
8682
8683         return_val_if_fail ( uri , FALSE);
8684         return_val_if_fail ( data , FALSE);
8685         return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
8686
8687         memset(data, 0, sizeof(MMPlayerParseProfile));
8688
8689         if ((path = strstr(uri, "file://")))
8690         {
8691                 int file_stat = MM_ERROR_NONE;
8692
8693                 file_stat = util_exist_file_path(path + 7);
8694
8695                 if (file_stat == MM_ERROR_NONE)
8696                 {
8697                         strncpy(data->uri, path, MM_MAX_URL_LEN-1);
8698
8699                         if ( util_is_sdp_file ( path ) )
8700                         {
8701                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8702                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8703                         }
8704                         else
8705                         {
8706                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8707                         }
8708                         ret = MM_ERROR_NONE;
8709                 }
8710                 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
8711                 {
8712                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8713                 }
8714                 else
8715                 {
8716                         debug_warning("could  access %s.\n", path);
8717                 }
8718         }
8719         else if ((path = strstr(uri, "buff://")))
8720         {
8721                         data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
8722                         ret = MM_ERROR_NONE;
8723         }
8724         else if ((path = strstr(uri, "rtsp://")))
8725         {
8726                 if (strlen(path)) {
8727                         if((path = strstr(uri, "/wfd1.0/"))) {
8728                                 strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
8729                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_WFD;
8730                                 ret = MM_ERROR_NONE;
8731                                 debug_log("uri is actually a wfd client path. giving it to wfdrtspsrc\n");
8732                         }
8733                         else {
8734                                 strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
8735                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8736                                 ret = MM_ERROR_NONE;
8737                         }
8738                 }
8739         }
8740         else if ((path = strstr(uri, "http://")))
8741         {
8742                 if (strlen(path)) {
8743                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
8744 #ifdef MM_SMOOTH_STREAMING
8745                         if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
8746                                 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
8747                         {
8748                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
8749                         }
8750                         else
8751 #endif
8752                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
8753
8754                         ret = MM_ERROR_NONE;
8755                 }
8756         }
8757         else if ((path = strstr(uri, "https://")))
8758         {
8759                 if (strlen(path)) {
8760                         strncpy(data->uri, uri, MM_MAX_URL_LEN -1);
8761 #ifdef MM_SMOOTH_STREAMING
8762                 if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
8763                                 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
8764                         {
8765                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
8766                         }
8767 #endif
8768                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
8769
8770                         ret = MM_ERROR_NONE;
8771                 }
8772         }
8773         else if ((path = strstr(uri, "rtspu://")))
8774         {
8775                 if (strlen(path)) {
8776                         strncpy(data->uri, uri, MM_MAX_URL_LEN -1);
8777                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8778                         ret = MM_ERROR_NONE;
8779                 }
8780         }
8781         else if ((path = strstr(uri, "rtspr://")))
8782         {
8783                 strncpy(data->uri, path, MM_MAX_URL_LEN -1);
8784                 char *separater =strstr(path, "*");
8785
8786                 if (separater) {
8787                         int urgent_len = 0;
8788                         char *urgent = separater + strlen("*");
8789
8790                         if ((urgent_len = strlen(urgent))) {
8791                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
8792                                 strncpy(data->urgent, urgent, MM_MAX_FILENAME_LEN -1);
8793                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8794                                 ret = MM_ERROR_NONE;
8795                         }
8796                 }
8797         }
8798         else if ((path = strstr(uri, "mms://")))
8799         {
8800                 if (strlen(path)) {
8801                         strncpy(data->uri, uri, MM_MAX_URL_LEN -1);
8802                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
8803                         ret = MM_ERROR_NONE;
8804                 }
8805         }
8806         else if ((path = strstr(uri, "mem://")))
8807         {
8808                 if (strlen(path)) {
8809                         #define MM_MAX_EXT_SIZE 100
8810                         int mem_size = 0;
8811                         char *buffer = NULL;
8812                         char *seperator = strchr(path, ',');
8813                         char ext[MM_MAX_EXT_SIZE] = {0,}, size[MM_MAX_EXT_SIZE] = {0,};
8814
8815                         if (seperator) {
8816                                 if ((buffer = strstr(path, "ext="))) {
8817                                         buffer += strlen("ext=");
8818
8819                                         if (strlen(buffer)) {
8820                                                 strncpy(ext, buffer, MM_MAX_EXT_SIZE -1);
8821
8822                                                 if ((seperator = strchr(ext, ','))
8823                                                         || (seperator = strchr(ext, ' '))
8824                                                         || (seperator = strchr(ext, '\0'))) {
8825                                                         seperator[0] = '\0';
8826                                                 }
8827                                         }
8828                                 }
8829
8830                                 if ((buffer = strstr(path, "size="))) {
8831                                         buffer += strlen("size=");
8832
8833                                         if (strlen(buffer) > 0) {
8834                                                 strncpy(size, buffer, MM_MAX_EXT_SIZE -1);
8835
8836                                                 if ((seperator = strchr(size, ','))
8837                                                         || (seperator = strchr(size, ' '))
8838                                                         || (seperator = strchr(size, '\0'))) {
8839                                                         seperator[0] = '\0';
8840                                                 }
8841
8842                                                 mem_size = atoi(size);
8843                                         }
8844                                 }
8845                         }
8846
8847                         debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
8848                         if ( mem_size && param)
8849                         {
8850                                 data->mem = param;
8851                                 data->mem_size = mem_size;
8852                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
8853                                 ret = MM_ERROR_NONE;
8854                         }
8855                 }
8856         }
8857         else
8858         {
8859                 int file_stat = MM_ERROR_NONE;
8860
8861                 file_stat = util_exist_file_path(uri);
8862
8863                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
8864                 if (file_stat == MM_ERROR_NONE)
8865                 {
8866                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", uri);
8867
8868                         if ( util_is_sdp_file( (char*)uri ) )
8869                         {
8870                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8871                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8872                         }
8873                         else
8874                         {
8875                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8876                         }
8877                         ret = MM_ERROR_NONE;
8878                 }
8879                 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
8880                 {
8881                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8882                 }
8883                 else
8884                 {
8885                         debug_error ("invalid uri, could not play..\n");
8886                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8887                 }
8888         }
8889
8890         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
8891                 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
8892         } else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION){
8893                 ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
8894         }
8895
8896         /* dump parse result */
8897         secure_debug_warning("incomming uri : %s\n", uri);
8898         debug_log("uri_type : %d, play_mode : %d, mem : 0x%x, mem_size : %d, urgent : %s\n",
8899                 data->uri_type, data->play_mode, (guint)data->mem, data->mem_size, data->urgent);
8900
8901         MMPLAYER_FLEAVE();
8902
8903         return ret;
8904 }
8905
8906 gboolean _asm_postmsg(gpointer *data)
8907 {
8908         mm_player_t* player = (mm_player_t*)data;
8909         MMMessageParamType msg = {0, };
8910
8911         MMPLAYER_FENTER();
8912         return_val_if_fail ( player, FALSE );
8913         debug_warning("get notified");
8914
8915         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
8916                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
8917         {
8918                 debug_warning("dispatched");
8919                 return FALSE;
8920         }
8921
8922
8923         msg.union_type = MM_MSG_UNION_CODE;
8924         msg.code = player->sm.event_src;
8925
8926 #if 0 // should remove
8927         if (player->sm.event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
8928         {
8929                 /* fill the message with state of player */
8930                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
8931                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
8932                 player->resumable_cancel_id = 0;
8933         }
8934         else
8935 #endif
8936         {
8937                 MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
8938                 player->resume_event_id = 0;
8939         }
8940
8941         debug_warning("dispatched");
8942         return FALSE;
8943 }
8944
8945 gboolean _asm_lazy_pause(gpointer *data)
8946 {
8947         mm_player_t* player = (mm_player_t*)data;
8948         int ret = MM_ERROR_NONE;
8949
8950         MMPLAYER_FENTER();
8951
8952         return_val_if_fail ( player, FALSE );
8953
8954         if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
8955         {
8956                 debug_log ("Ready to proceed lazy pause\n");
8957                 ret = _mmplayer_pause((MMHandleType)player);
8958                 if(MM_ERROR_NONE != ret)
8959                 {
8960                         debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
8961                 }
8962         }
8963         else
8964         {
8965                 debug_log ("Invalid state to proceed lazy pause\n");
8966         }
8967
8968         /* unset mute */
8969         if (player->pipeline && player->pipeline->audiobin)
8970                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
8971
8972         player->sm.by_asm_cb = FALSE; //should be reset here
8973
8974         MMPLAYER_FLEAVE();
8975
8976         return FALSE;
8977 }
8978
8979 static gboolean
8980 __mmplayer_can_do_interrupt(mm_player_t *player)
8981 {
8982         if (!player || !player->pipeline || !player->attrs)
8983         {
8984                 debug_warning("not initialized");
8985                 goto FAILED;
8986         }
8987
8988         if ((player->sm.exit_cb) || (player->set_mode.pcm_extraction))
8989         {
8990                 debug_warning("leave from asm cb right now, %d, %d", player->sm.exit_cb, player->set_mode.pcm_extraction);
8991                 goto FAILED;
8992         }
8993
8994         /* check if seeking */
8995         if (player->doing_seek)
8996         {
8997                 MMMessageParamType msg_param;
8998                 memset (&msg_param, 0, sizeof(MMMessageParamType));
8999                 msg_param.code = MM_ERROR_PLAYER_SEEK;
9000                 player->doing_seek = FALSE;
9001                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9002                 goto FAILED;
9003         }
9004
9005         /* check other thread */
9006         if (player->cmd_lock)
9007         {
9008                 if (!g_mutex_trylock(player->cmd_lock))
9009                 {
9010                         debug_warning("locked already, cmd state : %d", player->cmd);
9011
9012                         /* check application command */
9013                         if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)
9014                         {
9015                                 debug_warning("playing.. should wait cmd lock then, will be interrupted");
9016                                 g_mutex_lock(player->cmd_lock);
9017                                 goto INTERRUPT;
9018                         }
9019                         debug_warning("nothing to do");
9020                         goto FAILED;
9021                 }
9022                 else
9023                 {
9024                         debug_warning("can interrupt immediately");
9025                         goto INTERRUPT;
9026                 }
9027         }
9028
9029 FAILED:
9030         return FALSE;
9031
9032 INTERRUPT:
9033         return TRUE;
9034 }
9035
9036 ASM_cb_result_t
9037 __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
9038 {
9039         mm_player_t* player = (mm_player_t*) cb_data;
9040         ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
9041         int result = MM_ERROR_NONE;
9042         gboolean lazy_pause = FALSE;
9043
9044         debug_warning("get notified");
9045
9046         if (!__mmplayer_can_do_interrupt(player))
9047         {
9048                 debug_warning("no need to interrupt, so leave");
9049                 goto EXIT;
9050         }
9051
9052         player->sm.cb_pending = TRUE;
9053         debug_warning("asm event src type : %d, command : 0x%x", event_src, command);
9054
9055         player->sm.by_asm_cb = TRUE;
9056         player->sm.event_src = event_src;
9057
9058         /* first, check event source */
9059         if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG)
9060         {
9061                 int stop_by_asm = 0;
9062                 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
9063                 if (!stop_by_asm)
9064                         goto DONE;
9065         }
9066         else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
9067         {
9068                 /* can use video overlay simultaneously */
9069                 /* video resource conflict */
9070                 if(player->pipeline->videobin)
9071                 {
9072                         if (player->ini.multiple_codec_supported)
9073                         {
9074                                 debug_log("video conflict but, can support multiple video");
9075                                 result = _mmplayer_pause((MMHandleType)player);
9076                                 cb_res = ASM_CB_RES_PAUSE;
9077                         }
9078                         else
9079                         {
9080                                 debug_log("video conflict, can't support multiple video");
9081                                 result = _mmplayer_unrealize((MMHandleType)player);
9082                                 cb_res = ASM_CB_RES_STOP;
9083                         }
9084                 }
9085                 else if (player->pipeline->audiobin)
9086                 {
9087                         debug_log("audio resource conflict");
9088                         result = _mmplayer_pause((MMHandleType)player);
9089                         if (result != MM_ERROR_NONE)
9090                         {
9091                                 debug_warning("fail to set pause by asm");
9092                         }
9093                         cb_res = ASM_CB_RES_PAUSE;
9094                 }
9095                 goto DONE;
9096         }
9097 #if 0 // should remove
9098         else if (event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
9099         {
9100                 debug_warning("Got msg from asm for resumable canceled.\n");
9101                 player->sm.antishock = TRUE;
9102                 player->sm.by_asm_cb = FALSE;
9103
9104                 player->resumable_cancel_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
9105                 cb_res = ASM_CB_RES_IGNORE;
9106                 goto DONE;
9107         }
9108 #endif
9109         /* then, check command */
9110         switch(command)
9111         {
9112                 case ASM_COMMAND_PLAY:
9113                         debug_warning ("Got unexpected asm command (%d)", command);
9114                         break;
9115
9116                 case ASM_COMMAND_STOP: // notification case
9117                         {
9118                                 GstFormat format = GST_FORMAT_TIME;
9119                                 debug_warning("Got msg from asm to stop");
9120
9121                                 if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &player->last_position)) {
9122                                         debug_error("failed to get position");
9123                                         player->last_position = 0;
9124                                 }
9125
9126                                 debug_log ("pos_msec = %"GST_TIME_FORMAT"", GST_TIME_ARGS(player->last_position));
9127
9128                                 result = _mmplayer_stop((MMHandleType)player);
9129                                 if (result != MM_ERROR_NONE)
9130                                 {
9131                                         debug_warning("fail to set stop state by asm");
9132                                         cb_res = ASM_CB_RES_IGNORE;
9133                                 }
9134                                 else
9135                                 {
9136                                         cb_res = ASM_CB_RES_STOP;
9137                                 }
9138                                 player->sm.by_asm_cb = FALSE; // reset because no message any more from asm
9139                                 player->sm.keep_last_pos = TRUE;
9140                         }
9141                         break;
9142
9143                 case ASM_COMMAND_PAUSE:
9144                         {
9145                                 debug_warning("Got msg from asm to Pause");
9146                                 if(event_src == ASM_EVENT_SOURCE_CALL_START ||
9147                                         event_src == ASM_EVENT_SOURCE_NOTIFY_START ||
9148                                         event_src == ASM_EVENT_SOURCE_ALARM_START)
9149                                 {
9150                                         if(__mmplayer_ignore_current_external_display_mode(player) == MM_ERROR_NONE)
9151                                                 debug_log("screen will not display to external display");
9152                                 }
9153                                 if(event_src == ASM_EVENT_SOURCE_CALL_START ||
9154                                         event_src == ASM_EVENT_SOURCE_ALARM_START ||
9155                                         event_src == ASM_EVENT_SOURCE_MEDIA)
9156                                 {
9157                                         if ( ! MMPLAYER_IS_RTSP_STREAMING(player) ) {
9158                                                 //hold 0.7 second to excute "fadedown mute" effect
9159                                                 debug_warning ("do fade down->pause->undo fade down");
9160
9161                                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
9162
9163                                                 result = _mmplayer_pause((MMHandleType)player);
9164                                                 if (result != MM_ERROR_NONE)
9165                                                 {
9166                                                         debug_warning("fail to set Pause state by asm");
9167                                                         cb_res = ASM_CB_RES_IGNORE;
9168                                                         break;
9169                                                 }
9170                                                 __mmplayer_undo_sound_fadedown(player);
9171                                         } else {
9172                                                 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
9173                                                 _mmplayer_unrealize((MMHandleType)player);
9174                                         }
9175                                 }
9176 #ifdef USE_LAZY_PAUSE // if enabled, should consider event id and context when removed
9177                                 else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
9178                                 {
9179                                         lazy_pause = TRUE; // return as soon as possible, for fast start of other app
9180
9181                                         if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
9182                                                 g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
9183
9184                                         player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
9185                                         debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
9186                                 }
9187 #endif
9188                                 else
9189                                 {
9190                                         debug_warning ("pause immediately");
9191                                         result = _mmplayer_pause((MMHandleType)player);
9192                                 }
9193                                 cb_res = ASM_CB_RES_PAUSE;
9194                         }
9195                         break;
9196
9197                 case ASM_COMMAND_RESUME:
9198                         {
9199                                 debug_warning("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
9200                                 player->sm.antishock = TRUE;
9201                                 player->sm.by_asm_cb = FALSE;
9202
9203                                 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
9204                                 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
9205                                 cb_res = ASM_CB_RES_IGNORE;
9206                                 goto DONE;
9207                         }
9208                         break;
9209
9210                 default:
9211                         break;
9212         }
9213
9214 DONE:
9215         if ( !lazy_pause )
9216         {
9217                 player->sm.by_asm_cb = FALSE;
9218         }
9219         player->sm.cb_pending = FALSE;
9220         MMPLAYER_CMD_UNLOCK( player );
9221
9222 EXIT:
9223         debug_warning("dispatched");
9224         return cb_res;
9225 }
9226
9227 int
9228 _mmplayer_create_player(MMHandleType handle) // @
9229 {
9230         mm_player_t* player = MM_PLAYER_CAST(handle);
9231
9232         MMPLAYER_FENTER();
9233
9234         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9235
9236         /* initialize player state */
9237         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
9238         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
9239         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
9240         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
9241
9242         /* check current state */
9243         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
9244
9245         /* construct attributes */
9246         player->attrs = _mmplayer_construct_attribute(handle);
9247
9248         if ( !player->attrs )
9249         {
9250                 debug_error("Failed to construct attributes\n");
9251                 goto ERROR;
9252         }
9253
9254         /* initialize gstreamer with configured parameter */
9255         if ( ! __mmplayer_init_gstreamer(player) )
9256         {
9257                 debug_error("Initializing gstreamer failed\n");
9258                 goto ERROR;
9259         }
9260
9261         /* initialize factories if not using decodebin */
9262         if( player->factories == NULL )
9263             __mmplayer_init_factories(player);
9264
9265         /* create lock. note that g_tread_init() has already called in gst_init() */
9266         player->fsink_lock = g_mutex_new();
9267         if ( ! player->fsink_lock )
9268         {
9269                 debug_error("Cannot create mutex for command lock\n");
9270                 goto ERROR;
9271         }
9272
9273         /* create repeat mutex */
9274         player->repeat_thread_mutex = g_mutex_new();
9275         if ( ! player->repeat_thread_mutex )
9276         {
9277                 debug_error("Cannot create repeat mutex\n");
9278                 goto ERROR;
9279         }
9280
9281         /* create repeat cond */
9282         player->repeat_thread_cond = g_cond_new();
9283         if ( ! player->repeat_thread_cond )
9284         {
9285                 debug_error("Cannot create repeat cond\n");
9286                 goto ERROR;
9287         }
9288
9289         /* create repeat thread */
9290         player->repeat_thread =
9291                 g_thread_create (__mmplayer_repeat_thread, (gpointer)player, TRUE, NULL);
9292         if ( ! player->repeat_thread )
9293         {
9294                 debug_error("failed to create repeat thread");
9295                 goto ERROR;
9296         }
9297
9298         /* create next play mutex */
9299         player->next_play_thread_mutex = g_mutex_new();
9300         if ( ! player->next_play_thread_mutex )
9301         {
9302                 debug_error("Cannot create next_play mutex\n");
9303                 goto ERROR;
9304         }
9305
9306         /* create next play cond */
9307         player->next_play_thread_cond = g_cond_new();
9308         if ( ! player->next_play_thread_cond )
9309         {
9310                 debug_error("Cannot create next_play cond\n");
9311                 goto ERROR;
9312         }
9313
9314         /* create next play thread */
9315         player->next_play_thread =
9316                 g_thread_create (__mmplayer_next_play_thread, (gpointer)player, TRUE, NULL);
9317         if ( ! player->next_play_thread )
9318         {
9319                 debug_error("failed to create next play thread");
9320                 goto ERROR;
9321         }
9322
9323         if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
9324         {
9325                 debug_error("failed to initialize video capture\n");
9326                 goto ERROR;
9327         }
9328
9329         /* register to asm */
9330         if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
9331         {
9332                 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
9333                 debug_error("failed to register asm server\n");
9334                 return MM_ERROR_POLICY_INTERNAL;
9335         }
9336
9337         /* to add active device callback */
9338         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))
9339         {
9340                 debug_error("failed mm_sound_add_device_information_changed_callback \n");
9341         }
9342
9343         if (MMPLAYER_IS_HTTP_PD(player))
9344         {
9345                 player->pd_downloader = NULL;
9346                 player->pd_file_save_path = NULL;
9347         }
9348
9349         player->streaming_type = STREAMING_SERVICE_NONE;
9350
9351         /* give default value of audio effect setting */
9352         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
9353         player->playback_rate = DEFAULT_PLAYBACK_RATE;
9354
9355         player->play_subtitle = FALSE;
9356         player->use_textoverlay = FALSE;
9357         player->play_count = 0;
9358         player->use_decodebin = TRUE;
9359         player->ignore_asyncdone = FALSE;
9360         player->use_deinterleave = FALSE;
9361         player->pp_rebuilding = FALSE;
9362         player->max_audio_channels = 0;
9363         player->video_share_api_delta = 0;
9364         player->video_share_clock_delta = 0;
9365         player->has_closed_caption = FALSE;
9366
9367         __mmplayer_post_proc_reset(player);
9368
9369         if (player->ini.dump_element_keyword[0][0] == '\0')
9370         {
9371                 player->ini.set_dump_element_flag= FALSE;
9372         }
9373         else
9374         {
9375                 player->ini.set_dump_element_flag = TRUE;
9376         }
9377
9378         /* set player state to null */
9379         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
9380         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
9381
9382         return MM_ERROR_NONE;
9383
9384 ERROR:
9385         /* free lock */
9386         if ( player->fsink_lock )
9387                 g_mutex_free( player->fsink_lock );
9388         player->fsink_lock = NULL;
9389
9390         /* free thread */
9391         if ( player->repeat_thread_cond &&
9392                  player->repeat_thread_mutex &&
9393                  player->repeat_thread )
9394         {
9395                 player->repeat_thread_exit = TRUE;
9396                 g_cond_signal( player->repeat_thread_cond );
9397
9398                 g_thread_join( player->repeat_thread );
9399                 player->repeat_thread = NULL;
9400
9401                 g_mutex_free ( player->repeat_thread_mutex );
9402                 player->repeat_thread_mutex = NULL;
9403
9404                 g_cond_free ( player->repeat_thread_cond );
9405                 player->repeat_thread_cond = NULL;
9406         }
9407         /* clear repeat thread mutex/cond if still alive
9408          * this can happen if only thread creating has failed
9409          */
9410         if ( player->repeat_thread_mutex )
9411                 g_mutex_free ( player->repeat_thread_mutex );
9412
9413         if ( player->repeat_thread_cond )
9414                 g_cond_free ( player->repeat_thread_cond );
9415
9416         /* free next play thread */
9417         if ( player->next_play_thread_cond &&
9418                  player->next_play_thread_mutex &&
9419                  player->next_play_thread )
9420         {
9421                 player->next_play_thread_exit = TRUE;
9422                 g_cond_signal( player->next_play_thread_cond );
9423
9424                 g_thread_join( player->next_play_thread );
9425                 player->next_play_thread = NULL;
9426
9427                 g_mutex_free ( player->next_play_thread_mutex );
9428                 player->next_play_thread_mutex = NULL;
9429
9430                 g_cond_free ( player->next_play_thread_cond );
9431                 player->next_play_thread_cond = NULL;
9432         }
9433         /* clear next play thread mutex/cond if still alive
9434          * this can happen if only thread creating has failed
9435          */
9436         if ( player->next_play_thread_mutex )
9437                 g_mutex_free ( player->next_play_thread_mutex );
9438
9439         if ( player->next_play_thread_cond )
9440                 g_cond_free ( player->next_play_thread_cond );
9441
9442         /* release attributes */
9443         _mmplayer_deconstruct_attribute(handle);
9444
9445         MMPLAYER_FLEAVE();
9446
9447         return MM_ERROR_PLAYER_INTERNAL;
9448 }
9449
9450 static gboolean
9451 __mmplayer_init_gstreamer(mm_player_t* player) // @
9452 {
9453         static gboolean initialized = FALSE;
9454         static const int max_argc = 50;
9455         gint* argc = NULL;
9456         gchar** argv = NULL;
9457         gchar** argv2 = NULL;
9458         GError *err = NULL;
9459         int i = 0;
9460         int arg_count = 0;
9461
9462         if ( initialized )
9463         {
9464                 debug_log("gstreamer already initialized.\n");
9465                 return TRUE;
9466         }
9467
9468         /* alloc */
9469         argc = malloc( sizeof(int) );
9470         argv = malloc( sizeof(gchar*) * max_argc );
9471         argv2 = malloc( sizeof(gchar*) * max_argc );
9472
9473         if ( !argc || !argv || !argv2)
9474                 goto ERROR;
9475
9476         memset( argv, 0, sizeof(gchar*) * max_argc );
9477         memset( argv2, 0, sizeof(gchar*) * max_argc );
9478
9479         /* add initial */
9480         *argc = 1;
9481         argv[0] = g_strdup( "mmplayer" );
9482
9483         /* add gst_param */
9484         for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
9485         {
9486                 if ( strlen( player->ini.gst_param[i] ) > 0 )
9487                 {
9488                         argv[*argc] = g_strdup( player->ini.gst_param[i] );
9489                         (*argc)++;
9490                 }
9491         }
9492
9493         /* we would not do fork for scanning plugins */
9494         argv[*argc] = g_strdup("--gst-disable-registry-fork");
9495         (*argc)++;
9496
9497         /* check disable registry scan */
9498         if ( player->ini.skip_rescan )
9499         {
9500                 argv[*argc] = g_strdup("--gst-disable-registry-update");
9501                 (*argc)++;
9502         }
9503
9504         /* check disable segtrap */
9505         if ( player->ini.disable_segtrap )
9506         {
9507                 argv[*argc] = g_strdup("--gst-disable-segtrap");
9508                 (*argc)++;
9509         }
9510
9511         debug_log("initializing gstreamer with following parameter\n");
9512         debug_log("argc : %d\n", *argc);
9513         arg_count = *argc;
9514
9515         for ( i = 0; i < arg_count; i++ )
9516         {
9517                 argv2[i] = argv[i];
9518                 debug_log("argv[%d] : %s\n", i, argv2[i]);
9519         }
9520
9521
9522         /* initializing gstreamer */
9523         if ( ! gst_init_check (argc, &argv, &err))
9524         {
9525                 debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
9526                 if (err)
9527                 {
9528                         g_error_free (err);
9529                 }
9530
9531                 goto ERROR;
9532         }
9533         /* release */
9534         for ( i = 0; i < arg_count; i++ )
9535         {
9536                 //debug_log("release - argv[%d] : %s\n", i, argv2[i]);
9537                 MMPLAYER_FREEIF( argv2[i] );
9538         }
9539
9540         MMPLAYER_FREEIF( argv );
9541         MMPLAYER_FREEIF( argv2 );
9542         MMPLAYER_FREEIF( argc );
9543
9544         /* done */
9545         initialized = TRUE;
9546
9547         return TRUE;
9548
9549 ERROR:
9550
9551         /* release */
9552         for ( i = 0; i < arg_count; i++ )
9553         {
9554                 debug_log("free[%d] : %s\n", i, argv2[i]);
9555                 MMPLAYER_FREEIF( argv2[i] );
9556         }
9557
9558         MMPLAYER_FREEIF( argv );
9559         MMPLAYER_FREEIF( argv2 );
9560         MMPLAYER_FREEIF( argc );
9561
9562         return FALSE;
9563 }
9564
9565 int
9566 __mmplayer_destroy_streaming_ext(mm_player_t* player)
9567 {
9568         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9569
9570         if (player->pd_downloader)
9571         {
9572                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
9573                 MMPLAYER_FREEIF(player->pd_downloader);
9574         }
9575
9576         if (MMPLAYER_IS_HTTP_PD(player))
9577         {
9578                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
9579                 MMPLAYER_FREEIF(player->pd_file_save_path);
9580         }
9581
9582         return MM_ERROR_NONE;
9583 }
9584
9585 int
9586 _mmplayer_destroy(MMHandleType handle) // @
9587 {
9588         mm_player_t* player = MM_PLAYER_CAST(handle);
9589
9590         MMPLAYER_FENTER();
9591
9592         /* check player handle */
9593         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9594
9595         /* destroy can called at anytime */
9596         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
9597
9598         __mmplayer_destroy_streaming_ext(player);
9599
9600         /* release repeat thread */
9601         if ( player->repeat_thread_cond &&
9602                  player->repeat_thread_mutex &&
9603                  player->repeat_thread )
9604         {
9605                 player->repeat_thread_exit = TRUE;
9606                 g_cond_signal( player->repeat_thread_cond );
9607
9608                 debug_log("waitting for repeat thread exit\n");
9609                 g_thread_join ( player->repeat_thread );
9610                 g_mutex_free ( player->repeat_thread_mutex );
9611                 g_cond_free ( player->repeat_thread_cond );
9612                 debug_log("repeat thread released\n");
9613         }
9614
9615         /* release next play thread */
9616         if ( player->next_play_thread_cond &&
9617                  player->next_play_thread_mutex &&
9618                  player->next_play_thread )
9619         {
9620                 player->next_play_thread_exit = TRUE;
9621                 g_cond_signal( player->next_play_thread_cond );
9622
9623                 debug_log("waitting for next play thread exit\n");
9624                 g_thread_join ( player->next_play_thread );
9625                 g_mutex_free ( player->next_play_thread_mutex );
9626                 g_cond_free ( player->next_play_thread_cond );
9627                 debug_log("next play thread released\n");
9628         }
9629
9630         _mmplayer_release_video_capture(player);
9631
9632         /* flush any pending asm_cb */
9633         if (player->sm.cb_pending)
9634         {
9635                 /* set a flag for make sure asm_cb to be returned immediately */
9636                 debug_warning("asm cb has pending state");
9637                 player->sm.exit_cb = TRUE;
9638
9639                 /* make sure to release any pending asm_cb which locked by cmd_lock */
9640                 MMPLAYER_CMD_UNLOCK(player);
9641                 sched_yield();
9642                 MMPLAYER_CMD_LOCK(player);
9643         }
9644
9645         /* withdraw asm */
9646         if ( MM_ERROR_NONE != _mmplayer_asm_unregister(&player->sm) )
9647         {
9648                 debug_error("failed to deregister asm server\n");
9649         }
9650
9651 #ifdef USE_LAZY_PAUSE
9652         if (player->lazy_pause_event_id)
9653         {
9654                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->lazy_pause_event_id);
9655                 player->lazy_pause_event_id = 0;
9656         }
9657 #endif
9658
9659         if (player->resume_event_id)
9660         {
9661                 g_source_remove (player->resume_event_id);
9662                 player->resume_event_id = 0;
9663         }
9664
9665         if (player->resumable_cancel_id)
9666         {
9667                 g_source_remove (player->resumable_cancel_id);
9668                 player->resumable_cancel_id = 0;
9669         }
9670
9671         /* release pipeline */
9672         if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
9673         {
9674                 debug_error("failed to destory pipeline\n");
9675                 return MM_ERROR_PLAYER_INTERNAL;
9676         }
9677
9678         if (player->is_external_subtitle_present && player->subtitle_language_list)
9679         {
9680           g_list_free (player->subtitle_language_list);
9681           player->subtitle_language_list = NULL;
9682         }
9683
9684         __mmplayer_release_dump_list (player->dump_list);
9685
9686         /* release miscellaneous information.
9687            these info needs to be released after pipeline is destroyed. */
9688         __mmplayer_release_misc_post( player );
9689
9690         /* release attributes */
9691         _mmplayer_deconstruct_attribute( handle );
9692
9693         /* release factories */
9694         __mmplayer_release_factories( player );
9695
9696         /* release lock */
9697         if ( player->fsink_lock )
9698                 g_mutex_free( player->fsink_lock );
9699
9700         if ( player->msg_cb_lock )
9701                 g_mutex_free( player->msg_cb_lock );
9702
9703         MMPLAYER_FLEAVE();
9704
9705         return MM_ERROR_NONE;
9706 }
9707
9708 int
9709 __mmplayer_realize_streaming_ext(mm_player_t* player)
9710 {
9711         int ret = MM_ERROR_NONE;
9712
9713         MMPLAYER_FENTER();
9714         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9715
9716         if (MMPLAYER_IS_HTTP_PD(player))
9717         {
9718                 gboolean bret = FALSE;
9719
9720                 player->pd_downloader = _mmplayer_create_pd_downloader();
9721                 if ( !player->pd_downloader )
9722                 {
9723                         debug_error ("Unable to create PD Downloader...");
9724                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
9725                 }
9726
9727                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
9728
9729                 if (FALSE == bret)
9730                 {
9731                         debug_error ("Unable to create PD Downloader...");
9732                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
9733                 }
9734         }
9735
9736         MMPLAYER_FLEAVE();
9737         return ret;
9738 }
9739
9740 int
9741 _mmplayer_realize(MMHandleType hplayer) // @
9742 {
9743         mm_player_t* player =  (mm_player_t*)hplayer;
9744         char *uri =NULL;
9745         void *param = NULL;
9746         int application_pid = -1;
9747         gboolean update_registry = FALSE;
9748         MMHandleType attrs = 0;
9749         int ret = MM_ERROR_NONE;
9750
9751         MMPLAYER_FENTER();
9752
9753         /* check player handle */
9754         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
9755
9756         /* check current state */
9757         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
9758
9759         attrs = MMPLAYER_GET_ATTRS(player);
9760         if ( !attrs )
9761         {
9762                 debug_error("fail to get attributes.\n");
9763                 return MM_ERROR_PLAYER_INTERNAL;
9764         }
9765
9766         mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
9767         player->sm.pid = application_pid;
9768
9769         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
9770         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
9771
9772         ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
9773
9774         if (ret != MM_ERROR_NONE)
9775         {
9776                 debug_error("failed to parse profile\n");
9777                 return ret;
9778         }
9779
9780         /* FIXIT : we can use thouse in player->profile directly */
9781         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
9782         {
9783                 player->mem_buf.buf = (char *)player->profile.mem;
9784                 player->mem_buf.len = player->profile.mem_size;
9785                 player->mem_buf.offset = 0;
9786         }
9787
9788         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
9789         {
9790                 debug_warning("mms protocol is not supported format.\n");
9791                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
9792         }
9793
9794         if (MMPLAYER_IS_STREAMING(player))
9795                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
9796         else
9797                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
9798
9799         player->needed_v_parser = FALSE;
9800         player->smooth_streaming = FALSE;
9801         player->videodec_linked  = 0;
9802         player->videosink_linked = 0;
9803         player->audiodec_linked  = 0;
9804         player->audiosink_linked = 0;
9805         player->textsink_linked = 0;
9806         player->is_external_subtitle_present = FALSE;
9807         /* set the subtitle ON default */
9808         player->is_subtitle_off = FALSE;
9809
9810         /* registry should be updated for downloadable codec */
9811         mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
9812
9813         if ( update_registry )
9814         {
9815                 debug_log("updating registry...\n");
9816                 gst_update_registry();
9817
9818                 /* then we have to rebuild factories */
9819                 __mmplayer_release_factories( player );
9820                 __mmplayer_init_factories(player);
9821         }
9822
9823         /* realize pipeline */
9824         ret = __gst_realize( player );
9825         if ( ret != MM_ERROR_NONE )
9826         {
9827                 debug_error("fail to realize the player.\n");
9828         }
9829         else
9830         {
9831                 ret = __mmplayer_realize_streaming_ext(player);
9832         }
9833
9834         MMPLAYER_FLEAVE();
9835
9836         return ret;
9837 }
9838
9839 int
9840 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
9841 {
9842         MMPLAYER_FENTER();
9843         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9844
9845         /* destroy can called at anytime */
9846         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
9847         {
9848                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
9849                 MMPLAYER_FREEIF(player->pd_downloader);
9850         }
9851
9852         MMPLAYER_FLEAVE();
9853         return MM_ERROR_NONE;
9854 }
9855
9856 int
9857 _mmplayer_unrealize(MMHandleType hplayer)
9858 {
9859         mm_player_t* player = (mm_player_t*)hplayer;
9860         int ret = MM_ERROR_NONE;
9861
9862         MMPLAYER_FENTER();
9863
9864         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
9865
9866         /* check current state */
9867         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
9868
9869         __mmplayer_unrealize_streaming_ext(player);
9870
9871         /* unrealize pipeline */
9872         ret = __gst_unrealize( player );
9873
9874         /* set asm stop if success */
9875         if (MM_ERROR_NONE == ret)
9876         {
9877                 if (player->sm.state != ASM_STATE_STOP)
9878                 {
9879                         /* NOTE : Stop asm after pipeline unrealize. Keep this sequence. */
9880                         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP, FALSE);
9881                         if ( ret )
9882                         {
9883                                 debug_error("failed to set asm state to STOP");
9884                                 return ret;
9885                         }
9886                 }
9887         }
9888         else
9889         {
9890                 debug_error("failed and don't change asm state to stop");
9891         }
9892
9893         MMPLAYER_FLEAVE();
9894
9895         return ret;
9896 }
9897
9898 int
9899 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
9900 {
9901         mm_player_t* player = (mm_player_t*)hplayer;
9902
9903         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9904
9905         return __gst_set_message_callback(player, callback, user_param);
9906 }
9907
9908 int
9909 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
9910 {
9911         mm_player_t *player = (mm_player_t*)hplayer;
9912
9913         return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
9914
9915         *state = MMPLAYER_CURRENT_STATE(player);
9916
9917         return MM_ERROR_NONE;
9918 }
9919
9920
9921 int
9922 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
9923 {
9924         mm_player_t* player = (mm_player_t*) hplayer;
9925         GstElement* vol_element = NULL;
9926         int i = 0;
9927
9928         MMPLAYER_FENTER();
9929
9930         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9931
9932         debug_log("volume [L]=%f:[R]=%f\n",
9933                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
9934
9935         /* invalid factor range or not */
9936         for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
9937         {
9938                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
9939                         debug_error("Invalid factor! (valid factor:0~1.0)\n");
9940                         return MM_ERROR_INVALID_ARGUMENT;
9941                 }
9942         }
9943
9944         /* not support to set other value into each channel */
9945         if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
9946                 return MM_ERROR_INVALID_ARGUMENT;
9947
9948         /* Save volume to handle. Currently the first array element will be saved. */
9949         player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
9950
9951         /* check pipeline handle */
9952         if ( ! player->pipeline || ! player->pipeline->audiobin )
9953         {
9954                 debug_log("audiobin is not created yet\n");
9955                 debug_log("but, current stored volume will be set when it's created.\n");
9956
9957                 /* NOTE : stored volume will be used in create_audiobin
9958                  * returning MM_ERROR_NONE here makes application to able to
9959                  * set volume at anytime.
9960                  */
9961                 return MM_ERROR_NONE;
9962         }
9963
9964         /* setting volume to volume element */
9965         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
9966
9967         if ( vol_element )
9968         {
9969                 debug_log("volume is set [%f]\n", player->sound.volume);
9970                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
9971         }
9972
9973         MMPLAYER_FLEAVE();
9974
9975         return MM_ERROR_NONE;
9976 }
9977
9978
9979 int
9980 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
9981 {
9982         mm_player_t* player = (mm_player_t*) hplayer;
9983         int i = 0;
9984
9985         MMPLAYER_FENTER();
9986
9987         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9988         return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
9989
9990         /* returning stored volume */
9991         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
9992                 volume->level[i] = player->sound.volume;
9993
9994         MMPLAYER_FLEAVE();
9995
9996         return MM_ERROR_NONE;
9997 }
9998
9999
10000
10001 int
10002 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
10003 {
10004         mm_player_t* player = (mm_player_t*) hplayer;
10005         GstElement* vol_element = NULL;
10006
10007         MMPLAYER_FENTER();
10008
10009         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10010
10011         /* mute value shoud 0 or 1 */
10012         if ( mute != 0 && mute != 1 )
10013         {
10014                 debug_error("bad mute value\n");
10015
10016                 /* FIXIT : definitly, we need _BAD_PARAM error code */
10017                 return MM_ERROR_INVALID_ARGUMENT;
10018         }
10019
10020         player->sound.mute = mute;
10021
10022         /* just hold mute value if pipeline is not ready */
10023         if ( !player->pipeline || !player->pipeline->audiobin )
10024         {
10025                 debug_log("pipeline is not ready. holding mute value\n");
10026                 return MM_ERROR_NONE;
10027         }
10028
10029         vol_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
10030
10031         /* NOTE : volume will only created when the bt is enabled */
10032         if ( vol_element )
10033         {
10034                 debug_log("mute : %d\n", mute);
10035                 g_object_set(vol_element, "mute", mute, NULL);
10036         }
10037         else
10038         {
10039                 debug_log("volume elemnet is not created. using volume in audiosink\n");
10040         }
10041
10042         MMPLAYER_FLEAVE();
10043
10044         return MM_ERROR_NONE;
10045 }
10046
10047 int
10048 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
10049 {
10050         mm_player_t* player = (mm_player_t*) hplayer;
10051
10052         MMPLAYER_FENTER();
10053
10054         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10055         return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
10056
10057         /* just hold mute value if pipeline is not ready */
10058         if ( !player->pipeline || !player->pipeline->audiobin )
10059         {
10060                 debug_log("pipeline is not ready. returning stored value\n");
10061                 *pmute = player->sound.mute;
10062                 return MM_ERROR_NONE;
10063         }
10064
10065         *pmute = player->sound.mute;
10066
10067         MMPLAYER_FLEAVE();
10068
10069         return MM_ERROR_NONE;
10070 }
10071
10072 int
10073 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
10074 {
10075         mm_player_t* player = (mm_player_t*) hplayer;
10076
10077         MMPLAYER_FENTER();
10078
10079         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10080
10081         player->video_stream_cb = callback;
10082         player->video_stream_cb_user_param = user_param;
10083         player->use_video_stream = TRUE;
10084         debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
10085
10086         MMPLAYER_FLEAVE();
10087
10088         return MM_ERROR_NONE;
10089 }
10090
10091 int
10092 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
10093 {
10094         mm_player_t* player = (mm_player_t*) hplayer;
10095
10096         MMPLAYER_FENTER();
10097
10098         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10099
10100         player->audio_stream_cb = callback;
10101         player->audio_stream_cb_user_param = user_param;
10102         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
10103
10104         MMPLAYER_FLEAVE();
10105
10106         return MM_ERROR_NONE;
10107 }
10108
10109 int
10110 _mmplayer_set_buffer_need_data_cb(MMHandleType hplayer, mm_player_buffer_need_data_callback callback, void *user_param) // @
10111 {
10112         mm_player_t* player = (mm_player_t*) hplayer;
10113
10114         MMPLAYER_FENTER();
10115
10116         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
10117         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
10118
10119         player->need_data_cb = callback;
10120         player->buffer_cb_user_param = user_param;
10121
10122         debug_log("buffer need dataHandle value is %p : %p\n", player, player->need_data_cb);
10123
10124         MMPLAYER_FLEAVE();
10125
10126         return MM_ERROR_NONE;
10127 }
10128
10129 int
10130 _mmplayer_set_buffer_enough_data_cb(MMHandleType hplayer, mm_player_buffer_enough_data_callback callback, void *user_param) // @
10131 {
10132         mm_player_t* player = (mm_player_t*) hplayer;
10133
10134         MMPLAYER_FENTER();
10135
10136         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
10137         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
10138
10139         player->enough_data_cb = callback;
10140         player->buffer_cb_user_param = user_param;
10141
10142         debug_log("buffer enough data cb Handle value is %p : %p\n", player, player->enough_data_cb);
10143
10144         MMPLAYER_FLEAVE();
10145
10146         return MM_ERROR_NONE;
10147 }
10148
10149 int
10150 _mmplayer_set_buffer_seek_data_cb(MMHandleType hplayer, mm_player_buffer_seek_data_callback callback, void *user_param) // @
10151 {
10152         mm_player_t* player = (mm_player_t*) hplayer;
10153
10154         MMPLAYER_FENTER();
10155
10156         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
10157         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
10158
10159         player->seek_data_cb = callback;
10160         player->buffer_cb_user_param = user_param;
10161
10162         debug_log("buffer seek data cb Handle value is %p : %p\n", player, player->seek_data_cb);
10163
10164         MMPLAYER_FLEAVE();
10165
10166         return MM_ERROR_NONE;
10167 }
10168
10169 int
10170 __mmplayer_start_streaming_ext(mm_player_t *player)
10171 {
10172         gint ret = MM_ERROR_NONE;
10173
10174         MMPLAYER_FENTER();
10175         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10176
10177         if (MMPLAYER_IS_HTTP_PD(player))
10178         {
10179                 if ( !player->pd_downloader )
10180                 {
10181                         ret = __mmplayer_realize_streaming_ext(player);
10182
10183                         if ( ret != MM_ERROR_NONE)
10184                         {
10185                                 debug_error ("failed to realize streaming ext\n");
10186                                 return ret;
10187                         }
10188                 }
10189
10190                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
10191                 {
10192                         ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
10193                         if ( !ret )
10194                         {
10195                                 debug_error ("ERROR while starting PD...\n");
10196                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
10197                         }
10198                         ret = MM_ERROR_NONE;
10199                 }
10200         }
10201
10202         MMPLAYER_FLEAVE();
10203         return ret;
10204 }
10205
10206 int
10207 _mmplayer_start(MMHandleType hplayer) // @
10208 {
10209         mm_player_t* player = (mm_player_t*) hplayer;
10210         gint ret = MM_ERROR_NONE;
10211
10212         MMPLAYER_FENTER();
10213
10214         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10215
10216         /* check current state */
10217         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
10218
10219         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
10220         if ( ret != MM_ERROR_NONE )
10221         {
10222                 debug_error("failed to set asm state to PLAYING\n");
10223                 return ret;
10224         }
10225
10226         /* NOTE : we should check and create pipeline again if not created as we destroy
10227          * whole pipeline when stopping in streamming playback
10228          */
10229         if ( ! player->pipeline )
10230         {
10231                 ret = __gst_realize( player );
10232                 if ( MM_ERROR_NONE != ret )
10233                 {
10234                         debug_error("failed to realize before starting. only in streamming\n");
10235                         /* unlock */
10236                         return ret;
10237                 }
10238         }
10239
10240         ret = __mmplayer_start_streaming_ext(player);
10241         if ( ret != MM_ERROR_NONE )
10242         {
10243                 debug_error("failed to start streaming ext \n");
10244         }
10245
10246         /* start pipeline */
10247         ret = __gst_start( player );
10248         if ( ret != MM_ERROR_NONE )
10249         {
10250                 debug_error("failed to start player.\n");
10251         }
10252
10253         MMPLAYER_FLEAVE();
10254
10255         return ret;
10256 }
10257
10258 /* NOTE: post "not supported codec message" to application
10259  * when one codec is not found during AUTOPLUGGING in MSL.
10260  * So, it's separated with error of __mmplayer_gst_callback().
10261  * And, if any codec is not found, don't send message here.
10262  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
10263  */
10264 int
10265 __mmplayer_handle_missed_plugin(mm_player_t* player)
10266 {
10267         MMMessageParamType msg_param;
10268         memset (&msg_param, 0, sizeof(MMMessageParamType));
10269         gboolean post_msg_direct = FALSE;
10270
10271         MMPLAYER_FENTER();
10272
10273         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10274
10275         debug_log("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
10276                         player->not_supported_codec, player->can_support_codec);
10277
10278         if( player->not_found_demuxer )
10279         {
10280                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
10281                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
10282
10283                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10284                 MMPLAYER_FREEIF(msg_param.data);
10285
10286                 return MM_ERROR_NONE;
10287         }
10288
10289         if (player->not_supported_codec)
10290         {
10291                 if ( player->can_support_codec ) // There is one codec to play
10292                 {
10293                         post_msg_direct = TRUE;
10294                 }
10295                 else
10296                 {
10297                         if ( player->pipeline->audiobin ) // Some content has only PCM data in container.
10298                                 post_msg_direct = TRUE;
10299                 }
10300
10301                 if ( post_msg_direct )
10302                 {
10303                         MMMessageParamType msg_param;
10304                         memset (&msg_param, 0, sizeof(MMMessageParamType));
10305
10306                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
10307                         {
10308                                 debug_warning("not found AUDIO codec, posting error code to application.\n");
10309
10310                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
10311                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
10312                         }
10313                         else if ( player->not_supported_codec ==  MISSING_PLUGIN_VIDEO )
10314                         {
10315                                 debug_warning("not found VIDEO codec, posting error code to application.\n");
10316
10317                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
10318                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
10319                         }
10320
10321                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10322
10323                         MMPLAYER_FREEIF(msg_param.data);
10324
10325                         return MM_ERROR_NONE;
10326                 }
10327                 else // no any supported codec case
10328                 {
10329                         debug_warning("not found any codec, posting error code to application.\n");
10330
10331                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
10332                         {
10333                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
10334                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
10335                         }
10336                         else
10337                         {
10338                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
10339                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
10340                         }
10341
10342                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10343
10344                         MMPLAYER_FREEIF(msg_param.data);
10345                 }
10346         }
10347
10348         MMPLAYER_FLEAVE();
10349
10350         return MM_ERROR_NONE;
10351 }
10352
10353 static void __mmplayer_check_pipeline(mm_player_t* player)
10354 {
10355         GstState element_state = GST_STATE_VOID_PENDING;
10356         GstState element_pending_state = GST_STATE_VOID_PENDING;
10357         gint timeout = 0;
10358         int ret = MM_ERROR_NONE;
10359
10360         if (player->pp_rebuilding)
10361         {
10362                 debug_warning("pipeline is under construction.\n");
10363
10364                 MMPLAYER_PLAYBACK_LOCK(player);
10365                 MMPLAYER_PLAYBACK_UNLOCK(player);
10366
10367                 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
10368
10369                 /* wait for state transition */
10370                 ret = gst_element_get_state( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND );
10371
10372                 if ( ret == GST_STATE_CHANGE_FAILURE )
10373                 {
10374                         debug_error("failed to change pipeline state within %d sec\n", timeout );
10375                 }
10376         }
10377 }
10378
10379 /* NOTE : it should be able to call 'stop' anytime*/
10380 int
10381 _mmplayer_stop(MMHandleType hplayer) // @
10382 {
10383         mm_player_t* player = (mm_player_t*)hplayer;
10384         int ret = MM_ERROR_NONE;
10385
10386         MMPLAYER_FENTER();
10387
10388         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10389
10390         /* check current state */
10391         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
10392
10393         /* check pipline building state */
10394         __mmplayer_check_pipeline(player);
10395
10396         /* NOTE : application should not wait for EOS after calling STOP */
10397         __mmplayer_cancel_eos_timer( player );
10398
10399         __mmplayer_unrealize_streaming_ext(player);
10400
10401         /* reset */
10402         player->doing_seek = FALSE;
10403
10404         /* stop pipeline */
10405         ret = __gst_stop( player );
10406
10407         if ( ret != MM_ERROR_NONE )
10408         {
10409                 debug_error("failed to stop player.\n");
10410         }
10411
10412         MMPLAYER_FLEAVE();
10413
10414         return ret;
10415 }
10416
10417 int
10418 _mmplayer_pause(MMHandleType hplayer) // @
10419 {
10420         mm_player_t* player = (mm_player_t*)hplayer;
10421         GstFormat fmt = GST_FORMAT_TIME;
10422         gint64 pos_msec = 0;
10423         gboolean async = FALSE;
10424         gint ret = MM_ERROR_NONE;
10425
10426         MMPLAYER_FENTER();
10427
10428         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10429
10430         /* check current state */
10431         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
10432
10433         /* check pipline building state */
10434         __mmplayer_check_pipeline(player);
10435
10436         switch (MMPLAYER_CURRENT_STATE(player))
10437         {
10438                 case MM_PLAYER_STATE_READY:
10439                 {
10440                         /* check prepare async or not.
10441                          * In the case of streaming playback, it's recommned to avoid blocking wait.
10442                          */
10443                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10444                         debug_log("prepare working mode : %s", (async ? "async" : "sync"));
10445                 }
10446                 break;
10447
10448                 case MM_PLAYER_STATE_PLAYING:
10449                 {
10450                         /* NOTE : store current point to overcome some bad operation
10451                         * ( returning zero when getting current position in paused state) of some
10452                         * elements
10453                         */
10454                         if ( !gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &pos_msec))
10455                                 debug_warning("getting current position failed in paused\n");
10456
10457                         player->last_position = pos_msec;
10458                 }
10459                 break;
10460         }
10461
10462         /* pause pipeline */
10463         ret = __gst_pause( player, async );
10464
10465         if ( ret != MM_ERROR_NONE )
10466         {
10467                 debug_error("failed to pause player. ret : 0x%x\n", ret);
10468         }
10469
10470         MMPLAYER_FLEAVE();
10471
10472         return ret;
10473 }
10474
10475 int
10476 _mmplayer_resume(MMHandleType hplayer)
10477 {
10478         mm_player_t* player = (mm_player_t*)hplayer;
10479         int ret = MM_ERROR_NONE;
10480         gboolean async = FALSE;
10481
10482         MMPLAYER_FENTER();
10483
10484         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10485
10486         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
10487         if ( ret )
10488         {
10489                 debug_error("failed to set asm state to PLAYING\n");
10490                 return ret;
10491         }
10492
10493         /* check current state */
10494         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
10495
10496         /* resume pipeline */
10497         ret = __gst_resume( player, async );
10498
10499         if ( ret != MM_ERROR_NONE )
10500         {
10501                 debug_error("failed to resume player.\n");
10502         }
10503
10504         MMPLAYER_FLEAVE();
10505
10506         return ret;
10507 }
10508
10509 int
10510 __mmplayer_set_play_count(mm_player_t* player, gint count)
10511 {
10512         MMHandleType attrs = 0;
10513
10514         MMPLAYER_FENTER();
10515
10516         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10517
10518         attrs =  MMPLAYER_GET_ATTRS(player);
10519         if ( !attrs )
10520         {
10521                 debug_error("fail to get attributes.\n");
10522                 return MM_ERROR_PLAYER_INTERNAL;
10523         }
10524
10525         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
10526         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
10527                 debug_error("failed to commit\n");
10528
10529         MMPLAYER_FLEAVE();
10530
10531         return  MM_ERROR_NONE;
10532 }
10533
10534 int
10535 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
10536 {
10537         mm_player_t* player = (mm_player_t*)hplayer;
10538         gint64 start_pos = 0;
10539         gint64 end_pos = 0;
10540         gint infinity = -1;
10541
10542         MMPLAYER_FENTER();
10543
10544         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10545         return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
10546
10547         player->section_repeat = TRUE;
10548         player->section_repeat_start = start;
10549         player->section_repeat_end = end;
10550
10551         start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
10552         end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
10553
10554         __mmplayer_set_play_count( player, infinity );
10555
10556         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10557                                         player->playback_rate,
10558                                         GST_FORMAT_TIME,
10559                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10560                                         GST_SEEK_TYPE_SET, start_pos,
10561                                         GST_SEEK_TYPE_SET, end_pos)))
10562         {
10563                 debug_error("failed to activate section repeat\n");
10564
10565                 return MM_ERROR_PLAYER_SEEK;
10566         }
10567
10568         debug_log("succeeded to set section repeat from %d to %d\n",
10569                 player->section_repeat_start, player->section_repeat_end);
10570
10571         MMPLAYER_FLEAVE();
10572
10573         return  MM_ERROR_NONE;
10574 }
10575
10576 static int
10577 __mmplayer_set_pcm_extraction(mm_player_t* player)
10578 {
10579         gint64 start_nsec = 0;
10580         gint64 end_nsec = 0;
10581         gint64 dur_nsec = 0;
10582         gint64 dur_msec = 0;
10583         GstFormat fmt = GST_FORMAT_TIME;
10584         int required_start = 0;
10585         int required_end = 0;
10586         int ret = 0;
10587
10588         MMPLAYER_FENTER();
10589
10590         return_val_if_fail( player, FALSE );
10591
10592         mm_attrs_multiple_get(player->attrs,
10593                 NULL,
10594                 "pcm_extraction_start_msec", &required_start,
10595                 "pcm_extraction_end_msec", &required_end,
10596                 NULL);
10597
10598         debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
10599
10600         if (required_start == 0 && required_end == 0)
10601         {
10602                 debug_log("extracting entire stream");
10603                 return MM_ERROR_NONE;
10604         }
10605         else if (required_start < 0 || required_start > required_end || required_end < 0 )
10606         {
10607                 debug_log("invalid range for pcm extraction");
10608                 return MM_ERROR_INVALID_ARGUMENT;
10609         }
10610
10611         /* get duration */
10612         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec);
10613         if ( !ret )
10614         {
10615                 debug_error("failed to get duration");
10616                 return MM_ERROR_PLAYER_INTERNAL;
10617         }
10618         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
10619
10620         if (dur_msec < required_end) // FIXME
10621         {
10622                 debug_log("invalid end pos for pcm extraction");
10623                 return MM_ERROR_INVALID_ARGUMENT;
10624         }
10625
10626         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
10627         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
10628
10629         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10630                                         1.0,
10631                                         GST_FORMAT_TIME,
10632                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10633                                         GST_SEEK_TYPE_SET, start_nsec,
10634                                         GST_SEEK_TYPE_SET, end_nsec)))
10635         {
10636                 debug_error("failed to seek for pcm extraction\n");
10637
10638                 return MM_ERROR_PLAYER_SEEK;
10639         }
10640
10641         debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
10642
10643         MMPLAYER_FLEAVE();
10644
10645         return MM_ERROR_NONE;
10646 }
10647
10648 int
10649 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
10650 {
10651         mm_player_t* player = (mm_player_t*)hplayer;
10652         gint64 cur_pos = 0;
10653         GstFormat fmt  = GST_FORMAT_TIME;
10654         gint onetime = 1;
10655
10656         MMPLAYER_FENTER();
10657
10658         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10659
10660         player->section_repeat = FALSE;
10661
10662         __mmplayer_set_play_count( player, onetime );
10663
10664         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &cur_pos);
10665
10666         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10667                                         1.0,
10668                                         GST_FORMAT_TIME,
10669                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10670                                         GST_SEEK_TYPE_SET, cur_pos,
10671                                         GST_SEEK_TYPE_SET, player->duration )))
10672         {
10673                 debug_error("failed to deactivate section repeat\n");
10674
10675                 return MM_ERROR_PLAYER_SEEK;
10676         }
10677
10678         MMPLAYER_FENTER();
10679
10680         return MM_ERROR_NONE;
10681 }
10682
10683 int
10684 _mmplayer_set_playspeed(MMHandleType hplayer, float rate)
10685 {
10686         mm_player_t* player = (mm_player_t*)hplayer;
10687         signed long long pos_msec = 0;
10688         int ret = MM_ERROR_NONE;
10689         int mute = FALSE;
10690         GstFormat format =GST_FORMAT_TIME;
10691         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
10692         MMPLAYER_FENTER();
10693
10694         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
10695         return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
10696
10697         /* The sound of video is not supported under 0.0 and over 2.0. */
10698         if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
10699         {
10700                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
10701                         mute = TRUE;
10702         }
10703         _mmplayer_set_mute(hplayer, mute);
10704
10705         if (player->playback_rate == rate)
10706                 return MM_ERROR_NONE;
10707
10708         /* If the position is reached at start potion during fast backward, EOS is posted.
10709          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
10710          * */
10711         player->playback_rate = rate;
10712
10713         current_state = MMPLAYER_CURRENT_STATE(player);
10714
10715         if ( current_state != MM_PLAYER_STATE_PAUSED )
10716                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &pos_msec);
10717
10718         debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
10719
10720         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
10721                 || ( ! ret ))
10722                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
10723         {
10724                 debug_warning("returning last point : %lld\n", player->last_position );
10725                 pos_msec = player->last_position;
10726         }
10727
10728         if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10729                                 rate,
10730                                 GST_FORMAT_TIME,
10731                                 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10732                                 //( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT),
10733                                 GST_SEEK_TYPE_SET, pos_msec,
10734                                 //GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
10735                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)))
10736         {
10737                 debug_error("failed to set speed playback\n");
10738                 return MM_ERROR_PLAYER_SEEK;
10739         }
10740
10741         debug_log("succeeded to set speed playback as %0.1f\n", rate);
10742
10743         MMPLAYER_FLEAVE();
10744
10745         return MM_ERROR_NONE;;
10746 }
10747
10748 int
10749 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
10750 {
10751         mm_player_t* player = (mm_player_t*)hplayer;
10752         int ret = MM_ERROR_NONE;
10753
10754         MMPLAYER_FENTER();
10755
10756         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10757
10758         ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
10759
10760         MMPLAYER_FLEAVE();
10761
10762         return ret;
10763 }
10764
10765 int
10766 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
10767 {
10768         mm_player_t* player = (mm_player_t*)hplayer;
10769         int ret = MM_ERROR_NONE;
10770
10771         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10772
10773         ret = __gst_get_position ( player, format, position );
10774
10775         return ret;
10776 }
10777
10778 int
10779 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
10780 {
10781         mm_player_t* player = (mm_player_t*)hplayer;
10782         int ret = MM_ERROR_NONE;
10783
10784         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10785
10786         ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
10787
10788         return ret;
10789 }
10790
10791 int
10792 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
10793 {
10794         mm_player_t* player = (mm_player_t*)hplayer;
10795         int ret = MM_ERROR_NONE;
10796
10797         MMPLAYER_FENTER();
10798
10799         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10800
10801         ret = __gst_adjust_subtitle_position(player, format, position);
10802
10803         MMPLAYER_FLEAVE();
10804
10805         return ret;
10806 }
10807
10808 static gboolean
10809 __mmplayer_is_midi_type( gchar* str_caps)
10810 {
10811         if ( ( g_strrstr(str_caps, "audio/midi") ) ||
10812                 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
10813                 ( g_strrstr(str_caps, "application/x-smaf") ) ||
10814                 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
10815                 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
10816                 ( g_strrstr(str_caps, "audio/xmf") ) ||
10817                 ( g_strrstr(str_caps, "audio/mxmf") ) )
10818         {
10819                 debug_log("midi\n");
10820
10821                 return TRUE;
10822         }
10823
10824         return FALSE;
10825 }
10826
10827 static gboolean
10828 __mmplayer_is_only_mp3_type (gchar *str_caps)
10829 {
10830         if (g_strrstr(str_caps, "application/x-id3") ||
10831                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
10832         {
10833                 return TRUE;
10834         }
10835         return FALSE;
10836 }
10837
10838 /* try to use ALP decoder first instead of selected decoder */
10839 static gboolean
10840 __mmplayer_is_omx_decoder_type (mm_player_t* player)
10841 {
10842 #define MIN_THRESHOLD_SIZE  320 * 1024 // 320K
10843         gboolean ret = FALSE;
10844         gchar* path = NULL;
10845         guint64 data_size = 0;
10846         struct stat sb;
10847
10848         return_val_if_fail (player, FALSE);
10849
10850         /* consider mp3 audio only */
10851         if ((!MMPLAYER_IS_STREAMING(player)) &&
10852                 (__mmplayer_is_only_mp3_type(player->type)))
10853         {
10854                 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
10855
10856                 if (stat(path, &sb) == 0)
10857                 {
10858                         data_size = (guint64)sb.st_size;
10859
10860                         if (data_size > MIN_THRESHOLD_SIZE)
10861                         {
10862                                 ret = TRUE;
10863                         }
10864                 }
10865         }
10866
10867         debug_log ("need to select omx_decoder ? [%s]\n", (ret)?"YES":"NO");
10868         return ret;
10869 }
10870
10871 static void
10872 __mmplayer_set_audio_attrs (mm_player_t* player, GstCaps* caps)
10873 {
10874         GstStructure* caps_structure = NULL;
10875         gint samplerate = 0;
10876         gint channels = 0;
10877
10878         MMPLAYER_FENTER();
10879         return_if_fail (player && caps);
10880
10881         caps_structure = gst_caps_get_structure(caps, 0);
10882
10883         /* set stream information */
10884         gst_structure_get_int (caps_structure, "rate", &samplerate);
10885         mm_attrs_set_int_by_name (player->attrs, "content_audio_samplerate", samplerate);
10886
10887         gst_structure_get_int (caps_structure, "channels", &channels);
10888         mm_attrs_set_int_by_name (player->attrs, "content_audio_channels", channels);
10889
10890         debug_log ("audio samplerate : %d       channels : %d\n", samplerate, channels);
10891 }
10892
10893 static void
10894 __mmplayer_typefind_have_type(  GstElement *tf, guint probability,  // @
10895 GstCaps *caps, gpointer data)
10896 {
10897         mm_player_t* player = (mm_player_t*)data;
10898         GstPad* pad = NULL;
10899
10900         MMPLAYER_FENTER();
10901
10902         return_if_fail( player && tf && caps );
10903
10904         /* store type string */
10905         MMPLAYER_FREEIF(player->type);
10906         player->type = gst_caps_to_string(caps);
10907         if (player->type)
10908                 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
10909
10910         if ( (!MMPLAYER_IS_WFD_STREAMING( player )) &&
10911                  (!MMPLAYER_IS_RTSP_STREAMING( player )) &&
10912                  (g_strrstr(player->type, "audio/x-raw-int")))
10913         {
10914                 debug_error("not support media format\n");
10915
10916                 if (player->msg_posted == FALSE)
10917                 {
10918                         MMMessageParamType msg_param;
10919                         memset (&msg_param, 0, sizeof(MMMessageParamType));
10920
10921                         msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
10922                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10923
10924                         /* don't post more if one was sent already */
10925                         player->msg_posted = TRUE;
10926                 }
10927                 return;
10928         }
10929
10930         /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
10931         if ( __mmplayer_is_midi_type(player->type))
10932         {
10933                 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
10934                 player->bypass_audio_effect = TRUE;
10935         }
10936         else if ( g_strrstr(player->type, "application/x-hls"))
10937         {
10938                 /* If it can't know exact type when it parses uri because of redirection case,
10939                   * it will be fixed by typefinder here.
10940                   */
10941                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
10942         }
10943         else if ( g_strrstr(player->type, "application/dash+xml"))
10944         {
10945                 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
10946         }
10947
10948         pad = gst_element_get_static_pad(tf, "src");
10949         if ( !pad )
10950         {
10951                 debug_error("fail to get typefind src pad.\n");
10952                 return;
10953         }
10954
10955         if (player->use_decodebin)
10956         {
10957                 if(!__mmplayer_try_to_plug_decodebin( player, pad, caps ))
10958                 {
10959                         gboolean async = FALSE;
10960                         debug_error("failed to autoplug %s\n", player->type);
10961
10962                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10963
10964                         if ( async && player->msg_posted == FALSE )
10965                         {
10966                                 __mmplayer_handle_missed_plugin( player );
10967                         }
10968
10969                         goto DONE;
10970                 }
10971         }
10972         else
10973         {
10974                 /* try to plug */
10975                 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
10976                 {
10977                         gboolean async = FALSE;
10978                         debug_error("failed to autoplug %s\n", player->type);
10979
10980                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10981
10982                         if ( async && player->msg_posted == FALSE )
10983                         {
10984                                 __mmplayer_handle_missed_plugin( player );
10985                         }
10986
10987                         goto DONE;
10988                 }
10989
10990                 /* finish autopluging if no dynamic pad waiting */
10991                 if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
10992                 {
10993                         if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
10994                         {
10995                                 __mmplayer_pipeline_complete( NULL, (gpointer)player );
10996                         }
10997                 }
10998         }
10999
11000 DONE:
11001         gst_object_unref( GST_OBJECT(pad) );
11002
11003         MMPLAYER_FLEAVE();
11004
11005         return;
11006 }
11007
11008 #ifdef _MM_PLAYER_ALP_PARSER
11009 void check_name (void *data, void *user_data)
11010 {
11011         mm_player_t* player = user_data;
11012
11013         if (g_strrstr((gchar*)data, "mpegaudioparse"))
11014         {
11015                 debug_log("mpegaudioparse - set alp-mp3dec\n");
11016                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "alp-mp3dec", TRUE, NULL);
11017         }
11018 }
11019 #endif
11020
11021 static GstElement *
11022 __mmplayer_create_decodebin (mm_player_t* player)
11023 {
11024         GstElement *decodebin = NULL;
11025
11026         MMPLAYER_FENTER();
11027
11028         /* create decodebin */
11029         decodebin = gst_element_factory_make("decodebin2", "decodebin2");
11030
11031         if (!decodebin)
11032         {
11033                 debug_error("fail to create decodebin\n");
11034                 goto ERROR;
11035         }
11036
11037         /* raw pad handling signal */
11038         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
11039                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
11040
11041         /* no-more-pad pad handling signal */
11042         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
11043                                                 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
11044
11045         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
11046                                                 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
11047
11048         /* This signal is emitted when a pad for which there is no further possible
11049            decoding is added to the decodebin.*/
11050         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
11051                                                 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player );
11052
11053         /* This signal is emitted whenever decodebin2 finds a new stream. It is emitted
11054            before looking for any elements that can handle that stream.*/
11055         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
11056                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
11057
11058         /* This signal is emitted whenever decodebin2 finds a new stream. It is emitted
11059            before looking for any elements that can handle that stream.*/
11060         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
11061                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
11062
11063         /* Once decodebin2 has found the possible GstElementFactory objects to try for
11064            caps on pad, this signal is emited. The purpose of the signal is for the
11065            application to perform additional sorting or filtering on the element factory
11066            array.*/
11067         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
11068                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_sort), player);
11069
11070         /* This signal is emitted once decodebin2 has finished decoding all the data.*/
11071         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
11072                                                 G_CALLBACK(__mmplayer_gst_decode_drained), player);
11073
11074         /* This signal is emitted when a element is added to the bin.*/
11075         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
11076                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
11077
11078 ERROR:
11079         return decodebin;
11080 }
11081
11082 static void
11083 __mmplayer_gst_id3_pad_added(GstElement *element, GstPad *pad, gpointer data)
11084 {
11085         mm_player_t* player = (mm_player_t*)data;
11086         GstCaps *caps = NULL;
11087         gchar *caps_str = NULL;
11088
11089         MMPLAYER_FENTER();
11090         return_if_fail (player && pad);
11091
11092         caps = gst_pad_get_caps(pad);
11093         caps_str = gst_caps_to_string(caps);
11094
11095         debug_log("pad %s:%s, caps %s", GST_DEBUG_PAD_NAME(pad), caps_str);
11096         __mmplayer_try_to_plug_decodebin(player, pad, caps);
11097
11098         MMPLAYER_FREEIF( caps_str );
11099         gst_caps_unref(caps);
11100
11101         MMPLAYER_FLEAVE();
11102 }
11103
11104 static gboolean
11105 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
11106 {
11107         MMPlayerGstElement* mainbin = NULL;
11108         GstElement* decodebin2 = NULL;
11109         GstElement* queue2 = NULL;
11110         GstElement* id3demux = NULL;
11111
11112         GstPad* sinkpad = NULL;
11113         GstPad* qsrcpad= NULL;
11114         gchar *caps_str = NULL;
11115
11116         GstFormat fmt  = GST_FORMAT_BYTES;
11117         gint64 dur_bytes = 0L;
11118         gchar* file_buffering_path = NULL;
11119         gboolean use_file_buffer = FALSE;
11120
11121         guint max_buffer_size_bytes = 0;
11122         gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
11123
11124         MMPLAYER_FENTER();
11125         return_val_if_fail (player && player->pipeline && player->pipeline->mainbin, FALSE);
11126
11127         mainbin = player->pipeline->mainbin;
11128
11129         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
11130                 (MMPLAYER_IS_HTTP_STREAMING(player)))
11131         {
11132                 debug_log ("creating http streaming buffering queue (queue2)\n");
11133
11134                 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
11135                 {
11136                         debug_error ("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
11137                 }
11138                 else
11139             {
11140                         if (!mainbin[MMPLAYER_M_ID3DEMUX].gst)
11141                         {
11142                                 caps_str = gst_caps_to_string(caps);
11143                                 if (g_strrstr(caps_str, "application/x-id3"))
11144                                 {
11145                                         debug_log("create id3demux in front of queue2 \n");
11146
11147                                         id3demux = gst_element_factory_make ("id3demux", NULL);
11148                                         if (!id3demux)
11149                                         {
11150                                                 debug_error ("failed to create buffering id3demux element\n");
11151                                                 goto ERROR;
11152                                         }
11153
11154                                         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(id3demux), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
11155                                                                                 G_CALLBACK(__mmplayer_gst_id3_pad_added), player);
11156
11157                                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), id3demux))
11158                                         {
11159                                                 debug_error("failed to add id3demux\n");
11160                                                 goto ERROR;
11161                                         }
11162
11163                                         sinkpad = gst_element_get_static_pad(id3demux, "sink");
11164
11165                                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11166                                         {
11167                                                 debug_error("failed to link buffering queue\n");
11168                                                 goto ERROR;
11169                                         }
11170
11171                                         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (id3demux))
11172                                         {
11173                                                 debug_error("failed to sync id3demux state with parent\n");
11174                                                 goto ERROR;
11175                                         }
11176
11177                                         mainbin[MMPLAYER_M_ID3DEMUX].id = MMPLAYER_M_ID3DEMUX;
11178                                         mainbin[MMPLAYER_M_ID3DEMUX].gst = id3demux;
11179
11180                                         gst_object_unref(GST_OBJECT(sinkpad));
11181                                         MMPLAYER_FREEIF( caps_str );
11182
11183                                         MMPLAYER_FLEAVE();
11184                                         return TRUE;
11185                                 }
11186
11187                                 MMPLAYER_FREEIF( caps_str );
11188                         }
11189
11190                         queue2 = gst_element_factory_make ("queue2", "queue2");
11191                         if (!queue2)
11192                         {
11193                                 debug_error ("failed to create buffering queue element\n");
11194                                 goto ERROR;
11195                         }
11196
11197                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2))
11198                         {
11199                                 debug_error("failed to add buffering queue\n");
11200                                 goto ERROR;
11201                         }
11202
11203                         sinkpad = gst_element_get_static_pad(queue2, "sink");
11204                         qsrcpad = gst_element_get_static_pad(queue2, "src");
11205
11206                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11207                         {
11208                                 debug_error("failed to link buffering queue\n");
11209                                 goto ERROR;
11210                         }
11211
11212                         // if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
11213                         {
11214                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
11215                                         debug_error("fail to get duration.\n");
11216
11217                                 debug_log("dur_bytes = %lld\n", dur_bytes);
11218
11219                                 if (dur_bytes > 0)
11220                                 {
11221                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
11222                                         file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
11223                                 }
11224                                 else
11225                                 {
11226                                         dur_bytes = 0;
11227                                 }
11228                         }
11229
11230                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
11231                         // if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
11232                         if(!g_strrstr(player->type, "video/mpegts"))
11233                         {
11234                                 max_buffer_size_bytes = (use_file_buffer)?(player->ini.http_max_size_bytes):(5*1024*1024);
11235                                 debug_log("max_buffer_size_bytes = %d\n", max_buffer_size_bytes);
11236
11237                                 __mm_player_streaming_set_queue2(player->streamer,
11238                                                                                                 queue2,
11239                                                                                                 FALSE,
11240                                                                                                 max_buffer_size_bytes,
11241                                                                                                 player->ini.http_buffering_time,
11242                                                                                                 1.0,                                                            // no meaning
11243                                                                                                 player->ini.http_buffering_limit,       // no meaning
11244                                                                                                 use_file_buffer,
11245                                                                                                 file_buffering_path,
11246                                                                                                 (guint64)dur_bytes);
11247                         }
11248
11249                         MMPLAYER_FREEIF(file_buffering_path);
11250                         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (queue2))
11251                         {
11252                                 debug_error("failed to sync queue2 state with parent\n");
11253                                 goto ERROR;
11254                         }
11255
11256                         srcpad = qsrcpad;
11257
11258                         gst_object_unref(GST_OBJECT(sinkpad));
11259
11260                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
11261                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
11262                 }
11263         }
11264
11265         /* create decodebin */
11266         decodebin2 = __mmplayer_create_decodebin(player);
11267
11268         if (!decodebin2)
11269         {
11270                 debug_error("can not create autoplug element\n");
11271                 goto ERROR;
11272         }
11273
11274         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin2))
11275         {
11276                 debug_error("failed to add decodebin2\n");
11277                 goto ERROR;
11278         }
11279
11280         /* to force caps on the decodebin element and avoid reparsing stuff by
11281         * typefind. It also avoids a deadlock in the way typefind activates pads in
11282         * the state change */
11283         g_object_set (decodebin2, "sink-caps", caps, NULL);
11284
11285         sinkpad = gst_element_get_static_pad(decodebin2, "sink");
11286
11287         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11288         {
11289                 debug_error("failed to link decodebin2\n");
11290                 goto ERROR;
11291         }
11292
11293         gst_object_unref(GST_OBJECT(sinkpad));
11294
11295         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
11296         mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin2;
11297
11298         if ( ((!MMPLAYER_IS_HTTP_PD(player)) &&
11299             (MMPLAYER_IS_HTTP_STREAMING(player))) || MMPLAYER_IS_DASH_STREAMING (player))
11300         {
11301                 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
11302
11303                 g_object_set (G_OBJECT(decodebin2), "use-buffering", TRUE,
11304                                                                                         "high-percent", (gint)player->ini.http_buffering_limit,
11305                                                                                         "low-percent", 1,   // 1%
11306                                                                                         "max-size-bytes", MAX_DECODEBIN_BUFFER_BYTES,
11307                                                                                         "max-size-time", (guint64)(MAX_DECODEBIN_BUFFER_TIME * GST_SECOND),
11308                                                                                         "max-size-buffers", 0, NULL);  // disable or automatic
11309         }
11310
11311         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin2))
11312         {
11313                 debug_error("failed to sync decodebin2 state with parent\n");
11314                 goto ERROR;
11315         }
11316
11317         MMPLAYER_FLEAVE();
11318
11319         return TRUE;
11320
11321 ERROR:
11322
11323         MMPLAYER_FREEIF( caps_str );
11324
11325         if (sinkpad)
11326                 gst_object_unref(GST_OBJECT(sinkpad));
11327
11328         if (queue2)
11329         {
11330                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
11331                  * You need to explicitly set elements to the NULL state before
11332                  * dropping the final reference, to allow them to clean up.
11333                  */
11334                 gst_element_set_state(queue2, GST_STATE_NULL);
11335
11336                 /* And, it still has a parent "player".
11337                  * You need to let the parent manage the object instead of unreffing the object directly.
11338                  */
11339                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
11340                 gst_object_unref (queue2);
11341                 queue2 = NULL;
11342         }
11343
11344         if (id3demux)
11345         {
11346                 /* NOTE : Trying to dispose element id3demux, but it is in READY instead of the NULL state.
11347                  * You need to explicitly set elements to the NULL state before
11348                  * dropping the final reference, to allow them to clean up.
11349                  */
11350                 gst_element_set_state(id3demux, GST_STATE_NULL);
11351
11352                 /* And, it still has a parent "player".
11353                  * You need to let the parent manage the object instead of unreffing the object directly.
11354                  */
11355                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), id3demux);
11356                 gst_object_unref (id3demux);
11357                 id3demux = NULL;
11358         }
11359
11360         if (decodebin2)
11361         {
11362                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
11363                  * You need to explicitly set elements to the NULL state before
11364                  * dropping the final reference, to allow them to clean up.
11365                  */
11366                 gst_element_set_state(decodebin2, GST_STATE_NULL);
11367
11368                 /* And, it still has a parent "player".
11369                  * You need to let the parent manage the object instead of unreffing the object directly.
11370                  */
11371
11372                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin2);
11373                 gst_object_unref (decodebin2);
11374                 decodebin2 = NULL;
11375         }
11376
11377         return FALSE;
11378 }
11379
11380 /* it will return first created element */
11381 static gboolean
11382 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
11383 {
11384         MMPlayerGstElement* mainbin = NULL;
11385         const char* mime = NULL;
11386         const GList* item = NULL;
11387         const gchar* klass = NULL;
11388         GstCaps* res = NULL;
11389         gboolean skip = FALSE;
11390         GstPad* queue_pad = NULL;
11391         GstElement* queue = NULL;
11392         GstElement *element = NULL;
11393
11394         MMPLAYER_FENTER();
11395
11396         return_val_if_fail( player && player->pipeline && player->pipeline->mainbin, FALSE );
11397
11398         mainbin = player->pipeline->mainbin;
11399
11400         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
11401
11402         /* return if we got raw output */
11403         if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
11404                 || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup"))
11405         {
11406
11407                 element = (GstElement*)gst_pad_get_parent(pad);
11408 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
11409  * No queue will be added. I think it can caused breaking sound when playing raw audio
11410  * frames but there's no different. Decodebin also doesn't add with those wav fils.
11411  * Anyway, currentely raw-queue seems not necessary.
11412  */
11413 #if 1
11414                 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
11415                  * has linked. if so, we need to add queue for quality of output. note that
11416                  * decodebin also has same problem.
11417                  */
11418                 klass = gst_element_factory_get_klass( gst_element_get_factory(element) );
11419
11420                 /* add queue if needed */
11421                 if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
11422                         || g_strrstr(klass, "Parse")) &&  !g_str_has_prefix(mime, "text"))
11423                 {
11424                         debug_log("adding raw queue\n");
11425
11426                         queue = gst_element_factory_make("queue", NULL);
11427                         if ( ! queue )
11428                         {
11429                                 debug_warning("failed to create queue\n");
11430                                 goto ERROR;
11431                         }
11432
11433                         /* warmup */
11434                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
11435                         {
11436                                 debug_warning("failed to set state READY to queue\n");
11437                                 goto ERROR;
11438                         }
11439
11440                         /* add to pipeline */
11441                         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
11442                         {
11443                                 debug_warning("failed to add queue\n");
11444                                 goto ERROR;
11445                         }
11446
11447                         /* link queue */
11448                         queue_pad = gst_element_get_static_pad(queue, "sink");
11449
11450                         if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
11451                         {
11452                                 debug_warning("failed to link queue\n");
11453                                 goto ERROR;
11454                         }
11455                         gst_object_unref ( GST_OBJECT(queue_pad) );
11456                         queue_pad = NULL;
11457
11458                         /* running */
11459                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
11460                         {
11461                                 debug_warning("failed to set state READY to queue\n");
11462                                 goto ERROR;
11463                         }
11464
11465                         /* replace given pad to queue:src */
11466                         pad = gst_element_get_static_pad(queue, "src");
11467                         if ( ! pad )
11468                         {
11469                                 debug_warning("failed to get pad from queue\n");
11470                                 goto ERROR;
11471                         }
11472                 }
11473 #endif
11474                 /* check if player can do start continually */
11475                 MMPLAYER_CHECK_CMD_IF_EXIT(player);
11476
11477                 if(__mmplayer_link_sink(player,pad))
11478                         __mmplayer_gst_decode_callback(element, pad, player);
11479
11480                 gst_object_unref( GST_OBJECT(element));
11481                 element = NULL;
11482
11483                 return TRUE;
11484         }
11485
11486         item = player->factories;
11487         for(; item != NULL ; item = item->next)
11488         {
11489                 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
11490                 const GList *pads;
11491                 gint idx = 0;
11492
11493                 skip = FALSE;
11494
11495                 /* filtering exclude keyword */
11496                 for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
11497                 {
11498                         if ( g_strrstr(GST_PLUGIN_FEATURE_NAME (factory),
11499                                         player->ini.exclude_element_keyword[idx] ) )
11500                         {
11501                                 debug_warning("skipping [%s] by exculde keyword [%s]\n",
11502                                         GST_PLUGIN_FEATURE_NAME (factory),
11503                                         player->ini.exclude_element_keyword[idx] );
11504
11505                                 skip = TRUE;
11506                                 break;
11507                         }
11508                 }
11509
11510                 if ( MMPLAYER_IS_RTSP_STREAMING(player) && g_strrstr(GST_PLUGIN_FEATURE_NAME (factory), "omx_mpeg4dec"))
11511                 {
11512                         // omx decoder can not support mpeg4video data partitioned
11513                         // rtsp streaming didn't know mpeg4video data partitioned format
11514                         // so, if rtsp playback, player will skip omx_mpeg4dec.
11515                         debug_warning("skipping [%s] when rtsp streaming \n",
11516                                         GST_PLUGIN_FEATURE_NAME (factory));
11517
11518                         skip = TRUE;
11519                 }
11520
11521                 if ( skip ) continue;
11522
11523                 /* check factory class for filtering */
11524                 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory));
11525
11526                 /* NOTE : msl don't need to use image plugins.
11527                  * So, those plugins should be skipped for error handling.
11528                  */
11529                 if ( g_strrstr(klass, "Codec/Decoder/Image") )
11530                 {
11531                         debug_log("skipping [%s] by not required\n", GST_PLUGIN_FEATURE_NAME (factory));
11532                         continue;
11533                 }
11534
11535                 /* check pad compatability */
11536                 for(pads = gst_element_factory_get_static_pad_templates(factory);
11537                                         pads != NULL; pads=pads->next)
11538                 {
11539                         GstStaticPadTemplate *temp1 = pads->data;
11540                         GstCaps* static_caps = NULL;
11541
11542                         if( temp1->direction != GST_PAD_SINK ||
11543                                                 temp1->presence != GST_PAD_ALWAYS)
11544                                 continue;
11545
11546                         if ( GST_IS_CAPS( &temp1->static_caps.caps) )
11547                         {
11548                                 /* using existing caps */
11549                                 static_caps = gst_caps_ref( &temp1->static_caps.caps );
11550                         }
11551                         else
11552                         {
11553                                 /* create one */
11554                                 static_caps = gst_caps_from_string ( temp1->static_caps.string );
11555                         }
11556
11557                         res = gst_caps_intersect(caps, static_caps);
11558
11559                         gst_caps_unref( static_caps );
11560                         static_caps = NULL;
11561
11562                         if( res && !gst_caps_is_empty(res) )
11563                         {
11564                                 GstElement *new_element;
11565                                 GList *elements = player->parsers;
11566                                 char *name_template = g_strdup(temp1->name_template);
11567                                 gchar *name_to_plug = GST_PLUGIN_FEATURE_NAME(factory);
11568                                 gst_caps_unref(res);
11569
11570                                 /* check ALP Codec can be used or not */
11571                                 if ((g_strrstr(klass, "Codec/Decoder/Audio")))
11572                                 {
11573                                         /* consider mp3 audio only */
11574                                         if ( !MMPLAYER_IS_STREAMING(player) && __mmplayer_is_only_mp3_type(player->type) )
11575                                         {
11576                                                 /* try to use ALP decoder first instead of selected decoder */
11577                                                 GstElement *element = NULL;
11578                                                 GstElementFactory * element_facory;
11579                                                 gchar *path = NULL;
11580                                                 guint64 data_size = 0;
11581                                                 #define MIN_THRESHOLD_SIZE  320 * 1024 // 320K
11582                                                 struct stat sb;
11583
11584                                                 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
11585
11586                                                 if (stat(path, &sb) == 0)
11587                                                 {
11588                                                         data_size = (guint64)sb.st_size;
11589                                                 }
11590                                                 debug_log("file size : %u", data_size);
11591
11592                                                 if (data_size > MIN_THRESHOLD_SIZE)
11593                                                 {
11594                                                         debug_log("checking if ALP can be used or not");
11595                                                         element = gst_element_factory_make("omx_mp3dec", "omx mp3 decoder");
11596                                                         if ( element )
11597                                                         {
11598                                                                 /* check availability because multi-instance is not supported */
11599                                                                 GstStateChangeReturn ret = gst_element_set_state(element, GST_STATE_READY);
11600
11601                                                                 if (ret != GST_STATE_CHANGE_SUCCESS) // use just selected decoder
11602                                                                 {
11603                                                                         gst_object_unref (element);
11604                                                                 }
11605                                                                 else if (ret == GST_STATE_CHANGE_SUCCESS) // replace facotry to use omx
11606                                                                 {
11607                                                                         /* clean  */
11608                                                                         gst_element_set_state(element, GST_STATE_NULL);
11609                                                                         gst_object_unref (element);
11610
11611                                                                         element_facory = gst_element_factory_find("omx_mp3dec");
11612                                                                         /* replace, otherwise use selected thing instead */
11613                                                                         if (element_facory)
11614                                                                         {
11615                                                                                 factory = element_facory;
11616                                                                                 name_to_plug = GST_PLUGIN_FEATURE_NAME(factory);
11617                                                                         }
11618
11619                                                                         /* make parser alp mode */
11620                                                                         #ifdef _MM_PLAYER_ALP_PARSER
11621                                                                         g_list_foreach (player->parsers, check_name, player);
11622                                                                         #endif
11623                                                                 }
11624                                                         }
11625                                                 }
11626                                         }
11627                                 }
11628                                 else if ((g_strrstr(klass, "Codec/Decoder/Video")))
11629                                 {
11630                                         if ( g_strrstr(GST_PLUGIN_FEATURE_NAME(factory), "omx_") )
11631                                         {
11632                                                 char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
11633                                                 if (env != NULL)
11634                                                 {
11635                                                         if (strncasecmp(env, "yes", 3) == 0)
11636                                                         {
11637                                                                 debug_log("skipping [%s] by disabled\n", name_to_plug);
11638                                                                 MMPLAYER_FREEIF(name_template);
11639                                                                 continue;
11640                                                         }
11641                                                 }
11642                                         }
11643                                 }
11644
11645                                 debug_log("found %s to plug\n", name_to_plug);
11646
11647                                 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
11648                                 if ( ! new_element )
11649                                 {
11650                                         debug_error("failed to create element [%s]. continue with next.\n",
11651                                                 GST_PLUGIN_FEATURE_NAME (factory));
11652
11653                                         MMPLAYER_FREEIF(name_template);
11654
11655                                         continue;
11656                                 }
11657
11658                                 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
11659                                  * because parser can accept its own output as input.
11660                                  */
11661                                 if (g_strrstr(klass, "Parser"))
11662                                 {
11663                                         gchar *selected = NULL;
11664
11665                                         for ( ; elements; elements = g_list_next(elements))
11666                                         {
11667                                                 gchar *element_name = elements->data;
11668
11669                                                 if (g_strrstr(element_name, name_to_plug))
11670                                                 {
11671                                                         debug_log("but, %s already linked, so skipping it\n", name_to_plug);
11672                                                         skip = TRUE;
11673                                                 }
11674                                         }
11675
11676                                         if (skip)
11677                                         {
11678                                                 MMPLAYER_FREEIF(name_template);
11679                                                 continue;
11680                                         }
11681
11682                                         selected = g_strdup(name_to_plug);
11683                                         player->parsers = g_list_append(player->parsers, selected);
11684                                 }
11685
11686                                 /* store specific handles for futher control */
11687                                 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
11688                                 {
11689                                         /* FIXIT : first value will be overwritten if there's more
11690                                          * than 1 demuxer/parser
11691                                          */
11692                                         debug_log("plugged element is demuxer. take it\n");
11693                                         mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
11694                                         mainbin[MMPLAYER_M_DEMUX].gst = new_element;
11695
11696                                         /*Added for multi audio support */
11697                                         if(g_strrstr(klass, "Demux"))
11698                                         {
11699                                                 mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
11700                                                 mainbin[MMPLAYER_M_DEMUX_EX].gst = new_element;
11701
11702                                                 /* NOTE : workaround for bug in mpegtsdemux since doesn't emit
11703                                                 no-more-pad signal. this may cause wrong content attributes at PAUSED state
11704                                                 this code should be removed after mpegtsdemux is fixed */
11705                                                 if ( g_strrstr(GST_PLUGIN_FEATURE_NAME(factory), "mpegtsdemux") )
11706                                                 {
11707                                                         debug_warning("force no-more-pad to TRUE since mpegtsdemux os not giving no-more-pad signal. content attributes may wrong");
11708                                                         player->no_more_pad = TRUE;
11709                                                 }
11710                                         }
11711                                         if (g_strrstr(name_to_plug, "asfdemux")) // to support trust-zone only
11712                                         {
11713                                                 g_object_set(mainbin[MMPLAYER_M_DEMUX_EX].gst, "file-location", player->profile.uri,NULL);
11714                                         }
11715                                 }
11716                                 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
11717                                 {
11718                                         if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
11719                                         {
11720                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
11721                                                 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
11722                                                 mainbin[MMPLAYER_M_DEC1].gst = new_element;
11723                                         }
11724                                         else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
11725                                         {
11726                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
11727                                                 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
11728                                                 mainbin[MMPLAYER_M_DEC2].gst = new_element;
11729                                         }
11730                                         /* NOTE : IF one codec is found, add it to supported_codec and remove from
11731                                          * missing plugin. Both of them are used to check what's supported codec
11732                                          * before returning result of play start. And, missing plugin should be
11733                                          * updated here for multi track files.
11734                                          */
11735                                         if(g_str_has_prefix(mime, "video"))
11736                                         {
11737                                                 GstPad *src_pad = NULL;
11738                                                 GstPadTemplate *pad_templ = NULL;
11739                                                 GstCaps *caps = NULL;
11740                                                 gchar *caps_str = NULL;
11741
11742                                                 debug_log("found VIDEO decoder\n");
11743                                                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
11744                                                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
11745
11746                                                 src_pad = gst_element_get_static_pad (new_element, "src");
11747                                                 pad_templ = gst_pad_get_pad_template (src_pad);
11748                                                 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
11749
11750                                                 caps_str = gst_caps_to_string(caps);
11751
11752                                                 /* clean */
11753                                                 MMPLAYER_FREEIF( caps_str );
11754                                                 gst_object_unref (src_pad);
11755                                         }
11756                                         else if (g_str_has_prefix(mime, "audio"))
11757                                         {
11758                                                 debug_log("found AUDIO decoder\n");
11759                                                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
11760                                                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
11761                                         }
11762                                 }
11763
11764                                 if ( ! __mmplayer_close_link(player, pad, new_element,
11765                                                         name_template,gst_element_factory_get_static_pad_templates(factory)) )
11766                                 {
11767                                         MMPLAYER_FREEIF(name_template);
11768                                         if (player->keep_detecting_vcodec)
11769                                         continue;
11770
11771                                         /* Link is failed even though a supportable codec is found. */
11772                                         __mmplayer_check_not_supported_codec(player, klass, mime);
11773
11774                                         debug_error("failed to call _close_link\n");
11775                                         return FALSE;
11776                                 }
11777
11778                                 MMPLAYER_FREEIF(name_template);
11779                                 return TRUE;
11780                         }
11781
11782                         gst_caps_unref(res);
11783                         break;
11784                 }
11785         }
11786
11787         /* There is no available codec. */
11788         __mmplayer_check_not_supported_codec(player, klass, mime);
11789
11790         MMPLAYER_FLEAVE();
11791         return FALSE;
11792
11793 ERROR:
11794         /* release */
11795         if ( queue )
11796                 gst_object_unref( queue );
11797
11798         if ( queue_pad )
11799                 gst_object_unref( queue_pad );
11800
11801         if ( element )
11802                 gst_object_unref ( element );
11803
11804         return FALSE;
11805 }
11806
11807
11808 static int
11809 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
11810 {
11811         MMPLAYER_FENTER();
11812
11813         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
11814         return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
11815
11816         debug_log("class : %s, mime : %s \n", factory_class, mime );
11817
11818         /* add missing plugin */
11819         /* NOTE : msl should check missing plugin for image mime type.
11820          * Some motion jpeg clips can have playable audio track.
11821          * So, msl have to play audio after displaying popup written video format not supported.
11822          */
11823         if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
11824         {
11825                 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
11826                 {
11827                         debug_log("not found demuxer\n");
11828                         player->not_found_demuxer = TRUE;
11829                         player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
11830
11831                         goto DONE;
11832                 }
11833         }
11834
11835         if( !g_strrstr(factory_class, "Demuxer"))
11836         {
11837                 if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
11838                 {
11839                         debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
11840                                 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
11841
11842                         /* check that clip have multi tracks or not */
11843                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
11844                         {
11845                                 debug_log("video plugin is already linked\n");
11846                         }
11847                         else
11848                         {
11849                                 debug_warning("add VIDEO to missing plugin\n");
11850                                 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
11851                         }
11852                 }
11853                 else if ( g_str_has_prefix(mime, "audio") )
11854                 {
11855                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
11856                         {
11857                                 debug_log("audio plugin is already linked\n");
11858                         }
11859                         else
11860                         {
11861                                 debug_warning("add AUDIO to missing plugin\n");
11862                                 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
11863                         }
11864                 }
11865         }
11866
11867 DONE:
11868         MMPLAYER_FLEAVE();
11869
11870         return MM_ERROR_NONE;
11871 }
11872
11873
11874 static void
11875 __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
11876 {
11877     mm_player_t* player = (mm_player_t*)data;
11878
11879         MMPLAYER_FENTER();
11880
11881         return_if_fail( player );
11882
11883         /* remove fakesink. */
11884         if ( ! __mmplayer_gst_remove_fakesink( player,
11885         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
11886         {
11887                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
11888                  * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
11889                  * source element are not same. To overcome this situation, this function will called
11890                  * several places and several times. Therefore, this is not an error case.
11891                  */
11892                 return;
11893         }
11894
11895         debug_log("pipeline has completely constructed\n");
11896
11897         if ( ( player->ini.async_start ) &&
11898                 ( player->msg_posted == FALSE ) &&
11899                 ( player->cmd >= MMPLAYER_COMMAND_START ))
11900         {
11901                 __mmplayer_handle_missed_plugin( player );
11902         }
11903
11904         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complete" );
11905 }
11906
11907 static gboolean
11908 __mmplayer_verify_next_play_path(mm_player_t *player)
11909 {
11910         MMHandleType attrs = 0;
11911         MMPlayerParseProfile profile;
11912         gint uri_idx = 0, check_cnt = 0;
11913         char *uri = NULL;
11914         gint mode = MM_PLAYER_PD_MODE_NONE;
11915         gint count = 0;
11916         guint num_of_list = 0;
11917
11918         MMPLAYER_FENTER();
11919
11920         debug_log("checking for next play");
11921
11922         if (player->pipeline->textbin)
11923         {
11924                 debug_error("subtitle path is enabled. next play is not supported.\n");
11925                 goto ERROR;
11926         }
11927
11928         attrs = MMPLAYER_GET_ATTRS(player);
11929         if ( !attrs )
11930         {
11931                 debug_error("fail to get attributes.\n");
11932                 goto ERROR;
11933         }
11934
11935         /* seamless playback is supported in case of audio only */
11936         mm_attrs_get_int_by_name(attrs, "content_video_found", &mode);
11937         if (mode)
11938         {
11939                 debug_log("video found");
11940                 goto ERROR;
11941         }
11942
11943         if (mm_attrs_get_int_by_name (attrs, "pd_mode", &mode) == MM_ERROR_NONE)
11944         {
11945                 if (mode == TRUE)
11946                 {
11947                         debug_warning("pd mode\n");
11948                         goto ERROR;
11949                 }
11950         }
11951
11952         if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
11953         {
11954                 debug_error("can not get play count\n");
11955         }
11956
11957         num_of_list = g_list_length(player->uri_info.uri_list);
11958
11959         debug_log("repeat count = %d, num_of_list = %d\n", count, num_of_list);
11960
11961         if ( num_of_list == 0 )
11962         {
11963                 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE)
11964                 {
11965                         debug_error("can not get profile_uri\n");
11966                         goto ERROR;
11967                 }
11968
11969                 if (!uri)
11970                 {
11971                         debug_error("uri list is empty.\n");
11972                         goto ERROR;
11973                 }
11974
11975                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
11976                 debug_log("add original path : %s ", uri);
11977
11978                 num_of_list = 1;
11979                 uri= NULL;
11980         }
11981
11982         uri_idx = player->uri_info.uri_idx;
11983
11984         while(TRUE)
11985         {
11986                 check_cnt++;
11987
11988                 if (check_cnt > num_of_list)
11989                 {
11990                         debug_error("there is no valid uri.");
11991                         goto ERROR;
11992                 }
11993
11994                 debug_log("uri idx : %d / %d\n", uri_idx, num_of_list);
11995
11996                 if ( uri_idx < num_of_list-1 )
11997                 {
11998                         uri_idx++;
11999                 }
12000                 else
12001                 {
12002                         if ((count <= 1) && (count != -1))
12003                         {
12004                                 debug_log("no repeat.");
12005                                 goto ERROR;
12006                         }
12007                         else if ( count > 1 )   /* decrease play count */
12008                         {
12009                                 /* we successeded to rewind. update play count and then wait for next EOS */
12010                                 count--;
12011
12012                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
12013
12014                                 /* commit attribute */
12015                                 if ( mmf_attrs_commit ( attrs ) )
12016                                 {
12017                                         debug_error("failed to commit attribute\n");
12018                                 }
12019                         }
12020
12021                         /* count < 0 : repeat continually */
12022                         uri_idx = 0;
12023                 }
12024
12025                 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12026                 debug_log("uri idx : %d, uri = %s\n", uri_idx, uri);
12027
12028                 if (uri == NULL)
12029                 {
12030                         debug_warning("next uri does not exist\n");
12031                         continue;
12032                 }
12033
12034                 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE)
12035                 {
12036                         debug_error("failed to parse profile\n");
12037                         continue;
12038                 }
12039
12040                 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
12041                         (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP))
12042                 {
12043                         debug_warning("uri type is not supported (%d).", profile.uri_type);
12044                         continue;
12045                 }
12046
12047                 break;
12048         }
12049
12050         player->uri_info.uri_idx = uri_idx;
12051         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
12052
12053
12054         if (mmf_attrs_commit(player->attrs))
12055         {
12056                 debug_error("failed to commit.\n");
12057                 goto ERROR;
12058         }
12059
12060         debug_log("next uri %s (%d)\n", uri, uri_idx);
12061
12062         return TRUE;
12063
12064 ERROR:
12065
12066         debug_error("unable to play next path. EOS will be posted soon.\n");
12067         return FALSE;
12068 }
12069
12070 static void
12071 __mmplayer_initialize_next_play(mm_player_t *player)
12072 {
12073         int i;
12074
12075         MMPLAYER_FENTER();
12076
12077         player->needed_v_parser = FALSE;
12078         player->smooth_streaming = FALSE;
12079         player->videodec_linked = 0;
12080         player->audiodec_linked = 0;
12081         player->videosink_linked = 0;
12082         player->audiosink_linked = 0;
12083         player->textsink_linked = 0;
12084         player->is_external_subtitle_present = FALSE;
12085         player->not_supported_codec = MISSING_PLUGIN_NONE;
12086         player->can_support_codec = FOUND_PLUGIN_NONE;
12087         player->pending_seek.is_pending = FALSE;
12088         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
12089         player->pending_seek.pos = 0;
12090         player->msg_posted = FALSE;
12091         player->has_many_types = FALSE;
12092         player->no_more_pad = FALSE;
12093         player->is_drm_file = FALSE;
12094         player->not_found_demuxer = 0;
12095         player->doing_seek = FALSE;
12096         player->max_audio_channels = 0;
12097         player->is_subtitle_force_drop = FALSE;
12098         player->play_subtitle = FALSE;
12099         player->use_textoverlay = FALSE;
12100         player->adjust_subtitle_pos = 0;
12101
12102         player->updated_bitrate_count = 0;
12103         player->total_bitrate = 0;
12104         player->updated_maximum_bitrate_count = 0;
12105         player->total_maximum_bitrate = 0;
12106
12107         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
12108         {
12109                 player->bitrate[i] = 0;
12110                 player->maximum_bitrate[i] = 0;
12111         }
12112
12113         if (player->v_stream_caps)
12114         {
12115                 gst_caps_unref(player->v_stream_caps);
12116                 player->v_stream_caps = NULL;
12117         }
12118
12119         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
12120         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
12121
12122         /* clean found parsers */
12123         if (player->parsers)
12124         {
12125                 GList *parsers = player->parsers;
12126                 for ( ;parsers ; parsers = g_list_next(parsers))
12127                 {
12128                         gchar *name = parsers->data;
12129                         MMPLAYER_FREEIF(name);
12130                 }
12131                 g_list_free(player->parsers);
12132                 player->parsers = NULL;
12133         }
12134
12135         /* clean found audio decoders */
12136         if (player->audio_decoders)
12137         {
12138                 GList *a_dec = player->audio_decoders;
12139                 for ( ;a_dec ; a_dec = g_list_next(a_dec))
12140                 {
12141                         gchar *name = a_dec->data;
12142                         MMPLAYER_FREEIF(name);
12143                 }
12144                 g_list_free(player->audio_decoders);
12145                 player->audio_decoders = NULL;
12146         }
12147
12148         MMPLAYER_FLEAVE();
12149 }
12150
12151 static void
12152 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
12153 {
12154         MMPlayerGstElement *mainbin = NULL;
12155         MMMessageParamType msg_param = {0,};
12156         GstElement *element = NULL;
12157         MMHandleType attrs = 0;
12158         char *uri = NULL;
12159         enum MainElementID elemId = MMPLAYER_M_NUM;
12160
12161         MMPLAYER_FENTER();
12162
12163         if ((player->pipeline == NULL) ||
12164                 (player->pipeline->mainbin == NULL))
12165         {
12166                 debug_error("player is null.\n");
12167                 goto ERROR;
12168         }
12169
12170         mainbin = player->pipeline->mainbin;
12171         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
12172
12173         attrs = MMPLAYER_GET_ATTRS(player);
12174         if ( !attrs )
12175         {
12176                 debug_error("fail to get attributes.\n");
12177                 goto ERROR;
12178         }
12179
12180         /* Initialize Player values */
12181         __mmplayer_initialize_next_play(player);
12182
12183         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
12184
12185         if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE)
12186         {
12187                 debug_error("failed to parse profile\n");
12188                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
12189                 goto ERROR;
12190         }
12191
12192         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
12193                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player)))
12194         {
12195                 debug_error("it's dash or hls. not support.");
12196                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
12197                 goto ERROR;
12198         }
12199
12200         /* setup source */
12201         switch ( player->profile.uri_type )
12202         {
12203                 /* file source */
12204                 case MM_PLAYER_URI_TYPE_FILE:
12205                 {
12206
12207 #ifdef ENABLE_DRMSRC
12208
12209                         char* drmsrc = player->ini.name_of_drmsrc;
12210
12211                         debug_log("using [%s] for 'file://' handler.\n", drmsrc);
12212
12213                         element = gst_element_factory_make(drmsrc, "source");
12214                         if ( !element )
12215                         {
12216                                 debug_error("failed to create %s\n", drmsrc);
12217                                 break;
12218                         }
12219 #else
12220                         debug_log("using filesrc for 'file://' handler.\n");
12221
12222                         element = gst_element_factory_make("filesrc", "source");
12223
12224                         if ( !element )
12225                         {
12226                                 debug_error("failed to create filesrc\n");
12227                                 break;
12228                         }
12229 #endif
12230                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
12231                         break;
12232                 }
12233                 case MM_PLAYER_URI_TYPE_URL_HTTP:
12234                 {
12235                         gchar *user_agent, *proxy, *cookies, **cookie_list;
12236                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
12237                         user_agent = proxy = cookies = NULL;
12238                         cookie_list = NULL;
12239
12240                         element = gst_element_factory_make(player->ini.name_of_httpsrc, "http_streaming_source");
12241                         if ( !element )
12242                         {
12243                                 debug_error("failed to create http streaming source element[%s].\n", player->ini.name_of_httpsrc);
12244                                 break;
12245                         }
12246                         debug_log("using http streamming source [%s].\n", player->ini.name_of_httpsrc);
12247
12248                         /* get attribute */
12249                         mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
12250                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
12251                         mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
12252                         mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
12253
12254                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
12255                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
12256                         {
12257                                 debug_log("get timeout from ini\n");
12258                                 http_timeout = player->ini.http_timeout;
12259                         }
12260
12261                         /* get attribute */
12262                         secure_debug_log("location : %s\n", player->profile.uri);
12263                         secure_debug_log("cookies : %s\n", cookies);
12264                         secure_debug_log("proxy : %s\n", proxy);
12265                         secure_debug_log("user_agent :  %s\n", user_agent);
12266                         debug_log("timeout : %d\n", http_timeout);
12267
12268                         /* setting property to streaming source */
12269                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
12270                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
12271                         g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
12272
12273                         /* check if prosy is vailid or not */
12274                         if ( util_check_valid_url ( proxy ) )
12275                                 g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
12276                         /* parsing cookies */
12277                         if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
12278                                 g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
12279                         if ( user_agent )
12280                                 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
12281                         break;
12282                 }
12283                 default:
12284                         debug_error("not support uri type %d\n", player->profile.uri_type);
12285                         break;
12286         }
12287
12288         if ( !element )
12289         {
12290                 debug_error("no source element was created.\n");
12291                 goto ERROR;
12292         }
12293
12294         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
12295         {
12296                 debug_error("failed to add source element to pipeline\n");
12297                 gst_object_unref(GST_OBJECT(element));
12298                 element = NULL;
12299                 goto ERROR;
12300         }
12301
12302         /* take source element */
12303         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
12304         mainbin[MMPLAYER_M_SRC].gst = element;
12305
12306         element = NULL;
12307
12308         if (MMPLAYER_IS_HTTP_STREAMING(player))
12309         {
12310                 if (player->streamer == NULL)
12311                 {
12312                         player->streamer = __mm_player_streaming_create();
12313
12314                         if(player->streamer == NULL)
12315                         goto ERROR;
12316
12317                         __mm_player_streaming_initialize(player->streamer);
12318                 }
12319
12320                 elemId = MMPLAYER_M_TYPEFIND;
12321                 element = gst_element_factory_make("typefind", "typefinder");
12322                 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
12323                         G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
12324         }
12325         else
12326         {
12327                 elemId = MMPLAYER_M_AUTOPLUG;
12328                 element = __mmplayer_create_decodebin(player);
12329         }
12330
12331         /* check autoplug element is OK */
12332         if ( ! element )
12333         {
12334                 debug_error("can not create element (%d)\n", elemId);
12335                 goto ERROR;
12336         }
12337
12338         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
12339         {
12340                 debug_error("failed to add sinkbin to pipeline\n");
12341                 gst_object_unref(GST_OBJECT(element));
12342                 element = NULL;
12343                 goto ERROR;
12344         }
12345
12346         mainbin[elemId].id = elemId;
12347         mainbin[elemId].gst = element;
12348
12349         if ( gst_element_link (mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE )
12350         {
12351                 debug_error("Failed to link src - autoplug (or typefind)\n");
12352                 goto ERROR;
12353         }
12354
12355         if (gst_element_set_state (mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE)
12356         {
12357                 debug_error("Failed to change state of src element\n");
12358                 goto ERROR;
12359         }
12360
12361         if (!MMPLAYER_IS_HTTP_STREAMING(player))
12362         {
12363                 if (gst_element_set_state (mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE)
12364                 {
12365                         debug_error("Failed to change state of decodebin2\n");
12366                         goto ERROR;
12367                 }
12368         }
12369         else
12370         {
12371                 if (gst_element_set_state (mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE)
12372                 {
12373                         debug_error("Failed to change state of src element\n");
12374                         goto ERROR;
12375                 }
12376         }
12377
12378         player->src_changed = TRUE;
12379         MMPLAYER_FLEAVE();
12380         return;
12381
12382 ERROR:
12383
12384         MMPLAYER_PLAYBACK_UNLOCK(player);
12385
12386         if (!player->msg_posted)
12387         {
12388                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
12389                 player->msg_posted = TRUE;
12390         }
12391         return;
12392 }
12393
12394 static gboolean
12395 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
12396 {
12397         mm_player_selector_t *selector = &player->selector[type];
12398         MMPlayerGstElement *sinkbin = NULL;
12399         enum MainElementID selectorId = MMPLAYER_M_NUM;
12400         enum MainElementID sinkId = MMPLAYER_M_NUM;
12401         GstPad *srcpad = NULL;
12402         GstPad *sinkpad = NULL;
12403
12404         MMPLAYER_FENTER();
12405         return_val_if_fail (player, FALSE);
12406
12407         debug_log("type %d", type);
12408
12409         switch (type)
12410         {
12411                 case MM_PLAYER_TRACK_TYPE_VIDEO:
12412                         selectorId = MMPLAYER_M_V_INPUT_SELECTOR;
12413                         sinkId = MMPLAYER_V_BIN;
12414                         sinkbin = player->pipeline->videobin;
12415                 break;
12416                 case MM_PLAYER_TRACK_TYPE_AUDIO:
12417                         selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
12418                         sinkId = MMPLAYER_A_BIN;
12419                         sinkbin = player->pipeline->audiobin;
12420                 break;
12421                 case MM_PLAYER_TRACK_TYPE_TEXT:
12422                         selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
12423                         sinkId = MMPLAYER_T_BIN;
12424                         sinkbin = player->pipeline->textbin;
12425                 break;
12426                 default:
12427                         debug_error("requested type is not supportable");
12428                         return FALSE;
12429                 break;
12430         }
12431
12432         if (player->pipeline->mainbin[selectorId].gst)
12433         {
12434                 gint n;
12435
12436                 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
12437
12438                 if ((sinkbin) && (sinkbin[sinkId].gst))
12439                 {
12440                         sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
12441
12442                         if (srcpad && sinkpad)
12443                         {
12444                                 /* after getting drained signal there is no data flows, so no need to do pad_block */
12445                                 debug_log("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
12446                                 gst_pad_unlink (srcpad, sinkpad);
12447                         }
12448
12449                         gst_object_unref (sinkpad);
12450                         sinkpad = NULL;
12451                 }
12452                 gst_object_unref (srcpad);
12453                 srcpad = NULL;
12454
12455                 debug_log("selector release");
12456                 if(selector->channels)
12457                 {
12458                         debug_log("release and unref request pads");
12459
12460                         /* release and unref requests pad from the selector */
12461                         for (n = 0; n < selector->channels->len; n++)
12462                         {
12463                                 GstPad *sinkpad = g_ptr_array_index (selector->channels, n);
12464                                 gst_element_release_request_pad ((player->pipeline->mainbin[selectorId].gst), sinkpad);
12465                         }
12466                         g_ptr_array_set_size (selector->channels, 0);
12467                 }
12468                 gst_element_set_state (player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
12469                 gst_bin_remove (GST_BIN_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
12470
12471                 player->pipeline->mainbin[selectorId].gst = NULL;
12472                 selector = NULL;
12473         }
12474
12475         return TRUE;
12476 }
12477
12478 static void
12479 __mmplayer_deactivate_old_path(mm_player_t *player)
12480 {
12481         MMPLAYER_FENTER();
12482         return_if_fail ( player );
12483
12484         g_object_set(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEC1].gst), "remove-buffer-signal", TRUE, NULL);
12485
12486         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
12487                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
12488                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT)))
12489         {
12490                 debug_error("deactivate selector error");
12491                 goto ERROR;
12492         }
12493
12494         __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG );
12495
12496         if (player->streamer)
12497         {
12498                 __mm_player_streaming_deinitialize (player->streamer);
12499                 __mm_player_streaming_destroy(player->streamer);
12500                 player->streamer = NULL;
12501         }
12502
12503         MMPLAYER_PLAYBACK_LOCK(player);
12504         g_cond_signal( player->next_play_thread_cond );
12505
12506         MMPLAYER_FLEAVE();
12507         return;
12508
12509 ERROR:
12510
12511         if (!player->msg_posted)
12512         {
12513                 MMMessageParamType msg = {0,};
12514
12515                 /*post error*/
12516                 msg.code = MM_ERROR_PLAYER_INTERNAL;
12517                 debug_error("next_uri_play> deactivate error");
12518
12519                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
12520                 player->msg_posted = TRUE;
12521         }
12522         return;
12523 }
12524
12525 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
12526 {
12527         int result = MM_ERROR_NONE;
12528         mm_player_t* player = (mm_player_t*) hplayer;
12529         MMPLAYER_FENTER();
12530
12531         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12532
12533         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
12534         if (mmf_attrs_commit(player->attrs))
12535         {
12536                 debug_error("failed to commit the original uri.\n");
12537                 result = MM_ERROR_PLAYER_INTERNAL;
12538         }
12539         else
12540         {
12541                 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
12542                 {
12543                         debug_error("failed to add the original uri in the uri list.\n");
12544                 }
12545         }
12546
12547         MMPLAYER_FLEAVE();
12548         return result;
12549 }
12550
12551 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
12552 {
12553         mm_player_t* player = (mm_player_t*) hplayer;
12554         guint num_of_list = 0;
12555
12556         MMPLAYER_FENTER();
12557
12558         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12559         return_val_if_fail (uri, MM_ERROR_INVALID_ARGUMENT);
12560
12561         if (player->pipeline && player->pipeline->textbin)
12562         {
12563                 debug_error("subtitle path is enabled.\n");
12564                 return MM_ERROR_PLAYER_INVALID_STATE;
12565         }
12566
12567         num_of_list = g_list_length(player->uri_info.uri_list);
12568
12569         if (is_first_path == TRUE)
12570         {
12571                 if (num_of_list == 0)
12572                 {
12573                         player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12574                         debug_log("add original path : %s", uri);
12575                 }
12576                 else
12577                 {
12578                         player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
12579                         player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
12580
12581                         debug_log("change original path : %s", uri);
12582                 }
12583         }
12584         else
12585         {
12586                 if (num_of_list == 0)
12587                 {
12588                         MMHandleType attrs = 0;
12589                         char *original_uri = NULL;
12590
12591                         attrs = MMPLAYER_GET_ATTRS(player);
12592                         if ( attrs )
12593                         {
12594                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
12595
12596                                 if (!original_uri)
12597                                 {
12598                                         debug_error("there is no original uri.");
12599                                         return MM_ERROR_PLAYER_INVALID_STATE;
12600                                 }
12601
12602                                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
12603                                 player->uri_info.uri_idx = 0;
12604
12605                                 debug_log("add original path at first : %s (%d)", original_uri);
12606                         }
12607                 }
12608
12609                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12610                 debug_log("add new path : %s (total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
12611         }
12612
12613         MMPLAYER_FLEAVE();
12614         return MM_ERROR_NONE;
12615 }
12616
12617 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
12618 {
12619         mm_player_t* player = (mm_player_t*) hplayer;
12620         char *next_uri = NULL;
12621         guint num_of_list = 0;
12622
12623         MMPLAYER_FENTER();
12624         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12625
12626         num_of_list = g_list_length(player->uri_info.uri_list);
12627
12628         if (num_of_list > 0)
12629         {
12630                 gint uri_idx = player->uri_info.uri_idx;
12631
12632                 if ( uri_idx < num_of_list-1 )
12633                         uri_idx++;
12634                 else
12635                         uri_idx = 0;
12636
12637                 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12638                 debug_error("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
12639
12640                 *uri = g_strdup(next_uri);
12641         }
12642
12643         MMPLAYER_FLEAVE();
12644         return MM_ERROR_NONE;
12645 }
12646
12647 static void
12648 __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad,
12649 GstCaps *caps, gpointer data)
12650 {
12651         mm_player_t* player = (mm_player_t*)data;
12652         const gchar* klass = NULL;
12653         const gchar* mime = NULL;
12654         gchar* caps_str = NULL;
12655
12656         klass = gst_element_factory_get_klass (gst_element_get_factory(elem));
12657         mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12658         caps_str = gst_caps_to_string(caps);
12659
12660         debug_warning("unknown type of caps : %s from %s",
12661                                         caps_str, GST_ELEMENT_NAME (elem));
12662
12663         MMPLAYER_FREEIF(caps_str);
12664
12665         /* There is no available codec. */
12666         __mmplayer_check_not_supported_codec (player, klass, mime);
12667 }
12668
12669 static gboolean
12670 __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad,
12671 GstCaps * caps,  gpointer data)
12672 {
12673         mm_player_t* player = (mm_player_t*)data;
12674         const char* mime = NULL;
12675         gboolean ret = TRUE;
12676
12677         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
12678         mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12679
12680         if (g_str_has_prefix(mime, "audio")) {
12681                 GstStructure* caps_structure = NULL;
12682                 gint samplerate = 0;
12683                 gint channels = 0;
12684                 gchar *caps_str = NULL;
12685
12686                 caps_structure = gst_caps_get_structure(caps, 0);
12687                 gst_structure_get_int (caps_structure, "rate", &samplerate);
12688                 gst_structure_get_int (caps_structure, "channels", &channels);
12689
12690                 if ( (channels > 0 && samplerate == 0)) {
12691                         debug_log("exclude audio...");
12692                         ret = FALSE;
12693                 }
12694
12695                 caps_str = gst_caps_to_string(caps);
12696                 /* set it directly because not sent by TAG */
12697                 if (g_strrstr(caps_str, "mobile-xmf")) {
12698                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
12699                 }
12700                 MMPLAYER_FREEIF (caps_str);
12701         } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
12702                 debug_log("already video linked");
12703                 ret = FALSE;
12704         } else {
12705                 debug_log("found new stream");
12706         }
12707
12708         return ret;
12709 }
12710
12711 static gint
12712 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad,
12713 GstCaps* caps, GstElementFactory* factory, gpointer data)
12714 {
12715         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
12716          We are defining our own and will be removed when it actually exposed */
12717         typedef enum {
12718                 GST_AUTOPLUG_SELECT_TRY,
12719                 GST_AUTOPLUG_SELECT_EXPOSE,
12720                 GST_AUTOPLUG_SELECT_SKIP
12721         } GstAutoplugSelectResult;
12722
12723         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
12724         mm_player_t* player = (mm_player_t*)data;
12725
12726         gchar* factory_name = NULL;
12727         gchar* caps_str = NULL;
12728         const gchar* klass = NULL;
12729         gint idx = 0;
12730
12731         factory_name = GST_PLUGIN_FEATURE_NAME (factory);
12732         klass = gst_element_factory_get_klass(factory);
12733         caps_str = gst_caps_to_string(caps);
12734
12735 //      debug_log("found new element [%s] to link for caps [%s]", factory_name, caps_str);
12736         debug_log("found new element [%s] to link", factory_name);
12737
12738         /* store type string */
12739         if (player->type == NULL)
12740         {
12741                 player->type = gst_caps_to_string(caps);
12742
12743                 /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
12744                 if (__mmplayer_is_midi_type(player->type))
12745                 {
12746                         player->profile.play_mode = MM_PLAYER_MODE_MIDI;
12747                         player->bypass_audio_effect = TRUE;
12748                 }
12749                 else if (g_strrstr(player->type, "application/x-hls"))
12750                 {
12751                         /* If it can't know exact type when it parses uri because of redirection case,
12752                          * it will be fixed by typefinder here.
12753                          */
12754                         player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
12755                 }
12756                 else if (g_strrstr(player->type, "application/dash+xml"))
12757                 {
12758                         player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
12759                 }
12760         }
12761
12762         /* filtering exclude keyword */
12763         for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
12764         {
12765                 if ( strstr(factory_name, player->ini.exclude_element_keyword[idx] ) )
12766                 {
12767                         debug_warning("skipping [%s] by exculde keyword [%s]\n",
12768                         factory_name, player->ini.exclude_element_keyword[idx] );
12769
12770                         // NOTE : does we need to check n_value against the number of item selected?
12771                         result = GST_AUTOPLUG_SELECT_SKIP;
12772                         goto DONE;
12773                 }
12774         }
12775
12776         /* check factory class for filtering */
12777         /* NOTE : msl don't need to use image plugins.
12778          * So, those plugins should be skipped for error handling.
12779          */
12780         if (g_strrstr(klass, "Codec/Decoder/Image"))
12781         {
12782                 debug_log("skipping [%s] by not required\n", factory_name);
12783                 result = GST_AUTOPLUG_SELECT_SKIP;
12784                 goto DONE;
12785         }
12786
12787         if (g_strrstr(factory_name, "mpegpsdemux"))
12788         {
12789                 debug_log("skipping PS container - not support\n");
12790                 result = GST_AUTOPLUG_SELECT_SKIP;
12791                 goto DONE;
12792         }
12793
12794         if (g_strrstr(factory_name, "mpegtsdemux") || g_strrstr(factory_name, "ssdemux"))
12795         {
12796                 if (g_strrstr(factory_name, "ssdemux"))
12797                         player->smooth_streaming = TRUE;
12798
12799                 if (g_strrstr(caps_str, "video/x-h264"))
12800                 {
12801                         player->needed_v_parser = TRUE;
12802                 }
12803                 else if (g_strrstr(caps_str, "video/mpeg"))
12804                 {
12805                         player->needed_v_parser = TRUE;
12806                 }
12807         }
12808
12809         /* check ALP Codec can be used or not */
12810         if ((g_strrstr(klass, "Codec/Decoder/Audio")))
12811         {
12812                 GstStructure* str = NULL;
12813                 gint channels = 0;
12814
12815                 str = gst_caps_get_structure( caps, 0 );
12816                 if ( str )
12817                 {
12818                         gst_structure_get_int (str, "channels", &channels);
12819
12820                         debug_log ("check audio ch : %d %d\n", player->max_audio_channels, channels);
12821                         if (player->max_audio_channels < channels)
12822                         {
12823                                 player->max_audio_channels = channels;
12824                         }
12825                 }
12826
12827                 if (!player->audiodec_linked)
12828                 {
12829                         /* set stream information */
12830                         __mmplayer_set_audio_attrs (player, caps);
12831                 }
12832         }
12833         else if ((g_strrstr(klass, "Codec/Decoder/Video")))
12834         {
12835                 if (g_strrstr(factory_name, "omx_"))
12836                 {
12837                         char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
12838                         if (env != NULL)
12839                         {
12840                                 if (strncasecmp(env, "yes", 3) == 0)
12841                                 {
12842                                         debug_log ("skipping [%s] by disabled\n", factory_name);
12843                                         result = GST_AUTOPLUG_SELECT_SKIP;
12844                                         goto DONE;
12845                                 }
12846                         }
12847                 }
12848         }
12849
12850         if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
12851                 (g_strrstr(klass, "Codec/Decoder/Video")))
12852         {
12853                 gint stype = 0;
12854                 gint width = 0;
12855                 GstStructure *str = NULL;
12856                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
12857
12858                 /* don't make video because of not required */
12859                 if (stype == MM_DISPLAY_SURFACE_NULL)
12860                 {
12861                         debug_log ("no video because it's not required. -> return expose");
12862                         if (player->set_mode.media_packet_video_stream == FALSE)
12863                         {
12864                                 result = GST_AUTOPLUG_SELECT_EXPOSE;
12865                                 goto DONE;
12866                         }
12867                 }
12868
12869                 /* get w/h for omx state-tune */
12870                 str = gst_caps_get_structure (caps, 0);
12871                 gst_structure_get_int (str, "width", &width);
12872
12873                 if (width != 0) {
12874                         #define UHD_SIZE 3840*2160
12875                         gint height = 0;
12876                         gst_structure_get_int (str, "height", &height);
12877
12878                         if (player->v_stream_caps) {
12879                                 gst_caps_unref(player->v_stream_caps);
12880                                 player->v_stream_caps = NULL;
12881                         }
12882
12883                         player->v_stream_caps = gst_caps_copy(caps);
12884                         debug_log ("take caps for video state tune");
12885                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
12886
12887                         /* check video resolution */
12888                         if (width*height == UHD_SIZE) {
12889                                 if ((util_is_miracast_connected()) && (player->msg_posted == FALSE)) {
12890                                         MMMessageParamType msg = {0,};
12891                                         /*post error*/
12892                                         msg.code = MM_ERROR_PLAYER_RESOURCE_LIMIT;
12893                                         debug_error("can't play in miracast");
12894                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
12895                                         player->msg_posted = TRUE;
12896                                 }
12897                         }
12898                 }
12899         }
12900     if ((g_strrstr(klass, "Codec/Parser/Audio")))
12901     {
12902                 if (player->smooth_streaming && (g_strrstr(caps_str, "audio/mpeg")))
12903                 {
12904                         debug_log ("ssdemux can't use audio parse");
12905                         result = GST_AUTOPLUG_SELECT_SKIP;
12906                         goto DONE;
12907                 }
12908
12909     }
12910
12911         if (g_strrstr(klass, "Decoder"))
12912         {
12913                 const char* mime = NULL;
12914                 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12915
12916                 if (g_str_has_prefix(mime, "video"))
12917                 {
12918                         // __mmplayer_check_video_zero_cpoy(player, factory);
12919
12920                         player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
12921                         player->can_support_codec |= FOUND_PLUGIN_VIDEO;
12922
12923                         player->videodec_linked = 1;
12924                 }
12925                 else if(g_str_has_prefix(mime, "audio"))
12926                 {
12927                         player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
12928                         player->can_support_codec |= FOUND_PLUGIN_AUDIO;
12929
12930                         player->audiodec_linked = 1;
12931                 }
12932         }
12933
12934 DONE:
12935         MMPLAYER_FREEIF(caps_str);
12936
12937         return result;
12938 }
12939
12940
12941 #if 0
12942 static GValueArray*
12943 __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad,
12944 GstCaps * caps,  gpointer data)
12945 {
12946         //mm_player_t* player = (mm_player_t*)data;
12947
12948         debug_log("decodebin is requesting factories for caps [%s] from element[%s]",
12949                 gst_caps_to_string(caps),
12950                 GST_ELEMENT_NAME(GST_PAD_PARENT(pad)));
12951
12952         return NULL;
12953 }
12954 #endif
12955
12956 static GValueArray*
12957 __mmplayer_gst_decode_autoplug_sort(GstElement *bin,  GstPad* pad,
12958 GstCaps* caps, GValueArray* factories, gpointer data) // @
12959 {
12960 #define DEFAULT_IDX 0xFFFF
12961
12962         guint idx = 0;
12963         guint a_omx_idx = DEFAULT_IDX;
12964         guint a_dec_idx = DEFAULT_IDX;
12965         guint v_dec_idx = DEFAULT_IDX;
12966         guint v_parser_idx = DEFAULT_IDX;
12967         guint new_pos = DEFAULT_IDX;
12968         guint elem_idx = DEFAULT_IDX;
12969
12970         GValueArray* new_factories = NULL;
12971         GValue val = { 0, };
12972
12973         GstElementFactory *factory = NULL;
12974         const gchar* klass = NULL;
12975         gchar* factory_name = NULL;
12976         gchar* caps_str = NULL;
12977
12978         mm_player_t* player = (mm_player_t*)data;
12979         caps_str = gst_caps_to_string(caps);
12980
12981         //debug_log("autoplug-sort signal [num: %d]\n", factories->n_values);
12982         debug_log("requesting custom sorting for the factories for caps [%s]", caps_str);
12983
12984         MMPLAYER_FREEIF(caps_str);
12985
12986         for(idx=0; idx < factories->n_values;idx++)
12987         {
12988                 factory =       g_value_get_object (g_value_array_get_nth (factories, idx));
12989
12990                 klass = gst_element_factory_get_klass(factory);
12991                 factory_name = GST_PLUGIN_FEATURE_NAME (factory);
12992
12993                 //debug_log("Klass [%s] Factory [%s]\n", klass, factory_name);
12994
12995                 if (g_strrstr(klass, "Codec/Decoder/Audio"))
12996                 {
12997                         if (a_dec_idx == DEFAULT_IDX)
12998                                 a_dec_idx = idx;
12999
13000                         /* check ALP Codec can be used or not */
13001                         if ((a_omx_idx == DEFAULT_IDX) &&
13002                                 (g_strrstr(factory_name, "omx_mp3dec")) &&
13003                                 (__mmplayer_is_omx_decoder_type(player)))
13004                         {
13005                                 debug_log("--> mp3_local : Priority of omx is higher than the others\n");
13006                                 a_omx_idx = idx;
13007                                 break;
13008                         }
13009                 }
13010                 else if ((v_dec_idx == DEFAULT_IDX) && (g_strrstr(klass, "Codec/Decoder/Video")))
13011                 {
13012                         v_dec_idx = idx;
13013                 }
13014
13015                 if ((v_parser_idx == DEFAULT_IDX) &&
13016                         (((player->smooth_streaming) &&
13017                           (g_strrstr(factory_name, "legacyh264parse"))) ||
13018                          // (g_strrstr(factory_name, "h264parse")) ||
13019                          (g_strrstr(factory_name, "mpeg4videoparse"))))
13020                 {
13021                         v_parser_idx = idx;
13022                 }
13023         }
13024
13025         if (player->needed_v_parser || player->smooth_streaming)
13026         {
13027                 debug_log("needed parser? %s, ss? %s\n",
13028                                         (player->needed_v_parser)?"OO":"XX",
13029                                         (player->smooth_streaming)?"OO":"XX");
13030         }
13031
13032         new_pos = (a_dec_idx!=DEFAULT_IDX)?(a_dec_idx):((player->needed_v_parser)?(v_dec_idx):(v_parser_idx));
13033         elem_idx = (a_omx_idx!=DEFAULT_IDX)?(a_omx_idx):((player->needed_v_parser)?(v_parser_idx):(v_dec_idx));
13034
13035         /* consider file mp3 audio only */
13036         if ((elem_idx != DEFAULT_IDX) && (new_pos < elem_idx))
13037         {
13038                 debug_log("[Re-arrange] factories sequence, new_pos : %d, elem_idx : %d\n", new_pos, elem_idx);
13039
13040                 new_factories = g_value_array_copy (factories);
13041
13042                 // insert omx decoder in front of other decoders
13043                 factory = g_value_get_object (g_value_array_get_nth (factories, elem_idx));
13044
13045                 g_value_init (&val, G_TYPE_OBJECT);
13046                 g_value_set_object (&val, factory);
13047                 g_value_array_insert (new_factories, new_pos, &val);
13048                 g_value_unset (&val);
13049
13050                 // remove duplicated omx element
13051                 g_value_array_remove(new_factories, elem_idx+1);
13052
13053                 for(idx=0; idx < new_factories->n_values;idx++)
13054                 {
13055                         factory = g_value_get_object (g_value_array_get_nth (new_factories, idx));
13056
13057                         debug_log("[Re-arranged] Klass [%s] Factory [%s]\n",
13058                                 gst_element_factory_get_klass(factory), GST_PLUGIN_FEATURE_NAME (factory));
13059                 }
13060         }
13061
13062         /* returning NULL to keep current order */
13063         return (new_factories)?(new_factories):(NULL);
13064 }
13065
13066 static void
13067 __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad,
13068 gpointer data) // @
13069 {
13070         //mm_player_t* player = (mm_player_t*)data;
13071         GstCaps* caps = NULL;
13072
13073         debug_log("[Decodebin2] pad-removed signal\n");
13074
13075         caps = gst_pad_get_caps(new_pad);
13076         if (caps)
13077         {
13078                 gchar* caps_str = NULL;
13079                 caps_str = gst_caps_to_string(caps);
13080
13081                 debug_log("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem) );
13082
13083                 MMPLAYER_FREEIF(caps_str);
13084         }
13085 }
13086
13087 static void
13088 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
13089 {
13090         mm_player_t* player = (mm_player_t*)data;
13091
13092         MMPLAYER_FENTER();
13093         return_if_fail ( player );
13094
13095         debug_log("__mmplayer_gst_decode_drained");
13096
13097         if (player->use_deinterleave == TRUE)
13098         {
13099                 debug_log("group playing mode.");
13100                 return;
13101         }
13102
13103         if ( !player->cmd_lock )
13104         {
13105                 debug_warning("can't get cmd lock\n");
13106                 return;
13107         }
13108
13109         if (!g_mutex_trylock(player->cmd_lock))
13110         {
13111                 debug_warning("Fail to get cmd lock");
13112                 return;
13113         }
13114
13115         if (!__mmplayer_verify_next_play_path(player))
13116         {
13117                 debug_log("decoding is finished.");
13118                 g_mutex_unlock(player->cmd_lock);
13119                 return;
13120         }
13121
13122         player->pp_rebuilding = TRUE;
13123
13124         /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
13125         __mmplayer_deactivate_old_path(player);
13126
13127         g_mutex_unlock(player->cmd_lock);
13128
13129         MMPLAYER_FLEAVE();
13130 }
13131
13132 static void
13133 __mmplayer_gst_element_added (GstElement *bin, GstElement *element, gpointer data)
13134 {
13135         mm_player_t* player = (mm_player_t*)data;
13136         const gchar* klass = NULL;
13137         gchar* factory_name = NULL;
13138
13139         klass = gst_element_factory_get_klass (gst_element_get_factory(element));
13140         factory_name = GST_PLUGIN_FEATURE_NAME (gst_element_get_factory(element));
13141
13142         debug_log("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
13143
13144         if (__mmplayer_add_dump_buffer_probe(player, element))
13145                 debug_log("add buffer probe");
13146
13147         //<-
13148         if (g_strrstr(klass, "Codec/Decoder/Audio"))
13149         {
13150                 gchar* selected = NULL;
13151                 selected = g_strdup( GST_ELEMENT_NAME(element));
13152                 player->audio_decoders = g_list_append (player->audio_decoders, selected);
13153         }
13154         //-> temp code
13155
13156         if (g_strrstr(klass, "Parser"))
13157         {
13158                 gchar* selected = NULL;
13159
13160                 selected = g_strdup (factory_name);
13161                 player->parsers = g_list_append (player->parsers, selected);
13162         }
13163
13164         if (g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
13165         {
13166                 /* FIXIT : first value will be overwritten if there's more
13167                  * than 1 demuxer/parser
13168                  */
13169
13170                 //debug_log ("plugged element is demuxer. take it\n");
13171                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
13172                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
13173
13174                 /*Added for multi audio support */ // Q. del?
13175                 if (g_strrstr(klass, "Demux"))
13176                 {
13177                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
13178                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
13179                 }
13180         }
13181
13182         if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux"))
13183         {
13184                 int surface_type = 0;
13185
13186                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
13187
13188                 /* playback protection if drm file */
13189                 if (player->use_video_stream || surface_type == MM_DISPLAY_SURFACE_EVAS || surface_type == MM_DISPLAY_SURFACE_X_EXT)
13190                 {
13191                         debug_log("playback can be protected if playready drm");
13192                         g_object_set (G_OBJECT(element), "playback-protection", TRUE, NULL);
13193                 }
13194         }
13195
13196         // to support trust-zone only
13197         if (g_strrstr(factory_name, "asfdemux"))
13198         {
13199                 debug_log ("set file-location %s\n", player->profile.uri);
13200                 g_object_set (G_OBJECT(element), "file-location", player->profile.uri, NULL);
13201
13202                 if (player->video_hub_download_mode == TRUE)
13203                 {
13204                         g_object_set (G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
13205                 }
13206         }
13207         else if (g_strrstr(factory_name, "legacyh264parse"))    // ssdemux
13208         {
13209                 debug_log ("[ssdemux] output-format to legacyh264parse\n");
13210                 g_object_set (G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
13211         }
13212         else if (g_strrstr(factory_name, "mpegaudioparse"))
13213         {
13214                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
13215                         (__mmplayer_is_only_mp3_type(player->type)))
13216                 {
13217                         debug_log ("[mpegaudioparse] set streaming pull mode.");
13218                         g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
13219                 }
13220         }
13221         else if (g_strrstr(factory_name, "omx_"))
13222         {
13223                 if (g_strrstr(klass, "Codec/Decoder/Video"))
13224                 {
13225                         gboolean ret = FALSE;
13226
13227                         if (player->v_stream_caps != NULL)
13228                         {
13229                                 GstPad *pad = gst_element_get_static_pad(element, "sink");
13230
13231                                 if (pad)
13232                                 {
13233                                         ret = gst_pad_set_caps(pad, player->v_stream_caps);
13234                                         debug_log("found omx decoder, setting gst_pad_set_caps for omx (ret:%d)", ret);
13235                                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
13236                                         gst_object_unref (pad);
13237                                 }
13238                         }
13239                         g_object_set (G_OBJECT(element), "state-tuning", TRUE, NULL);
13240                 }
13241 #ifdef _MM_PLAYER_ALP_PARSER
13242                 if (g_strrstr(factory_name, "omx_mp3dec"))
13243                 {
13244                         g_list_foreach (player->parsers, check_name, player);
13245                 }
13246 #endif
13247                 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
13248         }
13249
13250         if (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))
13251         {
13252                 debug_log ("plugged element is multiqueue. take it\n");
13253                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
13254                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
13255
13256                 if (MMPLAYER_IS_HTTP_STREAMING(player))
13257                 {
13258                         __mm_player_streaming_set_multiqueue(player->streamer,
13259                                 element,
13260                                 TRUE,
13261                                 MAX_DECODEBIN_BUFFER_BYTES, // player->ini.http_max_size_bytes,
13262                                 player->ini.http_buffering_time,
13263                                 1.0,
13264                                 player->ini.http_buffering_limit);
13265
13266                         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
13267                 }
13268         }
13269
13270         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-added" );
13271         return;
13272 }
13273
13274 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
13275 {
13276         MMPLAYER_FENTER();
13277         return_val_if_fail ( player, FALSE );
13278
13279         if ( MMPLAYER_IS_STREAMING(player) )
13280                 return FALSE;
13281
13282         /* This callback can be set to music player only. */
13283         if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
13284         {
13285                 debug_warning("audio callback is not supported for video");
13286                 return FALSE;
13287         }
13288
13289         if (player->audio_stream_cb)
13290         {
13291                 {
13292                         GstPad *pad = NULL;
13293
13294                         pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
13295
13296                         if ( !pad )
13297                         {
13298                                 debug_error("failed to get sink pad from audiosink to probe data\n");
13299                                 return FALSE;
13300                         }
13301
13302                         player->audio_cb_probe_id = gst_pad_add_buffer_probe (pad,
13303                                 G_CALLBACK (__mmplayer_audio_stream_probe), player);
13304
13305                         gst_object_unref (pad);
13306
13307                         pad = NULL;
13308                }
13309         }
13310         else
13311         {
13312                 debug_error("There is no audio callback to configure.\n");
13313                 return FALSE;
13314         }
13315
13316         MMPLAYER_FLEAVE();
13317
13318         return TRUE;
13319 }
13320
13321 static void
13322 __mmplayer_init_factories(mm_player_t* player) // @
13323 {
13324         return_if_fail ( player );
13325
13326         player->factories = gst_registry_feature_filter(gst_registry_get_default(),
13327                                         (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
13328         player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
13329 }
13330
13331 static void
13332 __mmplayer_release_factories(mm_player_t* player) // @
13333 {
13334         MMPLAYER_FENTER();
13335         return_if_fail ( player );
13336
13337         if (player->factories)
13338         {
13339                 gst_plugin_feature_list_free (player->factories);
13340                 player->factories = NULL;
13341         }
13342
13343         MMPLAYER_FLEAVE();
13344 }
13345
13346 static void
13347 __mmplayer_release_misc(mm_player_t* player)
13348 {
13349         int i;
13350         gboolean cur_mode = player->set_mode.rich_audio;
13351         MMPLAYER_FENTER();
13352
13353         return_if_fail ( player );
13354
13355         player->use_video_stream = FALSE;
13356         player->video_stream_cb = NULL;
13357         player->video_stream_cb_user_param = NULL;
13358
13359         player->audio_stream_cb = NULL;
13360         player->audio_stream_cb_user_param = NULL;
13361
13362         player->sent_bos = FALSE;
13363         player->playback_rate = DEFAULT_PLAYBACK_RATE;
13364
13365         player->doing_seek = FALSE;
13366
13367         player->updated_bitrate_count = 0;
13368         player->total_bitrate = 0;
13369         player->updated_maximum_bitrate_count = 0;
13370         player->total_maximum_bitrate = 0;
13371
13372         player->not_found_demuxer = 0;
13373
13374         player->last_position = 0;
13375         player->duration = 0;
13376         player->http_content_size = 0;
13377         player->not_supported_codec = MISSING_PLUGIN_NONE;
13378         player->can_support_codec = FOUND_PLUGIN_NONE;
13379         player->pending_seek.is_pending = FALSE;
13380         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
13381         player->pending_seek.pos = 0;
13382         player->msg_posted = FALSE;
13383         player->has_many_types = FALSE;
13384         player->is_drm_file = FALSE;
13385         player->max_audio_channels = 0;
13386         player->video_share_api_delta = 0;
13387         player->video_share_clock_delta = 0;
13388         player->sm.keep_last_pos = FALSE;
13389         player->display_stat = MMPLAYER_DISPLAY_STATUS_NULL;
13390         player->is_subtitle_force_drop = FALSE;
13391         player->play_subtitle = FALSE;
13392         player->use_textoverlay = FALSE;
13393         player->adjust_subtitle_pos = 0;
13394         player->last_multiwin_status = FALSE;
13395         player->has_closed_caption = FALSE;
13396         player->set_mode.media_packet_video_stream = FALSE;
13397
13398         memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
13399         /* recover mode */
13400         player->set_mode.rich_audio = cur_mode;
13401
13402         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
13403         {
13404                 player->bitrate[i] = 0;
13405                 player->maximum_bitrate[i] = 0;
13406         }
13407
13408         /* free memory related to audio effect */
13409         MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
13410
13411         if (player->state_tune_caps)
13412         {
13413                 gst_caps_unref(player->state_tune_caps);
13414                 player->state_tune_caps = NULL;
13415         }
13416
13417         if (player->video_cb_probe_id)
13418         {
13419                 GstPad *pad = NULL;
13420
13421                 pad = gst_element_get_static_pad (player->video_fakesink, "sink");
13422
13423                 if (pad) {
13424                         debug_log("release video probe\n");
13425
13426                         /* release audio callback */
13427                         gst_pad_remove_buffer_probe (pad, player->video_cb_probe_id);
13428                         player->video_cb_probe_id = 0;
13429                         player->video_stream_cb = NULL;
13430                         player->video_stream_cb_user_param = NULL;
13431                 }
13432         }
13433
13434         MMPLAYER_FLEAVE();
13435 }
13436
13437 static void
13438 __mmplayer_release_misc_post(mm_player_t* player)
13439 {
13440         char *original_uri = NULL;
13441         MMPLAYER_FENTER();
13442
13443         /* player->pipeline is already released before. */
13444
13445         return_if_fail ( player );
13446
13447         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
13448         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
13449
13450         /* clean found parsers */
13451         if (player->parsers)
13452         {
13453                 GList *parsers = player->parsers;
13454                 for ( ;parsers ; parsers = g_list_next(parsers))
13455                 {
13456                         gchar *name = parsers->data;
13457                         MMPLAYER_FREEIF(name);
13458                 }
13459                 g_list_free(player->parsers);
13460                 player->parsers = NULL;
13461         }
13462
13463         /* clean found audio decoders */
13464         if (player->audio_decoders)
13465         {
13466                 GList *a_dec = player->audio_decoders;
13467                 for ( ;a_dec ; a_dec = g_list_next(a_dec))
13468                 {
13469                         gchar *name = a_dec->data;
13470                         MMPLAYER_FREEIF(name);
13471                 }
13472                 g_list_free(player->audio_decoders);
13473                 player->audio_decoders = NULL;
13474         }
13475
13476         /* clean the uri list except original uri */
13477         if (player->uri_info.uri_list)
13478         {
13479                 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
13480
13481                 if (player->attrs)
13482                 {
13483                         mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
13484                         debug_log("restore original uri = %s\n", original_uri);
13485
13486                         if (mmf_attrs_commit(player->attrs))
13487                         {
13488                                 debug_error("failed to commit the original uri.\n");
13489                         }
13490                 }
13491
13492                 GList *uri_list = player->uri_info.uri_list;
13493                 for ( ;uri_list ; uri_list = g_list_next(uri_list))
13494                 {
13495                         gchar *uri = uri_list->data;
13496                         MMPLAYER_FREEIF(uri);
13497                 }
13498                 g_list_free(player->uri_info.uri_list);
13499                 player->uri_info.uri_list = NULL;
13500         }
13501
13502         player->uri_info.uri_idx = 0;
13503         player->src_changed = FALSE;
13504
13505         MMPLAYER_FLEAVE();
13506 }
13507
13508 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
13509 {
13510         GstElement *element = NULL;
13511         GstPad *sinkpad;
13512
13513         debug_log("creating %s to plug\n", name);
13514
13515         element = gst_element_factory_make(name, NULL);
13516         if ( ! element )
13517         {
13518                 debug_error("failed to create queue\n");
13519                 return NULL;
13520         }
13521
13522         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
13523         {
13524                 debug_error("failed to set state READY to %s\n", name);
13525                 gst_object_unref (element);
13526                 return NULL;
13527         }
13528
13529         if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
13530         {
13531                 debug_error("failed to add %s\n", name);
13532                 gst_object_unref (element);
13533                 return NULL;
13534         }
13535
13536         sinkpad = gst_element_get_static_pad(element, "sink");
13537
13538         if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
13539         {
13540                 debug_error("failed to link %s\n", name);
13541                 gst_object_unref (sinkpad);
13542                 gst_object_unref (element);
13543                 return NULL;
13544         }
13545
13546         debug_log("linked %s to pipeline successfully\n", name);
13547
13548         gst_object_unref (sinkpad);
13549
13550         return element;
13551 }
13552
13553 static gboolean
13554 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
13555 const char *padname, const GList *templlist)
13556 {
13557         GstPad *pad = NULL;
13558         gboolean has_dynamic_pads = FALSE;
13559         gboolean has_many_types = FALSE;
13560         const char *klass = NULL;
13561         GstStaticPadTemplate *padtemplate = NULL;
13562         GstElementFactory *factory = NULL;
13563         GstElement* queue = NULL;
13564         GstElement* parser = NULL;
13565         GstPad *pssrcpad = NULL;
13566         GstPad *qsrcpad = NULL, *qsinkpad = NULL;
13567         MMPlayerGstElement *mainbin = NULL;
13568         GstStructure* str = NULL;
13569         GstCaps* srccaps = NULL;
13570         GstState target_state = GST_STATE_READY;
13571         gboolean isvideo_decoder = FALSE;
13572         guint q_max_size_time = 0;
13573
13574         MMPLAYER_FENTER();
13575
13576         return_val_if_fail ( player &&
13577                 player->pipeline &&
13578                 player->pipeline->mainbin,
13579                 FALSE );
13580
13581         mainbin = player->pipeline->mainbin;
13582
13583         debug_log("plugging pad %s:%s to newly create %s:%s\n",
13584                         GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
13585                         GST_PAD_NAME( srcpad ),
13586                         GST_ELEMENT_NAME( sinkelement ),
13587                         padname);
13588
13589         factory = gst_element_get_factory(sinkelement);
13590         klass = gst_element_factory_get_klass(factory);
13591
13592         /* check if player can do start continually */
13593         MMPLAYER_CHECK_CMD_IF_EXIT(player);
13594
13595         /* need it to warm up omx before linking to pipeline */
13596         if (g_strrstr(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ), "demux"))
13597         {
13598                 debug_log("get demux caps.\n");
13599                 if (player->state_tune_caps)
13600                 {
13601                         gst_caps_unref(player->state_tune_caps);
13602                         player->state_tune_caps = NULL;
13603                 }
13604                 player->state_tune_caps = gst_caps_copy(GST_PAD_CAPS(srcpad));
13605         }
13606
13607         /* NOTE : OMX Codec can check if resource is available or not at this state. */
13608         if (g_strrstr(GST_ELEMENT_NAME(sinkelement), "omx"))
13609         {
13610                 if (player->state_tune_caps != NULL)
13611                 {
13612                         debug_log("set demux's caps to omx codec if resource is available");
13613                         if (gst_pad_set_caps(gst_element_get_static_pad(sinkelement, "sink"), player->state_tune_caps))
13614                         {
13615                                 target_state = GST_STATE_PAUSED;
13616                                 isvideo_decoder = TRUE;
13617                                 g_object_set(G_OBJECT(sinkelement), "state-tuning", TRUE, NULL);
13618                         }
13619                         else
13620                         {
13621                                 debug_warning("failed to set caps for state tuning");
13622                         }
13623                 }
13624                 gst_caps_unref(player->state_tune_caps);
13625                 player->state_tune_caps = NULL;
13626         }
13627
13628         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, target_state) )
13629         {
13630                 debug_error("failed to set %d state to %s\n", target_state, GST_ELEMENT_NAME( sinkelement ));
13631                 if (isvideo_decoder)
13632                 {
13633                         gst_element_set_state(sinkelement, GST_STATE_NULL);
13634                         gst_object_unref(G_OBJECT(sinkelement));
13635                         player->keep_detecting_vcodec = TRUE;
13636                 }
13637                 goto ERROR;
13638         }
13639
13640         /* add to pipeline */
13641         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
13642         {
13643                 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
13644                 goto ERROR;
13645         }
13646
13647         debug_log("element klass : %s\n", klass);
13648
13649         /* added to support multi track files */
13650         /* only decoder case and any of the video/audio still need to link*/
13651         if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
13652         {
13653                 gchar *name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
13654
13655                 if (g_strrstr(name, "mpegtsdemux")|| g_strrstr(name, "ssdemux"))
13656                 {
13657                         gchar *src_demux_caps_str = NULL;
13658                         gchar *needed_parser = NULL;
13659                         GstCaps *src_demux_caps = NULL;
13660                         gboolean smooth_streaming = FALSE;
13661
13662                         src_demux_caps = gst_pad_get_caps(srcpad);
13663                         src_demux_caps_str = gst_caps_to_string(src_demux_caps);
13664
13665                         gst_caps_unref(src_demux_caps);
13666
13667                         if (g_strrstr(src_demux_caps_str, "video/x-h264"))
13668                         {
13669                                 if (g_strrstr(name, "ssdemux"))
13670                                 {
13671                                         needed_parser = g_strdup("legacyh264parse");
13672                                         smooth_streaming = TRUE;
13673                                 }
13674                                 else
13675                                 {
13676                                         needed_parser = g_strdup("h264parse");
13677                                 }
13678                         }
13679                         else if (g_strrstr(src_demux_caps_str, "video/mpeg"))
13680                         {
13681                                 needed_parser = g_strdup("mpeg4videoparse");
13682                         }
13683                         MMPLAYER_FREEIF(src_demux_caps_str);
13684
13685                         if (needed_parser)
13686                         {
13687                                 parser = __mmplayer_element_create_and_link(player, srcpad, needed_parser);
13688                                 MMPLAYER_FREEIF(needed_parser);
13689
13690                                 if ( !parser )
13691                                 {
13692                                         debug_error("failed to create parser\n");
13693                                 }
13694                                 else
13695                                 {
13696                                         if (smooth_streaming)
13697                                         {
13698                                                 g_object_set (parser, "output-format", 1, NULL); /* NALU/Byte Stream format */
13699                                         }
13700
13701                                         /* update srcpad if parser is created */
13702                                         pssrcpad = gst_element_get_static_pad(parser, "src");
13703                                         srcpad = pssrcpad;
13704                                 }
13705                         }
13706                 }
13707                 MMPLAYER_FREEIF(name);
13708
13709                 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
13710                 if ( ! queue )
13711                 {
13712                         debug_error("failed to create queue\n");
13713                         goto ERROR;
13714                 }
13715
13716                 /* update srcpad to link with decoder */
13717                 qsrcpad = gst_element_get_static_pad(queue, "src");
13718                 srcpad = qsrcpad;
13719
13720                 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
13721
13722                 /* assigning queue handle for futher manipulation purpose */
13723                 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
13724                 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
13725                 {
13726                         mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
13727                         mainbin[MMPLAYER_M_Q1].gst = queue;
13728
13729                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
13730                         {
13731                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", 0 , NULL);
13732                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-buffers", 2, NULL);
13733                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-bytes", 0, NULL);
13734                         }
13735                         else
13736                         {
13737                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
13738                                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
13739                         }
13740                 }
13741                 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
13742                 {
13743                         mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
13744                         mainbin[MMPLAYER_M_Q2].gst = queue;
13745
13746                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
13747                         {
13748                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", 0 , NULL);
13749                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-buffers", 2, NULL);
13750                                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-bytes", 0, NULL);
13751                         }
13752                         else
13753                         {
13754                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
13755                                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
13756                         }
13757                 }
13758                 else
13759                 {
13760                         debug_error("Not supporting more then two elementary stream\n");
13761                         g_assert(1);
13762                 }
13763
13764                 pad = gst_element_get_static_pad(sinkelement, padname);
13765
13766                 if ( ! pad )
13767                 {
13768                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
13769                                 padname, GST_ELEMENT_NAME(sinkelement) );
13770
13771                         pad = gst_element_get_static_pad(sinkelement, "sink");
13772                         if ( ! pad )
13773                         {
13774                                 debug_error("failed to get pad(sink) from %s. \n",
13775                                 GST_ELEMENT_NAME(sinkelement) );
13776                                 goto ERROR;
13777                         }
13778                 }
13779
13780                 /*  to check the video/audio type set the proper flag*/
13781                 const gchar *mime_type = NULL;
13782                 {
13783                         srccaps = gst_pad_get_caps( srcpad );
13784                         if ( !srccaps )
13785                                 goto ERROR;
13786
13787                         str = gst_caps_get_structure( srccaps, 0 );
13788                         if ( ! str )
13789                                 goto ERROR;
13790
13791                         mime_type = gst_structure_get_name(str);
13792                         if ( ! mime_type )
13793                                 goto ERROR;
13794                 }
13795
13796                 /* link queue and decoder. so, it will be queue - decoder. */
13797                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
13798                 {
13799                         gst_object_unref(GST_OBJECT(pad));
13800                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
13801
13802                         /* reconstitute supportable codec */
13803                         if (strstr(mime_type, "video"))
13804                         {
13805                                 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
13806                         }
13807                         else if (strstr(mime_type, "audio"))
13808                         {
13809                                 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
13810                         }
13811                         goto ERROR;
13812                 }
13813
13814                 if (strstr(mime_type, "video"))
13815                 {
13816                         player->videodec_linked = 1;
13817                         debug_msg("player->videodec_linked set to 1\n");
13818
13819                 }
13820                 else if (strstr(mime_type, "audio"))
13821                 {
13822                         player->audiodec_linked = 1;
13823                         debug_msg("player->auddiodec_linked set to 1\n");
13824                 }
13825
13826                 gst_object_unref(GST_OBJECT(pad));
13827                 gst_caps_unref(GST_CAPS(srccaps));
13828                 srccaps = NULL;
13829         }
13830
13831         if ( !MMPLAYER_IS_HTTP_PD(player) )
13832         {
13833                 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
13834                 {
13835                         if (MMPLAYER_IS_HTTP_STREAMING(player))
13836                         {
13837                                 GstFormat fmt  = GST_FORMAT_BYTES;
13838                                 gint64 dur_bytes = 0L;
13839                                 gchar *file_buffering_path = NULL;
13840                                 gboolean use_file_buffer = FALSE;
13841
13842                                 if ( !mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
13843                                 {
13844                                         debug_log("creating http streaming buffering queue\n");
13845
13846                                         queue = gst_element_factory_make("queue2", "queue2");
13847                                         if ( ! queue )
13848                                         {
13849                                                 debug_error ( "failed to create buffering queue element\n" );
13850                                                 goto ERROR;
13851                                         }
13852
13853                                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
13854                                         {
13855                                                 debug_error("failed to set state READY to buffering queue\n");
13856                                                 goto ERROR;
13857                                         }
13858
13859                                         if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
13860                                         {
13861                                                 debug_error("failed to add buffering queue\n");
13862                                                 goto ERROR;
13863                                         }
13864
13865                                         qsinkpad = gst_element_get_static_pad(queue, "sink");
13866                                         qsrcpad = gst_element_get_static_pad(queue, "src");
13867
13868                                         if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
13869                                         {
13870                                                 debug_error("failed to link buffering queue\n");
13871                                                 goto ERROR;
13872                                         }
13873                                         srcpad = qsrcpad;
13874
13875
13876                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
13877                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue;
13878
13879                                         if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
13880                                         {
13881                                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
13882                                                         debug_error("fail to get duration.\n");
13883
13884                                                 if (dur_bytes > 0)
13885                                                 {
13886                                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
13887                                                         file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
13888                                                 }
13889                                                 else
13890                                                 {
13891                                                         dur_bytes = 0;
13892                                                 }
13893                                         }
13894
13895                                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
13896                                         if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
13897                                         {
13898                                                 __mm_player_streaming_set_queue2(player->streamer,
13899                                                         queue,
13900                                                         TRUE,
13901                                                         player->ini.http_max_size_bytes,
13902                                                         player->ini.http_buffering_time,
13903                                                         1.0,
13904                                                         player->ini.http_buffering_limit,
13905                                                         use_file_buffer,
13906                                                         file_buffering_path,
13907                                                         (guint64)dur_bytes);
13908                                         }
13909
13910                                         MMPLAYER_FREEIF(file_buffering_path);
13911                                 }
13912                         }
13913                 }
13914         }
13915         /* if it is not decoder or */
13916         /* in decoder case any of the video/audio still need to link*/
13917         if(!g_strrstr(klass, "Decoder"))
13918         {
13919
13920                 pad = gst_element_get_static_pad(sinkelement, padname);
13921                 if ( ! pad )
13922                 {
13923                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
13924                                         padname, GST_ELEMENT_NAME(sinkelement) );
13925
13926                         pad = gst_element_get_static_pad(sinkelement, "sink");
13927
13928                         if ( ! pad )
13929                         {
13930                                 debug_error("failed to get pad(sink) from %s. \n",
13931                                         GST_ELEMENT_NAME(sinkelement) );
13932                                 goto ERROR;
13933                         }
13934                 }
13935
13936                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
13937                 {
13938                         gst_object_unref(GST_OBJECT(pad));
13939                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
13940                         goto ERROR;
13941                 }
13942
13943                 gst_object_unref(GST_OBJECT(pad));
13944         }
13945
13946         for(;templlist != NULL; templlist = templlist->next)
13947         {
13948                 padtemplate = templlist->data;
13949
13950                 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
13951
13952                 if(     padtemplate->direction != GST_PAD_SRC ||
13953                         padtemplate->presence == GST_PAD_REQUEST        )
13954                         continue;
13955
13956                 switch(padtemplate->presence)
13957                 {
13958                         case GST_PAD_ALWAYS:
13959                         {
13960                                 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
13961                                 GstCaps *caps = gst_pad_get_caps(srcpad);
13962
13963                                 /* Check whether caps has many types */
13964                                 if ( gst_caps_get_size (caps) > 1 && g_strrstr(klass, "Parser"))
13965                                 {
13966                                         debug_log ("always pad but, caps has many types");
13967                                         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
13968                                         has_many_types = TRUE;
13969                                         break;
13970                                 }
13971
13972                                 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
13973                                 {
13974                                         gst_object_unref(GST_OBJECT(srcpad));
13975                                         gst_caps_unref(GST_CAPS(caps));
13976
13977                                         debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
13978                                         goto ERROR;
13979                                 }
13980
13981                                 gst_caps_unref(GST_CAPS(caps));
13982                                 gst_object_unref(GST_OBJECT(srcpad));
13983
13984                         }
13985                         break;
13986
13987
13988                         case GST_PAD_SOMETIMES:
13989                                 has_dynamic_pads = TRUE;
13990                         break;
13991
13992                         default:
13993                                 break;
13994                 }
13995         }
13996
13997         /* check if player can do start continually */
13998         MMPLAYER_CHECK_CMD_IF_EXIT(player);
13999
14000         if( has_dynamic_pads )
14001         {
14002                 player->have_dynamic_pad = TRUE;
14003                 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
14004                         G_CALLBACK(__mmplayer_add_new_pad), player);
14005
14006                 /* for streaming, more then one typefind will used for each elementary stream
14007                  * so this doesn't mean the whole pipeline completion
14008                  */
14009                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
14010                 {
14011                         MMPLAYER_SIGNAL_CONNECT( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
14012                                 G_CALLBACK(__mmplayer_pipeline_complete), player);
14013                 }
14014         }
14015
14016         if (has_many_types)
14017         {
14018                 GstPad *pad = NULL;
14019
14020                 player->has_many_types = has_many_types;
14021
14022                 pad = gst_element_get_static_pad(sinkelement, "src");
14023                 MMPLAYER_SIGNAL_CONNECT (player, pad, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
14024                 gst_object_unref (GST_OBJECT(pad));
14025         }
14026
14027
14028         /* check if player can do start continually */
14029         MMPLAYER_CHECK_CMD_IF_EXIT(player);
14030
14031         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
14032         {
14033                 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
14034                 goto ERROR;
14035         }
14036
14037         if ( queue )
14038         {
14039                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
14040                 {
14041                         debug_error("failed to set state PAUSED to queue\n");
14042                         goto ERROR;
14043                 }
14044
14045                 queue = NULL;
14046
14047                 gst_object_unref (GST_OBJECT(qsrcpad));
14048                 qsrcpad = NULL;
14049         }
14050
14051         if ( parser )
14052         {
14053                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
14054                 {
14055                         debug_error("failed to set state PAUSED to queue\n");
14056                         goto ERROR;
14057                 }
14058
14059                 parser = NULL;
14060
14061                 gst_object_unref (GST_OBJECT(pssrcpad));
14062                 pssrcpad = NULL;
14063         }
14064
14065         MMPLAYER_FLEAVE();
14066
14067         return TRUE;
14068
14069 ERROR:
14070
14071         if ( queue )
14072         {
14073                 gst_object_unref(GST_OBJECT(qsrcpad));
14074
14075                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
14076                  * You need to explicitly set elements to the NULL state before
14077                  * dropping the final reference, to allow them to clean up.
14078                  */
14079                 gst_element_set_state(queue, GST_STATE_NULL);
14080                 /* And, it still has a parent "player".
14081                  * You need to let the parent manage the object instead of unreffing the object directly.
14082                  */
14083
14084                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
14085                 //gst_object_unref( queue );
14086         }
14087
14088         if ( srccaps )
14089                 gst_caps_unref(GST_CAPS(srccaps));
14090
14091     return FALSE;
14092 }
14093
14094 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
14095 {
14096         const gchar *klass;
14097         //const gchar *name;
14098
14099         /* we only care about element factories */
14100         if (!GST_IS_ELEMENT_FACTORY(feature))
14101                 return FALSE;
14102
14103         /* only parsers, demuxers and decoders */
14104         klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
14105         //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
14106
14107         if( g_strrstr(klass, "Demux") == NULL &&
14108                 g_strrstr(klass, "Codec/Decoder") == NULL &&
14109                 g_strrstr(klass, "Depayloader") == NULL &&
14110                 g_strrstr(klass, "Parse") == NULL)
14111         {
14112                 return FALSE;
14113         }
14114     return TRUE;
14115 }
14116
14117
14118 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
14119 {
14120         mm_player_t* player = (mm_player_t*) data;
14121         GstCaps *caps = NULL;
14122         GstStructure *str = NULL;
14123         const char *name;
14124
14125         MMPLAYER_FENTER();
14126
14127         return_if_fail ( pad )
14128         return_if_fail ( unused )
14129         return_if_fail ( data )
14130
14131         caps = gst_pad_get_caps(pad);
14132         if ( !caps )
14133                 return;
14134
14135         str = gst_caps_get_structure(caps, 0);
14136         if ( !str )
14137                 return;
14138
14139         name = gst_structure_get_name(str);
14140         if ( !name )
14141                 return;
14142         debug_log("name=%s\n", name);
14143
14144         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
14145         {
14146                 debug_error("failed to autoplug for type (%s)\n", name);
14147                 gst_caps_unref(caps);
14148                 return;
14149         }
14150
14151         gst_caps_unref(caps);
14152
14153         __mmplayer_pipeline_complete( NULL, (gpointer)player );
14154
14155         MMPLAYER_FLEAVE();
14156
14157         return;
14158 }
14159
14160 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
14161 {
14162         GstStructure *str;
14163         gint version = 0;
14164         const char *stream_type;
14165         gchar *version_field = NULL;
14166
14167         MMPLAYER_FENTER();
14168
14169         return_if_fail ( player );
14170         return_if_fail ( caps );
14171
14172         str = gst_caps_get_structure(caps, 0);
14173         if ( !str )
14174                 return;
14175
14176         stream_type = gst_structure_get_name(str);
14177         if ( !stream_type )
14178                 return;
14179
14180
14181         /* set unlinked mime type for downloadable codec */
14182         if (g_str_has_prefix(stream_type, "video/"))
14183         {
14184                 if (g_str_has_prefix(stream_type, "video/mpeg"))
14185                 {
14186                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
14187                         version_field = MM_PLAYER_MPEG_VNAME;
14188                 }
14189                 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
14190                 {
14191                         gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
14192                         version_field = MM_PLAYER_WMV_VNAME;
14193
14194                 }
14195                 else if (g_str_has_prefix(stream_type, "video/x-divx"))
14196                 {
14197                         gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
14198                         version_field = MM_PLAYER_DIVX_VNAME;
14199                 }
14200
14201                 if (version)
14202                 {
14203                         player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
14204                 }
14205                 else
14206                 {
14207                         player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
14208                 }
14209         }
14210         else if (g_str_has_prefix(stream_type, "audio/"))
14211         {
14212                 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
14213                 {
14214                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
14215                         version_field = MM_PLAYER_MPEG_VNAME;
14216                 }
14217                 else if (g_str_has_prefix(stream_type, "audio/x-wma"))
14218                 {
14219                         gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
14220                         version_field = MM_PLAYER_WMA_VNAME;
14221                 }
14222
14223                 if (version)
14224                 {
14225                         player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
14226                 }
14227                 else
14228                 {
14229                         player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
14230                 }
14231         }
14232
14233         MMPLAYER_FLEAVE();
14234 }
14235
14236 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
14237 {
14238         mm_player_t* player = (mm_player_t*) data;
14239         GstCaps *caps = NULL;
14240         GstStructure *str = NULL;
14241         const char *name;
14242
14243         MMPLAYER_FENTER();
14244         return_if_fail ( player );
14245         return_if_fail ( pad );
14246
14247         GST_OBJECT_LOCK (pad);
14248         if ((caps = GST_PAD_CAPS(pad)))
14249                 gst_caps_ref(caps);
14250         GST_OBJECT_UNLOCK (pad);
14251
14252         if ( NULL == caps )
14253         {
14254                 caps = gst_pad_get_caps(pad);
14255                 if ( !caps ) return;
14256         }
14257
14258         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
14259
14260         str = gst_caps_get_structure(caps, 0);
14261         if ( !str )
14262                 return;
14263
14264         name = gst_structure_get_name(str);
14265         if ( !name )
14266                 return;
14267
14268         player->num_dynamic_pad++;
14269         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
14270
14271         /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
14272           *     If want to play it, remove this code.
14273           */
14274         if (g_strrstr(name, "application"))
14275         {
14276                 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
14277                 {
14278                         /* If id3/ape tag comes, keep going */
14279                         debug_log("application mime exception : id3/ape tag");
14280                 }
14281                 else
14282                 {
14283                         /* Otherwise, we assume that this stream is subtile. */
14284                         debug_log(" application mime type pad is closed.");
14285                         return;
14286                 }
14287         }
14288         else if (g_strrstr(name, "audio"))
14289         {
14290                 gint samplerate = 0, channels = 0;
14291
14292                 if (player->audiodec_linked)
14293                 {
14294                         gst_caps_unref(caps);
14295                         debug_log("multi tracks. skip to plug");
14296                         return;
14297                 }
14298
14299                 /* set stream information */
14300                 /* if possible, set it here because the caps is not distrubed by resampler. */
14301                 gst_structure_get_int (str, "rate", &samplerate);
14302                 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
14303
14304                 gst_structure_get_int (str, "channels", &channels);
14305                 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
14306
14307                 debug_log("audio samplerate : %d        channels : %d", samplerate, channels);
14308         }
14309         else if (g_strrstr(name, "video"))
14310         {
14311                 gint stype;
14312                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
14313
14314                 /* don't make video because of not required */
14315                 if (stype == MM_DISPLAY_SURFACE_NULL)
14316                 {
14317                         debug_log("no video because it's not required");
14318                         return;
14319                 }
14320
14321                 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
14322         }
14323
14324         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
14325         {
14326                 debug_error("failed to autoplug for type (%s)", name);
14327
14328                 __mmplayer_set_unlinked_mime_type(player, caps);
14329         }
14330
14331         gst_caps_unref(caps);
14332
14333         MMPLAYER_FLEAVE();
14334         return;
14335 }
14336
14337 /* test API for tuning audio gain. this API should be
14338  * deprecated before the day of final release
14339  */
14340 int
14341 _mmplayer_set_volume_tune(MMHandleType hplayer, MMPlayerVolumeType volume)
14342 {
14343         mm_player_t* player = (mm_player_t*) hplayer;
14344         gint error = MM_ERROR_NONE;
14345         gint vol_max = 0;
14346         gboolean isMidi = FALSE;
14347         gint i = 0;
14348
14349         MMPLAYER_FENTER();
14350
14351         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14352         return_val_if_fail( player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED )
14353
14354         debug_log("clip type=%d(1-midi, 0-others), volume [L]=%d:[R]=%d\n",
14355                 player->profile.play_mode, volume.level[0], volume.level[1]);
14356
14357         isMidi = ( player->profile.play_mode == MM_PLAYER_MODE_MIDI ) ? TRUE : FALSE;
14358
14359         if ( isMidi )
14360                 vol_max = 1000;
14361         else
14362                 vol_max = 100;
14363
14364         /* is it proper volume level? */
14365         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; ++i)
14366         {
14367                 if (volume.level[i] < 0 || volume.level[i] > vol_max) {
14368                         debug_log("Invalid Volume level!!!! \n");
14369                         return MM_ERROR_INVALID_ARGUMENT;
14370                 }
14371         }
14372
14373         if ( isMidi )
14374         {
14375                 if ( player->pipeline->mainbin )
14376                 {
14377                         GstElement *midi_element = player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst;
14378
14379                         if ( midi_element && ( strstr(GST_ELEMENT_NAME(midi_element), "midiparse")) )
14380                         {
14381                                 debug_log("setting volume (%d) level to midi plugin\n", volume.level[0]);
14382
14383                                 g_object_set(midi_element, "volume", volume.level[0], NULL);
14384                         }
14385                 }
14386         }
14387         else
14388         {
14389                 if ( player->pipeline->audiobin )
14390                 {
14391                         GstElement *sink_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
14392
14393                         /* Set to Avsysaudiosink element */
14394                         if ( sink_element )
14395                         {
14396                                 gint vol_value = 0;
14397                                 gboolean mute = FALSE;
14398                                 vol_value = volume.level[0];
14399
14400                                 g_object_set(G_OBJECT(sink_element), "tuningvolume", vol_value, NULL);
14401
14402                                 mute = (vol_value == 0)? TRUE:FALSE;
14403
14404                                 g_object_set(G_OBJECT(sink_element), "mute", mute, NULL);
14405                         }
14406
14407                 }
14408         }
14409
14410         MMPLAYER_FLEAVE();
14411
14412         return error;
14413 }
14414
14415 gboolean
14416 __mmplayer_dump_pipeline_state( mm_player_t* player )
14417 {
14418         GstIterator*iter = NULL;
14419         gboolean done = FALSE;
14420
14421         GstElement *item = NULL;
14422         GstElementFactory *factory = NULL;
14423
14424         GstState state = GST_STATE_VOID_PENDING;
14425         GstState pending = GST_STATE_VOID_PENDING;
14426         GstClockTime time = 200*GST_MSECOND;
14427
14428         MMPLAYER_FENTER();
14429
14430         return_val_if_fail ( player &&
14431                 player->pipeline &&
14432                 player->pipeline->mainbin,
14433                 FALSE );
14434
14435         iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) );
14436
14437         if ( iter != NULL )
14438         {
14439                 while (!done) {
14440                          switch ( gst_iterator_next (iter, (gpointer)&item) )
14441                          {
14442                            case GST_ITERATOR_OK:
14443                                 gst_element_get_state(GST_ELEMENT (item),&state, &pending,time);
14444
14445                                 factory = gst_element_get_factory (item) ;
14446                                 if (factory)
14447                                 {
14448                                          debug_error("%s:%s : From:%s To:%s   refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(item) ,
14449                                                 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(item));
14450                                 }
14451                                  gst_object_unref (item);
14452                                  break;
14453                            case GST_ITERATOR_RESYNC:
14454                                  gst_iterator_resync (iter);
14455                                  break;
14456                            case GST_ITERATOR_ERROR:
14457                                  done = TRUE;
14458                                  break;
14459                            case GST_ITERATOR_DONE:
14460                                  done = TRUE;
14461                                  break;
14462                          }
14463                 }
14464         }
14465
14466         item = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
14467
14468         gst_element_get_state(GST_ELEMENT (item),&state, &pending,time);
14469
14470         factory = gst_element_get_factory (item) ;
14471
14472         if (factory)
14473         {
14474                 debug_error("%s:%s : From:%s To:%s  refcount : %d\n",
14475                         GST_OBJECT_NAME(factory),
14476                         GST_ELEMENT_NAME(item),
14477                         gst_element_state_get_name(state),
14478                         gst_element_state_get_name(pending),
14479                         GST_OBJECT_REFCOUNT_VALUE(item) );
14480         }
14481
14482         if ( iter )
14483                 gst_iterator_free (iter);
14484
14485         MMPLAYER_FLEAVE();
14486
14487         return FALSE;
14488 }
14489
14490
14491 gboolean
14492 __mmplayer_check_subtitle( mm_player_t* player )
14493 {
14494         MMHandleType attrs = 0;
14495         char *subtitle_uri = NULL;
14496
14497         MMPLAYER_FENTER();
14498
14499         return_val_if_fail( player, FALSE );
14500
14501         /* get subtitle attribute */
14502         attrs = MMPLAYER_GET_ATTRS(player);
14503         if ( !attrs )
14504                 return FALSE;
14505
14506         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
14507         if ( !subtitle_uri || !strlen(subtitle_uri))
14508                 return FALSE;
14509
14510         debug_log ("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
14511         player->is_external_subtitle_present = TRUE;
14512
14513         MMPLAYER_FLEAVE();
14514
14515         return TRUE;
14516 }
14517
14518 static gboolean
14519 __mmplayer_can_extract_pcm( mm_player_t* player )
14520 {
14521         MMHandleType attrs = 0;
14522         gboolean is_drm = FALSE;
14523         gboolean sound_extraction = FALSE;
14524
14525         return_val_if_fail ( player, FALSE );
14526
14527         attrs = MMPLAYER_GET_ATTRS(player);
14528         if ( !attrs )
14529         {
14530                 debug_error("fail to get attributes.");
14531                 return FALSE;
14532         }
14533
14534         /* check file is drm or not */
14535         if (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm"))
14536                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
14537
14538         /* get sound_extraction property */
14539         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
14540
14541         if ( ! sound_extraction || is_drm )
14542         {
14543                 debug_log("checking pcm extraction mode : %d, drm : %d", sound_extraction, is_drm);
14544                 return FALSE;
14545         }
14546
14547         return TRUE;
14548 }
14549
14550 static gboolean
14551 __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error )
14552 {
14553         MMMessageParamType msg_param;
14554         gchar *msg_src_element;
14555
14556         MMPLAYER_FENTER();
14557
14558         return_val_if_fail( player, FALSE );
14559         return_val_if_fail( error, FALSE );
14560
14561         /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
14562
14563         memset (&msg_param, 0, sizeof(MMMessageParamType));
14564
14565         if ( error->domain == GST_CORE_ERROR )
14566         {
14567                 msg_param.code = __gst_handle_core_error( player, error->code );
14568         }
14569         else if ( error->domain == GST_LIBRARY_ERROR )
14570         {
14571                 msg_param.code = __gst_handle_library_error( player, error->code );
14572         }
14573         else if ( error->domain == GST_RESOURCE_ERROR )
14574         {
14575                 msg_param.code = __gst_handle_resource_error( player, error->code );
14576         }
14577         else if ( error->domain == GST_STREAM_ERROR )
14578         {
14579                 msg_param.code = __gst_handle_stream_error( player, error, message );
14580         }
14581         else
14582         {
14583                 debug_warning("This error domain is not defined.\n");
14584
14585                 /* we treat system error as an internal error */
14586                 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
14587         }
14588
14589         if ( message->src )
14590         {
14591                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
14592
14593                 msg_param.data = (void *) error->message;
14594
14595                 debug_error("-Msg src : [%s]    Domain : [%s]   Error : [%s]  Code : [%d] is tranlated to error code : [0x%x]\n",
14596                         msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg_param.code);
14597         }
14598
14599         /* no error */
14600         if (msg_param.code == MM_ERROR_NONE)
14601                 return TRUE;
14602
14603         /* post error to application */
14604         if ( ! player->msg_posted )
14605         {
14606                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
14607                 /* don't post more if one was sent already */
14608                 player->msg_posted = TRUE;
14609         }
14610         else
14611         {
14612                 debug_log("skip error post because it's sent already.\n");
14613         }
14614
14615         MMPLAYER_FLEAVE();
14616
14617         return TRUE;
14618 }
14619
14620 static gboolean
14621 __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message )
14622 {
14623         debug_log("\n");
14624         MMMessageParamType msg_param;
14625         gchar *msg_src_element = NULL;
14626         GstStructure *s = NULL;
14627         guint error_id = 0;
14628         gchar *error_string = NULL;
14629
14630         MMPLAYER_FENTER();
14631
14632         return_val_if_fail ( player, FALSE );
14633         return_val_if_fail ( message, FALSE );
14634
14635         s = malloc( sizeof(GstStructure) );
14636         if ( s == NULL)
14637         {
14638                 debug_error ("malloc fail");
14639                 return FALSE;
14640         }
14641         memcpy ( s, gst_message_get_structure ( message ), sizeof(GstStructure));
14642
14643         if ( !gst_structure_get_uint (s, "error_id", &error_id) )
14644                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
14645
14646         switch ( error_id )
14647         {
14648                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
14649                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
14650                         break;
14651                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
14652                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
14653                         break;
14654                 case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
14655                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
14656                         break;
14657                 case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
14658                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
14659                         break;
14660                 case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
14661                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
14662                         break;
14663                 case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
14664                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
14665                         break;
14666                 case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
14667                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
14668                         break;
14669                 case MMPLAYER_STREAMING_ERROR_INVALID_URL:
14670                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
14671                         break;
14672                 case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
14673                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
14674                         break;
14675                 case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
14676                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
14677                         break;
14678                 case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
14679                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
14680                         break;
14681                 case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
14682                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
14683                         break;
14684                 case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
14685                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
14686                         break;
14687                 case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
14688                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
14689                         break;
14690                 case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
14691                         msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
14692                         break;
14693                 case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
14694                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
14695                         break;
14696                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
14697                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
14698                         break;
14699                 case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
14700                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
14701                         break;
14702                 case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
14703                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
14704                         break;
14705                 case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
14706                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
14707                         break;
14708                 case MMPLAYER_STREAMING_ERROR_GONE:
14709                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
14710                         break;
14711                 case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
14712                         msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
14713                         break;
14714                 case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
14715                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
14716                         break;
14717                 case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
14718                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
14719                         break;
14720                 case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
14721                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
14722                         break;
14723                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
14724                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
14725                         break;
14726                 case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
14727                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
14728                         break;
14729                 case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
14730                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
14731                         break;
14732                 case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
14733                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
14734                         break;
14735                 case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
14736                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
14737                         break;
14738                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
14739                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
14740                         break;
14741                 case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
14742                         msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
14743                         break;
14744                 case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
14745                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
14746                         break;
14747                 case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
14748                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
14749                         break;
14750                 case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
14751                         msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
14752                         break;
14753                 case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
14754                         msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
14755                         break;
14756                 case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
14757                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
14758                         break;
14759                 case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
14760                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
14761                         break;
14762                 case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
14763                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
14764                         break;
14765                 case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
14766                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
14767                         break;
14768                 case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
14769                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
14770                         break;
14771                 case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
14772                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
14773                         break;
14774                 case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
14775                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
14776                         break;
14777                 case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
14778                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
14779                         break;
14780                 case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
14781                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
14782                         break;
14783                 default:
14784                         {
14785                                 MMPLAYER_FREEIF(s);
14786                                 return MM_ERROR_PLAYER_STREAMING_FAIL;
14787                         }
14788         }
14789
14790         error_string = g_strdup(gst_structure_get_string (s, "error_string"));
14791         if ( error_string )
14792                 msg_param.data = (void *) error_string;
14793
14794         if ( message->src )
14795         {
14796                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
14797
14798                 debug_error("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
14799                         msg_src_element, msg_param.code, (char*)msg_param.data );
14800         }
14801
14802         /* post error to application */
14803         if ( ! player->msg_posted )
14804         {
14805                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
14806
14807                 /* don't post more if one was sent already */
14808                 player->msg_posted = TRUE;
14809         }
14810         else
14811         {
14812                 debug_log("skip error post because it's sent already.\n");
14813         }
14814
14815         MMPLAYER_FREEIF(s);
14816         MMPLAYER_FLEAVE();
14817         g_free(error_string);
14818
14819         return TRUE;
14820
14821 }
14822
14823 static gint
14824 __gst_handle_core_error( mm_player_t* player, int code )
14825 {
14826         gint trans_err = MM_ERROR_NONE;
14827
14828         MMPLAYER_FENTER();
14829
14830         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14831
14832         switch ( code )
14833         {
14834                 case GST_CORE_ERROR_MISSING_PLUGIN:
14835                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
14836                 case GST_CORE_ERROR_STATE_CHANGE:
14837                 case GST_CORE_ERROR_SEEK:
14838                 case GST_CORE_ERROR_NOT_IMPLEMENTED:
14839                 case GST_CORE_ERROR_FAILED:
14840                 case GST_CORE_ERROR_TOO_LAZY:
14841                 case GST_CORE_ERROR_PAD:
14842                 case GST_CORE_ERROR_THREAD:
14843                 case GST_CORE_ERROR_NEGOTIATION:
14844                 case GST_CORE_ERROR_EVENT:
14845                 case GST_CORE_ERROR_CAPS:
14846                 case GST_CORE_ERROR_TAG:
14847                 case GST_CORE_ERROR_CLOCK:
14848                 case GST_CORE_ERROR_DISABLED:
14849                 default:
14850                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
14851                 break;
14852         }
14853
14854         MMPLAYER_FLEAVE();
14855
14856         return trans_err;
14857 }
14858
14859 static gint
14860 __gst_handle_library_error( mm_player_t* player, int code )
14861 {
14862         gint trans_err = MM_ERROR_NONE;
14863
14864         MMPLAYER_FENTER();
14865
14866         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14867
14868         switch ( code )
14869         {
14870                 case GST_LIBRARY_ERROR_FAILED:
14871                 case GST_LIBRARY_ERROR_TOO_LAZY:
14872                 case GST_LIBRARY_ERROR_INIT:
14873                 case GST_LIBRARY_ERROR_SHUTDOWN:
14874                 case GST_LIBRARY_ERROR_SETTINGS:
14875                 case GST_LIBRARY_ERROR_ENCODE:
14876                 default:
14877                         trans_err =  MM_ERROR_PLAYER_INVALID_STREAM;
14878                 break;
14879         }
14880
14881         MMPLAYER_FLEAVE();
14882
14883         return trans_err;
14884 }
14885
14886
14887 static gint
14888 __gst_handle_resource_error( mm_player_t* player, int code )
14889 {
14890         gint trans_err = MM_ERROR_NONE;
14891
14892         MMPLAYER_FENTER();
14893
14894         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14895
14896         switch ( code )
14897         {
14898                 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
14899                         trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
14900                         break;
14901                 case GST_RESOURCE_ERROR_NOT_FOUND:
14902                 case GST_RESOURCE_ERROR_OPEN_READ:
14903                         if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
14904                                 || MMPLAYER_IS_RTSP_STREAMING(player))
14905                         {
14906                                 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
14907                                 break;
14908                         }
14909                 case GST_RESOURCE_ERROR_READ:
14910                         if ( MMPLAYER_IS_HTTP_STREAMING(player) ||  MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
14911                                 || MMPLAYER_IS_RTSP_STREAMING(player))
14912                         {
14913                                 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
14914                                 break;
14915                         }
14916                 case GST_RESOURCE_ERROR_WRITE:
14917                 case GST_RESOURCE_ERROR_FAILED:
14918                 case GST_RESOURCE_ERROR_SEEK:
14919                 case GST_RESOURCE_ERROR_TOO_LAZY:
14920                 case GST_RESOURCE_ERROR_BUSY:
14921                 case GST_RESOURCE_ERROR_OPEN_WRITE:
14922                 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
14923                 case GST_RESOURCE_ERROR_CLOSE:
14924                 case GST_RESOURCE_ERROR_SYNC:
14925                 case GST_RESOURCE_ERROR_SETTINGS:
14926                 default:
14927                         trans_err = MM_ERROR_PLAYER_INTERNAL;
14928                 break;
14929         }
14930
14931         MMPLAYER_FLEAVE();
14932
14933         return trans_err;
14934 }
14935
14936
14937 static gint
14938 __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message )
14939 {
14940         gint trans_err = MM_ERROR_NONE;
14941
14942         MMPLAYER_FENTER();
14943
14944         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14945         return_val_if_fail( error, MM_ERROR_INVALID_ARGUMENT );
14946         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
14947
14948         switch ( error->code )
14949         {
14950                 case GST_STREAM_ERROR_FAILED:
14951                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
14952                 case GST_STREAM_ERROR_DECODE:
14953                 case GST_STREAM_ERROR_WRONG_TYPE:
14954                 case GST_STREAM_ERROR_DECRYPT:
14955                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
14956                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
14957                          trans_err = __gst_transform_gsterror( player, message, error );
14958                 break;
14959
14960                 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
14961                 case GST_STREAM_ERROR_TOO_LAZY:
14962                 case GST_STREAM_ERROR_ENCODE:
14963                 case GST_STREAM_ERROR_DEMUX:
14964                 case GST_STREAM_ERROR_MUX:
14965                 case GST_STREAM_ERROR_FORMAT:
14966                 default:
14967                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
14968                 break;
14969         }
14970
14971         MMPLAYER_FLEAVE();
14972
14973         return trans_err;
14974 }
14975
14976 /* NOTE : decide gstreamer state whether there is some playable track or not. */
14977 static gint
14978 __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error )
14979 {
14980         gchar *src_element_name = NULL;
14981         GstElement *src_element = NULL;
14982         GstElementFactory *factory = NULL;
14983         const gchar* klass = NULL;
14984
14985         MMPLAYER_FENTER();
14986
14987         /* FIXIT */
14988         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
14989         return_val_if_fail ( message->src, MM_ERROR_INVALID_ARGUMENT );
14990         return_val_if_fail ( error, MM_ERROR_INVALID_ARGUMENT );
14991
14992         src_element = GST_ELEMENT_CAST(message->src);
14993         if ( !src_element )
14994                 goto INTERNAL_ERROR;
14995
14996         src_element_name = GST_ELEMENT_NAME(src_element);
14997         if ( !src_element_name )
14998                 goto INTERNAL_ERROR;
14999
15000         factory = gst_element_get_factory(src_element);
15001         if ( !factory )
15002                 goto INTERNAL_ERROR;
15003
15004         klass = gst_element_factory_get_klass(factory);
15005         if ( !klass )
15006                 goto INTERNAL_ERROR;
15007
15008         debug_log("error code=%d, msg=%s, src element=%s, class=%s\n",
15009                         error->code, error->message, src_element_name, klass);
15010
15011         //<-
15012         {
15013                 int msg_src_pos = 0;
15014                 gint active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
15015                 debug_log ("current  active pad index  -%d", active_pad_index);
15016
15017                 if  (src_element_name) {
15018                         int idx = 0;
15019
15020                         if (player->audio_decoders) {
15021                                 GList *adec = player->audio_decoders;
15022                                 for ( ;adec ; adec = g_list_next(adec)) {
15023                                         gchar *name = adec->data;
15024
15025                                         debug_log("found audio decoder name  = %s", name);
15026                                         if (g_strrstr(name, src_element_name)) {
15027                                                 msg_src_pos = idx;
15028                                                 break;
15029                                         }
15030                                         idx++;
15031                                 }
15032                         }
15033                         debug_log("active pad = %d, error src index = %d", active_pad_index,  msg_src_pos);
15034                 }
15035
15036                 if (active_pad_index != msg_src_pos) {
15037                         debug_log("skip error because error is posted from no activated track");
15038                         return MM_ERROR_NONE;
15039                 }
15040         }
15041         //-> temp code
15042
15043         switch ( error->code )
15044         {
15045                 case GST_STREAM_ERROR_DECODE:
15046                 {
15047                         /* Demuxer can't parse one track because it's corrupted.
15048                          * So, the decoder for it is not linked.
15049                          * But, it has one playable track.
15050                          */
15051                         if ( g_strrstr(klass, "Demux") )
15052                         {
15053                                 if ( player->can_support_codec == FOUND_PLUGIN_VIDEO )
15054                                 {
15055                                         return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
15056                                 }
15057                                 else if ( player->can_support_codec == FOUND_PLUGIN_AUDIO )
15058                                 {
15059                                         return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15060                                 }
15061                                 else
15062                                 {
15063                                         if ( player->pipeline->audiobin ) // PCM
15064                                         {
15065                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15066                                         }
15067                                         else
15068                                         {
15069                                                 goto CODEC_NOT_FOUND;
15070                                         }
15071                                 }
15072                         }
15073                         return MM_ERROR_PLAYER_INVALID_STREAM;
15074                 }
15075                 break;
15076
15077                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
15078                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
15079                 case GST_STREAM_ERROR_WRONG_TYPE:
15080                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15081
15082                 case GST_STREAM_ERROR_FAILED:
15083                 {
15084                         /* Decoder Custom Message */
15085                         if ( strstr(error->message, "ongoing") )
15086                         {
15087                                 if ( strncasecmp(klass, "audio", 5) )
15088                                 {
15089                                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) )
15090                                         {
15091                                                 debug_log("Video can keep playing.\n");
15092                                                 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
15093                                         }
15094                                         else
15095                                         {
15096                                                 goto CODEC_NOT_FOUND;
15097                                         }
15098
15099                                 }
15100                                 else if ( strncasecmp(klass, "video", 5) )
15101                                 {
15102                                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) )
15103                                         {
15104                                                 debug_log("Audio can keep playing.\n");
15105                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15106                                         }
15107                                         else
15108                                         {
15109                                                 goto CODEC_NOT_FOUND;
15110                                         }
15111                                 }
15112                         }
15113                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15114                 }
15115                 break;
15116
15117                 case GST_STREAM_ERROR_DECRYPT:
15118                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
15119                 {
15120                         debug_error("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
15121
15122                         if ( strstr(error->message, "rights expired") )
15123                         {
15124                                 return MM_ERROR_PLAYER_DRM_EXPIRED;
15125                         }
15126                         else if ( strstr(error->message, "no rights") )
15127                         {
15128                                 return MM_ERROR_PLAYER_DRM_NO_LICENSE;
15129                         }
15130                         else if ( strstr(error->message, "has future rights") )
15131                         {
15132                                 return MM_ERROR_PLAYER_DRM_FUTURE_USE;
15133                         }
15134                         else if ( strstr(error->message, "opl violation") )
15135                         {
15136                                 return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
15137                         }
15138                         return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
15139                 }
15140                 break;
15141
15142                 default:
15143                 break;
15144         }
15145
15146         MMPLAYER_FLEAVE();
15147
15148         return MM_ERROR_PLAYER_INVALID_STREAM;
15149
15150 INTERNAL_ERROR:
15151         return MM_ERROR_PLAYER_INTERNAL;
15152
15153 CODEC_NOT_FOUND:
15154         debug_log("not found any available codec. Player should be destroyed.\n");
15155         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
15156 }
15157
15158 static void
15159 __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms )
15160 {
15161         return_if_fail( player );
15162
15163
15164         /* post now if delay is zero */
15165         if ( delay_in_ms == 0 || player->set_mode.pcm_extraction)
15166         {
15167                 debug_log("eos delay is zero. posting EOS now\n");
15168                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15169
15170                 if ( player->set_mode.pcm_extraction )
15171                         __mmplayer_cancel_eos_timer(player);
15172
15173                 return;
15174         }
15175
15176         /* cancel if existing */
15177         __mmplayer_cancel_eos_timer( player );
15178
15179         /* init new timeout */
15180         /* NOTE : consider give high priority to this timer */
15181         debug_log("posting EOS message after [%d] msec\n", delay_in_ms);
15182
15183         player->eos_timer = g_timeout_add( delay_in_ms,
15184                 __mmplayer_eos_timer_cb, player );
15185
15186         player->context.global_default = g_main_context_default ();
15187         debug_log("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
15188
15189         /* check timer is valid. if not, send EOS now */
15190         if ( player->eos_timer == 0 )
15191         {
15192                 debug_warning("creating timer for delayed EOS has failed. sending EOS now\n");
15193                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15194         }
15195 }
15196
15197 static void
15198 __mmplayer_cancel_eos_timer( mm_player_t* player )
15199 {
15200         return_if_fail( player );
15201
15202         if ( player->eos_timer )
15203         {
15204                 debug_log("cancel eos timer");
15205                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
15206                 player->eos_timer = 0;
15207         }
15208
15209         return;
15210 }
15211
15212 static gboolean
15213 __mmplayer_eos_timer_cb(gpointer u_data)
15214 {
15215         mm_player_t* player = NULL;
15216         player = (mm_player_t*) u_data;
15217
15218         return_val_if_fail( player, FALSE );
15219
15220         if ( player->play_count > 1 )
15221         {
15222                 gint ret_value = 0;
15223                 ret_value = __gst_set_position( player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
15224                 if (ret_value == MM_ERROR_NONE)
15225                 {
15226                         MMHandleType attrs = 0;
15227                         attrs = MMPLAYER_GET_ATTRS(player);
15228
15229                         /* we successeded to rewind. update play count and then wait for next EOS */
15230                         player->play_count--;
15231
15232                         mm_attrs_set_int_by_name(attrs, "profile_play_count", player->play_count);
15233                         mmf_attrs_commit ( attrs );
15234                 }
15235                 else
15236                 {
15237                         debug_error("seeking to 0 failed in repeat play");
15238                 }
15239         }
15240         else
15241         {
15242                 /* posting eos */
15243                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15244         }
15245
15246         /* we are returning FALSE as we need only one posting */
15247         return FALSE;
15248 }
15249
15250 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force)
15251 {
15252         gint antishock = FALSE;
15253         MMHandleType attrs = 0;
15254
15255         MMPLAYER_FENTER();
15256
15257         return_if_fail ( player && player->pipeline );
15258
15259         /* It should be passed for video only clip */
15260         if ( ! player->pipeline->audiobin )
15261                 return;
15262
15263         if ( ( g_strrstr(player->ini.name_of_audiosink, "avsysaudiosink")) )
15264         {
15265                 attrs = MMPLAYER_GET_ATTRS(player);
15266                 if ( ! attrs )
15267                 {
15268                         debug_error("fail to get attributes.\n");
15269                         return;
15270                 }
15271
15272                 mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock);
15273
15274                 if (player->sm.antishock) {
15275                         antishock = TRUE;
15276                         player->sm.antishock = 0;
15277                 }
15278
15279                 debug_log("setting antishock as (%d)\n", antishock);
15280
15281                 if ( disable_by_force )
15282                 {
15283                         debug_log("but, antishock is disabled by force when is seeked\n");
15284
15285                         antishock = FALSE;
15286                 }
15287
15288                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "fadeup", antishock, NULL);
15289         }
15290
15291         MMPLAYER_FLEAVE();
15292
15293         return;
15294 }
15295
15296
15297 static gboolean
15298 __mmplayer_link_decoder( mm_player_t* player, GstPad *srcpad)
15299 {
15300         const gchar* name = NULL;
15301         GstStructure* str = NULL;
15302         GstCaps* srccaps = NULL;
15303
15304         MMPLAYER_FENTER();
15305
15306         return_val_if_fail( player, FALSE );
15307         return_val_if_fail ( srcpad, FALSE );
15308
15309         /* to check any of the decoder (video/audio) need to be linked  to parser*/
15310         srccaps = gst_pad_get_caps( srcpad );
15311         if ( !srccaps )
15312                 goto ERROR;
15313
15314         str = gst_caps_get_structure( srccaps, 0 );
15315         if ( ! str )
15316                 goto ERROR;
15317
15318         name = gst_structure_get_name(str);
15319         if ( ! name )
15320                 goto ERROR;
15321
15322         if (strstr(name, "video"))
15323         {
15324                 if(player->videodec_linked)
15325                 {
15326                     debug_msg("Video decoder already linked\n");
15327                         return FALSE;
15328                 }
15329         }
15330         if (strstr(name, "audio"))
15331         {
15332                 if(player->audiodec_linked)
15333                 {
15334                     debug_msg("Audio decoder already linked\n");
15335                         return FALSE;
15336                 }
15337         }
15338
15339         gst_caps_unref( srccaps );
15340
15341         MMPLAYER_FLEAVE();
15342
15343         return TRUE;
15344
15345 ERROR:
15346         if ( srccaps )
15347                 gst_caps_unref( srccaps );
15348
15349         return FALSE;
15350 }
15351
15352 static gboolean
15353 __mmplayer_link_sink( mm_player_t* player , GstPad *srcpad)
15354 {
15355         const gchar* name = NULL;
15356         GstStructure* str = NULL;
15357         GstCaps* srccaps = NULL;
15358
15359         MMPLAYER_FENTER();
15360
15361         return_val_if_fail ( player, FALSE );
15362         return_val_if_fail ( srcpad, FALSE );
15363
15364         /* to check any of the decoder (video/audio) need to be linked  to parser*/
15365         srccaps = gst_pad_get_caps( srcpad );
15366         if ( !srccaps )
15367                 goto ERROR;
15368
15369         str = gst_caps_get_structure( srccaps, 0 );
15370         if ( ! str )
15371                 goto ERROR;
15372
15373         name = gst_structure_get_name(str);
15374         if ( ! name )
15375                 goto ERROR;
15376
15377         if (strstr(name, "video"))
15378         {
15379                 if(player->videosink_linked)
15380                 {
15381                         debug_msg("Video Sink already linked\n");
15382                         return FALSE;
15383                 }
15384         }
15385         if (strstr(name, "audio"))
15386         {
15387                 if(player->audiosink_linked)
15388                 {
15389                         debug_msg("Audio Sink already linked\n");
15390                         return FALSE;
15391                 }
15392         }
15393         if (strstr(name, "text"))
15394         {
15395                 if(player->textsink_linked)
15396                 {
15397                         debug_msg("Text Sink already linked\n");
15398                         return FALSE;
15399                 }
15400         }
15401
15402         gst_caps_unref( srccaps );
15403
15404         MMPLAYER_FLEAVE();
15405
15406         return TRUE;
15407         //return (!player->videosink_linked || !player->audiosink_linked);
15408
15409 ERROR:
15410         if ( srccaps )
15411                 gst_caps_unref( srccaps );
15412
15413         return FALSE;
15414 }
15415
15416
15417 /* sending event to one of sinkelements */
15418 static gboolean
15419 __gst_send_event_to_sink( mm_player_t* player, GstEvent* event )
15420 {
15421         GstEvent * event2 = NULL;
15422         GList *sinks = NULL;
15423         gboolean res = FALSE;
15424         GstPad *sinkpad = NULL;
15425         MMPLAYER_FENTER();
15426
15427         return_val_if_fail( player, FALSE );
15428         return_val_if_fail ( event, FALSE );
15429
15430         if ( player->play_subtitle && !player->use_textoverlay)
15431                 event2 = gst_event_copy((const GstEvent *)event);
15432
15433         sinks = player->sink_elements;
15434         while (sinks)
15435         {
15436                 GstElement *sink = GST_ELEMENT_CAST (sinks->data);
15437
15438                 if (GST_IS_ELEMENT(sink))
15439                 {
15440                         /* keep ref to the event */
15441                         gst_event_ref (event);
15442
15443                         if ( (res = gst_element_send_event (sink, event)) )
15444                         {
15445                                 debug_log("sending event[%s] to sink element [%s] success!\n",
15446                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
15447                                 break;
15448                         }
15449
15450                         debug_log("sending event[%s] to sink element [%s] failed. try with next one.\n",
15451                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
15452                 }
15453
15454                 sinks = g_list_next (sinks);
15455         }
15456
15457 #if 0
15458         if (internal_sub)
15459           request pad name = sink0;
15460         else
15461           request pad name = sink1; // external
15462 #endif
15463
15464         /* Note : Textbin is not linked to the video or audio bin.
15465          * It needs to send the event to the text sink seperatelly.
15466          */
15467         if ( player->play_subtitle && !player->use_textoverlay)
15468         {
15469           GstElement *text_sink = NULL;
15470           gchar *change_pad_name = NULL;
15471
15472           debug_log ("external subtitle active idx = %d", player->external_text_idx);
15473
15474           /* To get the new pad from the selector */
15475           change_pad_name = g_strdup_printf ("sink%d", player->external_text_idx);
15476           if (change_pad_name == NULL)
15477           {
15478             debug_warning ("Pad does not exists\n");
15479             return FALSE;
15480           }
15481
15482           g_object_get (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "active-pad", &sinkpad, NULL);
15483           if (!strcmp (GST_PAD_NAME (sinkpad), change_pad_name))
15484           {
15485             debug_log ("active pad & change pad are same no need to change active pad");
15486           }
15487           else
15488           {
15489             sinkpad = gst_element_get_static_pad (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, change_pad_name);
15490             if (sinkpad == NULL)
15491             {
15492               debug_error ("failed to get static pad");;
15493               return FALSE;
15494             }
15495
15496             debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
15497             g_object_set (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "active-pad", sinkpad, NULL);
15498           }
15499
15500           text_sink = GST_ELEMENT_CAST (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
15501
15502           if (GST_IS_ELEMENT(text_sink))
15503           {
15504             /* keep ref to the event */
15505             gst_event_ref (event2);
15506
15507             if ( (res != gst_element_send_event (text_sink, event2)) )
15508             {
15509               debug_error("sending event[%s] to subtitle sink element [%s] failed!\n",
15510                   GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
15511             }
15512             else
15513             {
15514               debug_log("sending event[%s] to subtitle sink element [%s] success!\n",
15515                   GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
15516             }
15517
15518             gst_event_unref (event2);
15519           }
15520           g_free(change_pad_name);
15521         }
15522
15523         gst_event_unref (event);
15524
15525         MMPLAYER_FLEAVE();
15526
15527         return res;
15528 }
15529
15530 static void
15531 __mmplayer_add_sink( mm_player_t* player, GstElement* sink )
15532 {
15533         MMPLAYER_FENTER();
15534
15535         return_if_fail ( player );
15536         return_if_fail ( sink );
15537
15538         player->sink_elements =
15539                 g_list_append(player->sink_elements, sink);
15540
15541         MMPLAYER_FLEAVE();
15542 }
15543
15544 static void
15545 __mmplayer_del_sink( mm_player_t* player, GstElement* sink )
15546 {
15547         MMPLAYER_FENTER();
15548
15549         return_if_fail ( player );
15550         return_if_fail ( sink );
15551
15552         player->sink_elements =
15553                         g_list_remove(player->sink_elements, sink);
15554
15555         MMPLAYER_FLEAVE();
15556 }
15557
15558 static gboolean
15559 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
15560                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
15561                         gint64 cur, GstSeekType stop_type, gint64 stop )
15562 {
15563         GstEvent* event = NULL;
15564         gboolean result = FALSE;
15565
15566         MMPLAYER_FENTER();
15567
15568         return_val_if_fail( player, FALSE );
15569
15570         __mmplayer_drop_subtitle(player, FALSE);
15571
15572         event = gst_event_new_seek (rate, format, flags, cur_type,
15573                 cur, stop_type, stop);
15574
15575         result = __gst_send_event_to_sink( player, event );
15576
15577         MMPLAYER_FLEAVE();
15578
15579         return result;
15580 }
15581
15582 /* NOTE : be careful with calling this api. please refer to below glib comment
15583  * glib comment : Note that there is a bug in GObject that makes this function much
15584  * less useful than it might seem otherwise. Once gobject is disposed, the callback
15585  * will no longer be called, but, the signal handler is not currently disconnected.
15586  * If the instance is itself being freed at the same time than this doesn't matter,
15587  * since the signal will automatically be removed, but if instance persists,
15588  * then the signal handler will leak. You should not remove the signal yourself
15589  * because in a future versions of GObject, the handler will automatically be
15590  * disconnected.
15591  *
15592  * It's possible to work around this problem in a way that will continue to work
15593  * with future versions of GObject by checking that the signal handler is still
15594  * connected before disconnected it:
15595  *
15596  *  if (g_signal_handler_is_connected (instance, id))
15597  *    g_signal_handler_disconnect (instance, id);
15598  */
15599 static void
15600 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
15601 {
15602         GList* sig_list = NULL;
15603         MMPlayerSignalItem* item = NULL;
15604
15605         MMPLAYER_FENTER();
15606
15607         return_if_fail( player );
15608
15609         debug_log("release signals type : %d", type);
15610
15611         if ((type < MM_PLAYER_SIGNAL_TYPE_AUTOPLUG) || (type >= MM_PLAYER_SIGNAL_TYPE_ALL))
15612         {
15613                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
15614                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
15615                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
15616                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
15617                 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
15618                 return;
15619         }
15620
15621         sig_list = player->signals[type];
15622
15623         for ( ; sig_list; sig_list = sig_list->next )
15624         {
15625                 item = sig_list->data;
15626
15627                 if ( item && item->obj && GST_IS_ELEMENT(item->obj) )
15628                 {
15629                         if ( g_signal_handler_is_connected ( item->obj, item->sig ) )
15630                         {
15631                                 g_signal_handler_disconnect ( item->obj, item->sig );
15632                         }
15633                 }
15634
15635                 MMPLAYER_FREEIF( item );
15636         }
15637
15638         g_list_free ( player->signals[type] );
15639         player->signals[type] = NULL;
15640
15641         MMPLAYER_FLEAVE();
15642
15643         return;
15644 }
15645
15646 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
15647 {
15648         mm_player_t* player = 0;
15649         int prev_display_surface_type = 0;
15650         void *prev_display_overlay = NULL;
15651         const gchar *klass = NULL;
15652         gchar *cur_videosink_name = NULL;
15653         int ret = 0;
15654         int i = 0;
15655         int num_of_dec = 2; /* DEC1, DEC2 */
15656
15657         MMPLAYER_FENTER();
15658
15659         return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
15660         return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
15661
15662         player = MM_PLAYER_CAST(handle);
15663
15664         if (surface_type < MM_DISPLAY_SURFACE_X && surface_type > MM_DISPLAY_SURFACE_EVAS)
15665         {
15666                 debug_error("Not support this surface type(%d) for changing vidoesink", surface_type);
15667                 MMPLAYER_FLEAVE();
15668                 return MM_ERROR_INVALID_ARGUMENT;
15669         }
15670
15671         /* load previous attributes */
15672         if (player->attrs)
15673         {
15674                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &prev_display_surface_type);
15675                 mm_attrs_get_data_by_name (player->attrs, "display_overlay", &prev_display_overlay);
15676                 debug_log("[0: X surface, 1: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
15677                 if (prev_display_surface_type == surface_type)
15678                 {
15679                         debug_log("incoming display surface type is same as previous one, do nothing..");
15680                         MMPLAYER_FLEAVE();
15681                         return MM_ERROR_NONE;
15682                 }
15683         }
15684         else
15685         {
15686                 debug_error("failed to load attributes");
15687                 MMPLAYER_FLEAVE();
15688                 return MM_ERROR_PLAYER_INTERNAL;
15689         }
15690
15691         /* check videosink element is created */
15692         if (!player->pipeline || !player->pipeline->videobin ||
15693                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
15694         {
15695                 debug_log("videosink element is not yet ready");
15696
15697                 /* videobin is not created yet, so we just set attributes related to display surface */
15698                 debug_log("store display attribute for given surface type(%d)", surface_type);
15699                 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
15700                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
15701                 if ( mmf_attrs_commit ( player->attrs ) )
15702                 {
15703                         debug_error("failed to commit attribute");
15704                         MMPLAYER_FLEAVE();
15705                         return MM_ERROR_PLAYER_INTERNAL;
15706                 }
15707                 MMPLAYER_FLEAVE();
15708                 return MM_ERROR_NONE;
15709         }
15710         else
15711         {
15712                 /* get player command status */
15713                 if ( !(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE) )
15714                 {
15715                         debug_error("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command",player->cmd);
15716                         MMPLAYER_FLEAVE();
15717                         return MM_ERROR_PLAYER_INVALID_STATE;
15718                 }
15719
15720                 /* get a current videosink name */
15721                 cur_videosink_name = GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
15722
15723                 /* surface change */
15724                 for ( i = 0 ; i < num_of_dec ; i++)
15725                 {
15726                         if ( player->pipeline->mainbin &&
15727                                 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst )
15728                         {
15729                                 klass = gst_element_factory_get_klass( gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) );
15730                                 if ((g_strrstr(klass, "Codec/Decoder/Video")))
15731                                 {
15732                                         if ( !strncmp(cur_videosink_name, "x", 1) && (surface_type == MM_DISPLAY_SURFACE_EVAS) )
15733                                         {
15734                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_evas, surface_type, display_overlay);
15735                                                 if (ret)
15736                                                 {
15737                                                         goto ERROR_CASE;
15738                                                 }
15739                                                 else
15740                                                 {
15741                                                         debug_warning("success to changing display surface(%d)",surface_type);
15742                                                         MMPLAYER_FLEAVE();
15743                                                         return MM_ERROR_NONE;
15744                                                 }
15745                                         }
15746                                         else if (!strncmp(cur_videosink_name, "evas", 4) && (surface_type == MM_DISPLAY_SURFACE_X) )
15747                                         {
15748                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_x, surface_type, display_overlay);
15749                                                 if (ret)
15750                                                 {
15751                                                         goto ERROR_CASE;
15752                                                 }
15753                                                 else
15754                                                 {
15755                                                         debug_warning("success to changing display surface(%d)",surface_type);
15756                                                         MMPLAYER_FLEAVE();
15757                                                         return MM_ERROR_NONE;
15758                                                 }
15759                                         }
15760                                         else
15761                                         {
15762                                                 debug_error("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface",surface_type, cur_videosink_name);
15763                                                 ret = MM_ERROR_PLAYER_INTERNAL;
15764                                                 goto ERROR_CASE;
15765                                         }
15766                                 }
15767                         }
15768                 }
15769         }
15770
15771 ERROR_CASE:
15772         /* rollback to previous attributes */
15773         mm_attrs_set_int_by_name (player->attrs, "display_surface_type", prev_display_surface_type);
15774         mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(prev_display_overlay));
15775         if ( mmf_attrs_commit ( player->attrs ) )
15776         {
15777                 debug_error("failed to commit attributes to rollback");
15778                 MMPLAYER_FLEAVE();
15779                 return MM_ERROR_PLAYER_INTERNAL;
15780         }
15781         MMPLAYER_FLEAVE();
15782         return ret;
15783 }
15784
15785 /* NOTE : It does not support some use cases, eg using colorspace converter */
15786 int
15787 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
15788 {
15789         GstPad *src_pad_dec = NULL;
15790         GstPad *sink_pad_videosink = NULL;
15791         GstPad *sink_pad_videobin = NULL;
15792         GstClock *clock = NULL;
15793         MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
15794         int ret = MM_ERROR_NONE;
15795         gboolean is_audiobin_created = TRUE;
15796
15797         MMPLAYER_FENTER();
15798
15799         return_val_if_fail(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
15800         return_val_if_fail(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
15801         return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
15802
15803         debug_log("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
15804         debug_log("surface type(%d), display overlay(%x)", surface_type, display_overlay);
15805
15806         /* get information whether if audiobin is created */
15807         if ( !player->pipeline->audiobin ||
15808                      !player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
15809         {
15810                 debug_warning("audiobin is null, this video content may not have audio data");
15811                 is_audiobin_created = FALSE;
15812         }
15813
15814         /* get current state of player */
15815         previous_state = MMPLAYER_CURRENT_STATE(player);
15816         debug_log("previous state(%d)", previous_state);
15817
15818
15819         /* get src pad of decoder and block it */
15820         src_pad_dec = gst_element_get_static_pad (GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
15821         if (!src_pad_dec)
15822         {
15823                 debug_error("failed to get src pad from decode in mainbin");
15824                 return MM_ERROR_PLAYER_INTERNAL;
15825         }
15826
15827         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
15828         {
15829                 debug_warning("trying to block pad(video)");
15830                 if (!gst_pad_set_blocked (src_pad_dec, TRUE))
15831                 {
15832                         debug_error("failed to set block pad(video)");
15833                         return MM_ERROR_PLAYER_INTERNAL;
15834                 }
15835                 debug_warning("pad is blocked(video)");
15836         }
15837         else
15838         {
15839                 /* no data flows, so no need to do pad_block */
15840                 if (player->doing_seek) {
15841                         debug_warning("not completed seek(%d), do nothing", player->doing_seek);
15842                 }
15843                 debug_log("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
15844         }
15845
15846         /* remove pad */
15847         if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
15848                 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin))))
15849         {
15850                 debug_error("failed to remove previous ghost_pad for videobin");
15851                 return MM_ERROR_PLAYER_INTERNAL;
15852         }
15853
15854         /* change state of videobin to NULL */
15855         debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
15856         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
15857         if (ret != GST_STATE_CHANGE_SUCCESS)
15858         {
15859                 debug_error("failed to change state of videobin to NULL");
15860                 return MM_ERROR_PLAYER_INTERNAL;
15861         }
15862
15863         /* unlink between decoder and videobin and remove previous videosink from videobin */
15864         GST_ELEMENT_UNLINK(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst),GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
15865         if ( !gst_bin_remove (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst)) )
15866         {
15867                 debug_error("failed to remove former videosink from videobin");
15868                 return MM_ERROR_PLAYER_INTERNAL;
15869         }
15870
15871         __mmplayer_del_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
15872
15873         /* create a new videosink and add it to videobin */
15874         player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, videosink_element);
15875         gst_bin_add (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
15876         __mmplayer_add_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
15877         g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
15878
15879         /* save attributes */
15880         if (player->attrs)
15881         {
15882                 /* set a new display surface type */
15883                 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
15884                 /* set a new diplay overlay */
15885                 switch (surface_type)
15886                 {
15887                         case MM_DISPLAY_SURFACE_X:
15888                                 debug_log("save attributes related to display surface to X : xid = %d", *(int*)display_overlay);
15889                                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
15890                                 break;
15891                         case MM_DISPLAY_SURFACE_EVAS:
15892                                 debug_log("save attributes related to display surface to EVAS : evas image object = %x", display_overlay);
15893                                 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
15894                                 break;
15895                         default:
15896                                 debug_error("invalid type(%d) for changing display surface",surface_type);
15897                                 MMPLAYER_FLEAVE();
15898                                 return MM_ERROR_INVALID_ARGUMENT;
15899                 }
15900                 if ( mmf_attrs_commit ( player->attrs ) )
15901                 {
15902                         debug_error("failed to commit");
15903                         MMPLAYER_FLEAVE();
15904                         return MM_ERROR_PLAYER_INTERNAL;
15905                 }
15906         }
15907         else
15908         {
15909                 debug_error("player->attrs is null, failed to save attributes");
15910                 MMPLAYER_FLEAVE();
15911                 return MM_ERROR_PLAYER_INTERNAL;
15912         }
15913
15914         /* update video param */
15915         if ( MM_ERROR_NONE != _mmplayer_update_video_param( player ) )
15916         {
15917                 debug_error("failed to update video param");
15918                 return MM_ERROR_PLAYER_INTERNAL;
15919         }
15920
15921         /* change state of videobin to READY */
15922         debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
15923         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
15924         if (ret != GST_STATE_CHANGE_SUCCESS)
15925         {
15926                 debug_error("failed to change state of videobin to READY");
15927                 return MM_ERROR_PLAYER_INTERNAL;
15928         }
15929
15930         /* change ghostpad */
15931         sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
15932         if ( !sink_pad_videosink )
15933         {
15934                 debug_error("failed to get sink pad from videosink element");
15935                 return MM_ERROR_PLAYER_INTERNAL;
15936         }
15937         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
15938         if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE))
15939         {
15940                 debug_error("failed to set active to ghost_pad");
15941                 return MM_ERROR_PLAYER_INTERNAL;
15942         }
15943         if ( FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
15944         {
15945                 debug_error("failed to change ghostpad for videobin");
15946                 return MM_ERROR_PLAYER_INTERNAL;
15947         }
15948         gst_object_unref(sink_pad_videosink);
15949
15950         /* link decoder with videobin */
15951         sink_pad_videobin = gst_element_get_static_pad( GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
15952         if ( !sink_pad_videobin )
15953         {
15954                 debug_error("failed to get sink pad from videobin");
15955                 return MM_ERROR_PLAYER_INTERNAL;
15956         }
15957         if ( GST_PAD_LINK_OK != GST_PAD_LINK(src_pad_dec, sink_pad_videobin) )
15958         {
15959                 debug_error("failed to link");
15960                 return MM_ERROR_PLAYER_INTERNAL;
15961         }
15962         gst_object_unref(sink_pad_videobin);
15963
15964         /* clock setting for a new videosink plugin */
15965         /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
15966                         so we set it from audiosink plugin or pipeline(system clock) */
15967         if (!is_audiobin_created)
15968         {
15969                 debug_warning("audiobin is not created, get clock from pipeline..");
15970                 clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
15971         }
15972         else
15973         {
15974                 clock = GST_ELEMENT_CLOCK (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
15975         }
15976         if (clock)
15977         {
15978                 GstClockTime now;
15979                 GstClockTime base_time;
15980                 debug_log("set the clock to videosink");
15981                 gst_element_set_clock (GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
15982                 clock = GST_ELEMENT_CLOCK (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
15983                 if (clock)
15984                 {
15985                         debug_log("got clock of videosink");
15986                         now = gst_clock_get_time ( clock );
15987                         base_time = GST_ELEMENT_CAST (player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
15988                         debug_log ("at time %" GST_TIME_FORMAT ", base %"
15989                                         GST_TIME_FORMAT, GST_TIME_ARGS (now), GST_TIME_ARGS (base_time));
15990                 }
15991                 else
15992                 {
15993                         debug_error("failed to get clock of videosink after setting clock");
15994                         return MM_ERROR_PLAYER_INTERNAL;
15995                 }
15996         }
15997         else
15998         {
15999                 debug_warning("failed to get clock, maybe it is the time before first playing");
16000         }
16001
16002         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
16003         {
16004                 /* change state of videobin to PAUSED */
16005                 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
16006                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
16007                 if (ret != GST_STATE_CHANGE_FAILURE)
16008                 {
16009                         debug_warning("change state of videobin to PLAYING, ret(%d)", ret);
16010                 }
16011                 else
16012                 {
16013                         debug_error("failed to change state of videobin to PLAYING");
16014                         return MM_ERROR_PLAYER_INTERNAL;
16015                 }
16016
16017                 /* release blocked and unref src pad of video decoder */
16018                 if (!gst_pad_set_blocked (src_pad_dec, FALSE))
16019                 {
16020                         debug_error("failed to set pad blocked FALSE(video)");
16021                         return MM_ERROR_PLAYER_INTERNAL;
16022                 }
16023                 debug_warning("pad is unblocked(video)");
16024         }
16025         else
16026         {
16027                 if (player->doing_seek) {
16028                         debug_warning("not completed seek(%d)", player->doing_seek);
16029                 }
16030                 /* change state of videobin to PAUSED */
16031                 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
16032                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
16033                 if (ret != GST_STATE_CHANGE_FAILURE)
16034                 {
16035                         debug_warning("change state of videobin to PAUSED, ret(%d)", ret);
16036                 }
16037                 else
16038                 {
16039                         debug_error("failed to change state of videobin to PLAYING");
16040                         return MM_ERROR_PLAYER_INTERNAL;
16041                 }
16042
16043                 /* already skipped pad block */
16044                 debug_log("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
16045         }
16046
16047         /* do get/set position for new videosink plugin */
16048         {
16049                 unsigned long position = 0;
16050                 gint64 pos_msec = 0;
16051
16052                 debug_log("do get/set position for new videosink plugin");
16053                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
16054                 {
16055                         debug_error("failed to get position");
16056                         return MM_ERROR_PLAYER_INTERNAL;
16057                 }
16058 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
16059                 /* accurate seek */
16060                 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE ))
16061                 {
16062                         debug_error("failed to set position");
16063                         return MM_ERROR_PLAYER_INTERNAL;
16064                 }
16065 #else
16066                 /* key unit seek */
16067                 pos_msec = position * G_GINT64_CONSTANT(1000000);
16068                 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
16069                                 GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT ),
16070                                                         GST_SEEK_TYPE_SET, pos_msec,
16071                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
16072                 if ( !ret  )
16073                 {
16074                         debug_error("failed to set position");
16075                         return MM_ERROR_PLAYER_INTERNAL;
16076                 }
16077 #endif
16078         }
16079
16080         if (src_pad_dec)
16081         {
16082                 gst_object_unref (src_pad_dec);
16083         }
16084         debug_log("success to change sink");
16085
16086         MMPLAYER_FLEAVE();
16087
16088         return MM_ERROR_NONE;
16089 }
16090
16091 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
16092 {
16093         MMPlayerGstElement* mainbin = NULL;
16094         MMPlayerGstElement* textbin = NULL;
16095         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
16096         GstState current_state = GST_STATE_VOID_PENDING;
16097         GstState element_state = GST_STATE_VOID_PENDING;
16098         GstState element_pending_state = GST_STATE_VOID_PENDING;
16099         gint64 time = 0;
16100         GstFormat format = GST_FORMAT_TIME;
16101         GstEvent *event = NULL;
16102         int result = MM_ERROR_NONE;
16103
16104         GstClock *curr_clock = NULL;
16105         GstClockTime base_time, start_time, curr_time;
16106
16107
16108         MMPLAYER_FENTER();
16109
16110         /* check player handle */
16111         return_val_if_fail ( player && player->pipeline , MM_ERROR_PLAYER_NOT_INITIALIZED);
16112
16113         if (!(player->pipeline->mainbin) || !(player->pipeline->textbin))
16114         {
16115                 debug_error("Pipeline is not in proper state\n");
16116                 result = MM_ERROR_PLAYER_NOT_INITIALIZED;
16117                 goto EXIT;
16118         }
16119
16120         mainbin = player->pipeline->mainbin;
16121         textbin = player->pipeline->textbin;
16122
16123         current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
16124
16125         // sync clock with current pipeline
16126         curr_clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
16127         curr_time = gst_clock_get_time (curr_clock);
16128
16129         base_time = gst_element_get_base_time (GST_ELEMENT_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
16130         start_time = gst_element_get_start_time (GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
16131
16132         debug_log ("base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
16133                 GST_TIME_ARGS (base_time), GST_TIME_ARGS (start_time), GST_TIME_ARGS (curr_time));
16134
16135         if (current_state > GST_STATE_READY)
16136         {
16137                 // sync state with current pipeline
16138                 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
16139                 gst_element_set_state(mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, GST_STATE_PAUSED); // Naveen : enable if required only
16140                 gst_element_set_state(mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst, GST_STATE_PAUSED);
16141                 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
16142
16143                 ret = gst_element_get_state (mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
16144                 if ( GST_STATE_CHANGE_FAILURE == ret )
16145                 {
16146                         debug_error("fail to state change.\n");
16147                 }
16148         }
16149
16150         gst_element_set_base_time (textbin[MMPLAYER_T_BIN].gst, base_time);
16151         gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
16152
16153         if (curr_clock)
16154         {
16155                 gst_element_set_clock (textbin[MMPLAYER_T_BIN].gst, curr_clock);
16156                 gst_object_unref (curr_clock);
16157         }
16158
16159         // seek to current position
16160         if (!gst_element_query_position (mainbin[MMPLAYER_M_PIPE].gst, &format, &time))
16161         {
16162                 result = MM_ERROR_PLAYER_INVALID_STATE;
16163                 debug_error("gst_element_query_position failed, invalid state\n");
16164                 goto EXIT;
16165         }
16166
16167         debug_log("seek time = %lld\n", time);
16168
16169         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);
16170         if (event)
16171         {
16172                 __gst_send_event_to_sink(player, event);
16173         }
16174         else
16175         {
16176                 result = MM_ERROR_PLAYER_INTERNAL;
16177                 debug_error("gst_event_new_seek failed\n");
16178                 goto EXIT;
16179         }
16180
16181         // sync state with current pipeline
16182         gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
16183         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst);
16184         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst);
16185         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
16186
16187 EXIT:
16188         return result;
16189 }
16190
16191 static int
16192 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
16193 {
16194         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
16195         GstState current_state = GST_STATE_VOID_PENDING;
16196
16197         MMHandleType attrs = 0;
16198         MMPlayerGstElement* mainbin = NULL;
16199         MMPlayerGstElement* textbin = NULL;
16200
16201         gchar* subtitle_uri = NULL;
16202         int result = MM_ERROR_NONE;
16203         const gchar *charset = NULL;
16204
16205         MMPLAYER_FENTER();
16206
16207         /* check player handle */
16208         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16209         return_val_if_fail( filepath, MM_ERROR_COMMON_INVALID_ARGUMENT );
16210
16211         if (!(player->pipeline) || !(player->pipeline->mainbin))
16212         {
16213                 result = MM_ERROR_PLAYER_INVALID_STATE;
16214                 debug_error("Pipeline is not in proper state\n");
16215                 goto EXIT;
16216         }
16217
16218         mainbin = player->pipeline->mainbin;
16219         textbin = player->pipeline->textbin;
16220
16221         current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
16222         if (current_state < GST_STATE_READY)
16223         {
16224                 result = MM_ERROR_PLAYER_INVALID_STATE;
16225                 debug_error("Pipeline is not in proper state\n");
16226                 goto EXIT;
16227         }
16228
16229         attrs = MMPLAYER_GET_ATTRS(player);
16230         if (!attrs)
16231         {
16232                 debug_error("cannot get content attribute\n");
16233                 result = MM_ERROR_PLAYER_INTERNAL;
16234                 goto EXIT;
16235         }
16236
16237         mm_attrs_get_string_by_name (attrs, "subtitle_uri", &subtitle_uri);
16238         if (!subtitle_uri || strlen(subtitle_uri) < 1)
16239         {
16240                 debug_error("subtitle uri is not proper filepath\n");
16241                 result = MM_ERROR_PLAYER_INVALID_URI;
16242                 goto EXIT;
16243         }
16244
16245         debug_log("old subtitle file path is [%s]\n", subtitle_uri);
16246         debug_log("new subtitle file path is [%s]\n", filepath);
16247
16248         if (!strcmp (filepath, subtitle_uri))
16249         {
16250                 debug_log("No need to swtich subtitle, as input filepath is same as current filepath\n");
16251                 goto EXIT;
16252         }
16253         else
16254         {
16255                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16256                 if (mmf_attrs_commit(player->attrs))
16257                 {
16258                         debug_error("failed to commit.\n");
16259                         goto EXIT;
16260                 }
16261         }
16262
16263         //gst_pad_set_blocked_async(src-srcpad, TRUE)
16264
16265         ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
16266         if (ret != GST_STATE_CHANGE_SUCCESS)
16267         {
16268                 debug_error("failed to change state of textbin to READY");
16269                 result = MM_ERROR_PLAYER_INTERNAL;
16270                 goto EXIT;
16271         }
16272
16273         ret = gst_element_set_state(mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, GST_STATE_READY);
16274         if (ret != GST_STATE_CHANGE_SUCCESS)
16275         {
16276                 debug_error("failed to change state of input-selector to READY");
16277                 result = MM_ERROR_PLAYER_INTERNAL;
16278                 goto EXIT;
16279         }
16280
16281         ret = gst_element_set_state(mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst, GST_STATE_READY);
16282         if (ret != GST_STATE_CHANGE_SUCCESS)
16283         {
16284                 debug_error("failed to change state of subparse to READY");
16285                 result = MM_ERROR_PLAYER_INTERNAL;
16286                 goto EXIT;
16287         }
16288
16289         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
16290         if (ret != GST_STATE_CHANGE_SUCCESS)
16291         {
16292                 debug_error("failed to change state of filesrc to READY");
16293                 result = MM_ERROR_PLAYER_INTERNAL;
16294                 goto EXIT;
16295         }
16296
16297         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
16298
16299         charset = util_get_charset(filepath);
16300         if (charset)
16301         {
16302                 debug_log ("detected charset is %s\n", charset );
16303                 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst), "subtitle-encoding", charset, NULL);
16304         }
16305
16306         result = _mmplayer_sync_subtitle_pipeline(player);
16307
16308 EXIT:
16309         MMPLAYER_FLEAVE();
16310         return result;
16311 }
16312
16313 /* API to switch between external subtitles */
16314 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
16315 {
16316         int result = MM_ERROR_NONE;
16317         mm_player_t* player = (mm_player_t*)hplayer;
16318
16319         MMPLAYER_FENTER();
16320
16321         /* check player handle */
16322         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16323
16324         if (!player->pipeline)  // IDLE state
16325         {
16326                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16327                 if (mmf_attrs_commit(player->attrs))
16328                 {
16329                         debug_error("failed to commit.\n");
16330                         result= MM_ERROR_PLAYER_INTERNAL;
16331                 }
16332         }
16333         else    // curr state <> IDLE (READY, PAUSE, PLAYING..)
16334         {
16335                 if ( filepath == NULL )
16336                         return MM_ERROR_COMMON_INVALID_ARGUMENT;
16337
16338                 if (!__mmplayer_check_subtitle(player))
16339                 {
16340                         mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16341                         if (mmf_attrs_commit(player->attrs))
16342                         {
16343                                 debug_error("failed to commit.\n");
16344                                 result = MM_ERROR_PLAYER_INTERNAL;
16345                         }
16346
16347                         if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
16348                                 debug_error("fail to create subtitle src\n");
16349
16350                         result = _mmplayer_sync_subtitle_pipeline(player);
16351                 }
16352                 else
16353                 {
16354                         result = __mmplayer_change_external_subtitle_language(player, filepath);
16355                 }
16356         }
16357
16358         MMPLAYER_FLEAVE();
16359         return result;
16360 }
16361
16362 static int
16363 __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index)
16364 {
16365         int result = MM_ERROR_NONE;
16366         gchar* change_pad_name = NULL;
16367         GstPad* sinkpad = NULL;
16368         MMPlayerGstElement* mainbin = NULL;
16369         enum MainElementID elemId = MMPLAYER_M_NUM;
16370         GstCaps* caps = NULL;
16371         gint total_track_num = 0;
16372
16373         MMPLAYER_FENTER();
16374
16375         return_val_if_fail (player && player->pipeline && player->pipeline->mainbin,
16376                                                                                                         MM_ERROR_PLAYER_NOT_INITIALIZED);
16377
16378         debug_log ("Change Track(%d) to %d\n", type, index);
16379
16380         mainbin = player->pipeline->mainbin;
16381
16382         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
16383         {
16384                 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
16385         }
16386         else if (type == MM_PLAYER_TRACK_TYPE_TEXT)
16387         {
16388                 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
16389         }
16390         else
16391         {
16392                 debug_error ("Track Type Error\n");
16393                 goto EXIT;
16394         }
16395
16396         if (mainbin[elemId].gst == NULL)
16397         {
16398                 result = MM_ERROR_PLAYER_NO_OP;
16399                 debug_log ("Req track doesn't exist\n");
16400                 goto EXIT;
16401         }
16402
16403         total_track_num = player->selector[type].total_track_num;
16404         if (total_track_num <= 0)
16405         {
16406                 result = MM_ERROR_PLAYER_NO_OP;
16407                 debug_log ("Language list is not available \n");
16408                 goto EXIT;
16409         }
16410
16411         if ((index < 0) || (index >= total_track_num))
16412         {
16413                 result = MM_ERROR_INVALID_ARGUMENT;
16414                 debug_log ("Not a proper index : %d \n", index);
16415                 goto EXIT;
16416         }
16417
16418         /*To get the new pad from the selector*/
16419         change_pad_name = g_strdup_printf ("sink%d", index);
16420         if (change_pad_name == NULL)
16421         {
16422                 result = MM_ERROR_PLAYER_INTERNAL;
16423                 debug_log ("Pad does not exists\n");
16424                 goto EXIT;
16425         }
16426
16427         debug_log ("new active pad name: %s\n", change_pad_name);
16428
16429         sinkpad = gst_element_get_static_pad (mainbin[elemId].gst, change_pad_name);
16430         if (sinkpad == NULL)
16431         {
16432                 result = MM_ERROR_PLAYER_INTERNAL;
16433                 goto EXIT;
16434         }
16435
16436         debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
16437         g_object_set (mainbin[elemId].gst, "active-pad", sinkpad, NULL);
16438
16439         caps = GST_PAD_CAPS(sinkpad);
16440         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
16441
16442         if (sinkpad)
16443                 gst_object_unref (sinkpad);
16444
16445         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
16446         {
16447                 __mmplayer_set_audio_attrs (player, caps);
16448         }
16449
16450 EXIT:
16451
16452         MMPLAYER_FREEIF(change_pad_name);
16453         return result;
16454 }
16455
16456 int _mmplayer_change_track_language (MMHandleType hplayer, MMPlayerTrackType type, int index)
16457 {
16458         int result = MM_ERROR_NONE;
16459         mm_player_t* player = NULL;
16460         MMPlayerGstElement* mainbin = NULL;
16461
16462         gint current_active_index = 0;
16463
16464         GstState current_state = GST_STATE_VOID_PENDING;
16465         GstEvent* event = NULL;
16466         GstFormat format = GST_FORMAT_TIME;
16467         gint64 time = 0;
16468
16469         MMPLAYER_FENTER();
16470
16471         player = (mm_player_t*)hplayer;
16472         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
16473
16474         if (!player->pipeline)
16475         {
16476                 debug_error ("Track %d pre setting -> %d\n", type, index);
16477
16478                 player->selector[type].active_pad_index = index;
16479                 goto EXIT;
16480         }
16481
16482         mainbin = player->pipeline->mainbin;
16483
16484         current_active_index = player->selector[type].active_pad_index;
16485
16486         /*If index is same as running index no need to change the pad*/
16487         if (current_active_index == index)
16488         {
16489                 goto EXIT;
16490         }
16491
16492         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, &format, &time))
16493         {
16494                 result = MM_ERROR_PLAYER_INVALID_STATE;
16495                 goto EXIT;
16496         }
16497
16498         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
16499         if (current_state < GST_STATE_PAUSED)
16500         {
16501                 result = MM_ERROR_PLAYER_INVALID_STATE;
16502                 debug_warning ("Pipeline not in porper state\n");
16503                 goto EXIT;
16504         }
16505
16506         result = __mmplayer_change_selector_pad(player, type, index);
16507         if (result != MM_ERROR_NONE)
16508         {
16509                 debug_error ("change selector pad error\n");
16510                 goto EXIT;
16511         }
16512
16513         player->selector[type].active_pad_index = index;
16514
16515         if (current_state == GST_STATE_PLAYING)
16516         {
16517                 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);
16518                 if (event)
16519                 {
16520                         __gst_send_event_to_sink (player, event);
16521                 }
16522                 else
16523                 {
16524                         result = MM_ERROR_PLAYER_INTERNAL;
16525                         goto EXIT;
16526                 }
16527         }
16528
16529 EXIT:
16530         return result;
16531 }
16532
16533 const gchar *
16534 __get_state_name ( int state )
16535 {
16536         switch ( state )
16537         {
16538                 case MM_PLAYER_STATE_NULL:
16539                         return "NULL";
16540                 case MM_PLAYER_STATE_READY:
16541                         return "READY";
16542                 case MM_PLAYER_STATE_PAUSED:
16543                         return "PAUSED";
16544                 case MM_PLAYER_STATE_PLAYING:
16545                         return "PLAYING";
16546                 case MM_PLAYER_STATE_NONE:
16547                         return "NONE";
16548                 default:
16549                         return "INVAID";
16550         }
16551 }
16552
16553 gboolean
16554 __is_rtsp_streaming ( mm_player_t* player )
16555 {
16556         return_val_if_fail ( player, FALSE );
16557
16558         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP ) ? TRUE : FALSE;
16559 }
16560
16561 gboolean
16562 __is_wfd_streaming ( mm_player_t* player )
16563 {
16564   return_val_if_fail ( player, FALSE );
16565
16566   return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_WFD ) ? TRUE : FALSE;
16567 }
16568
16569 static gboolean
16570 __is_http_streaming ( mm_player_t* player )
16571 {
16572         return_val_if_fail ( player, FALSE );
16573
16574         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP ) ? TRUE : FALSE;
16575 }
16576
16577 static gboolean
16578 __is_streaming ( mm_player_t* player )
16579 {
16580         return_val_if_fail ( player, FALSE );
16581
16582   return ( __is_rtsp_streaming ( player ) || __is_wfd_streaming ( player ) || __is_http_streaming ( player )
16583           || __is_http_live_streaming ( player ) || __is_dash_streaming ( player ) || __is_smooth_streaming(player) ) ? TRUE : FALSE;
16584 }
16585
16586 gboolean
16587 __is_live_streaming ( mm_player_t* player )
16588 {
16589         return_val_if_fail ( player, FALSE );
16590
16591         return ( __is_rtsp_streaming ( player ) && player->streaming_type == STREAMING_SERVICE_LIVE ) ? TRUE : FALSE;
16592 }
16593
16594 static gboolean
16595 __is_http_live_streaming( mm_player_t* player )
16596 {
16597         return_val_if_fail( player, FALSE );
16598
16599         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS ) ? TRUE : FALSE;
16600 }
16601
16602 static gboolean
16603 __is_dash_streaming ( mm_player_t* player )
16604 {
16605         return_val_if_fail ( player, FALSE );
16606
16607         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH ) ? TRUE : FALSE;
16608 }
16609
16610 static gboolean
16611 __is_smooth_streaming ( mm_player_t* player )
16612 {
16613         return_val_if_fail ( player, FALSE );
16614
16615         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_SS ) ? TRUE : FALSE;
16616 }
16617
16618
16619 static gboolean
16620 __is_http_progressive_down(mm_player_t* player)
16621 {
16622         return_val_if_fail( player, FALSE );
16623
16624         return ((player->pd_mode) ? TRUE:FALSE);
16625 }
16626
16627 gboolean
16628 __has_suffix(mm_player_t* player, const gchar* suffix)
16629 {
16630         return_val_if_fail( player, FALSE );
16631         return_val_if_fail( suffix, FALSE );
16632
16633         gboolean ret = FALSE;
16634         gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
16635         gchar* t_suffix = g_ascii_strdown(suffix, -1);
16636
16637         if ( g_str_has_suffix(player->profile.uri, suffix) )
16638         {
16639                 ret = TRUE;
16640         }
16641
16642         MMPLAYER_FREEIF(t_url);
16643         MMPLAYER_FREEIF(t_suffix);
16644
16645         return ret;
16646 }
16647
16648 int
16649 _mmplayer_set_display_zoom(MMHandleType hplayer, float level, int x, int y)
16650 {
16651         mm_player_t* player = (mm_player_t*) hplayer;
16652
16653         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16654
16655         MMPLAYER_VIDEO_SINK_CHECK(player);
16656
16657         debug_log("setting display zoom level = %f, offset = %d, %d", level, x, y);
16658
16659         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", level, "zoom-pos-x", x, "zoom-pos-y", y, NULL);
16660
16661         return MM_ERROR_NONE;
16662 }
16663 int
16664 _mmplayer_get_display_zoom(MMHandleType hplayer, float *level, int *x, int *y)
16665 {
16666
16667         mm_player_t* player = (mm_player_t*) hplayer;
16668         float _level = 0.0;
16669         int _x = 0;
16670         int _y = 0;
16671
16672         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16673
16674         MMPLAYER_VIDEO_SINK_CHECK(player);
16675
16676         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", &_level, "zoom-pos-x", &_x, "zoom-pos-y", &_y, NULL);
16677
16678         debug_log("display zoom level = %f, start off x = %d, y = %d", _level, _x, _y);
16679
16680         *level = _level;
16681         *x = _x;
16682         *y = _y;
16683
16684         return MM_ERROR_NONE;
16685 }
16686
16687 int
16688 _mmplayer_get_video_rotate_angle(MMHandleType hplayer, int *angle)
16689 {
16690         mm_player_t* player = (mm_player_t*) hplayer;
16691         int org_angle = 0;
16692
16693         MMPLAYER_FENTER();
16694
16695         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16696         return_val_if_fail ( angle, MM_ERROR_COMMON_INVALID_ARGUMENT );
16697
16698         if (player->v_stream_caps)
16699         {
16700                 GstStructure *str = NULL;
16701
16702                 str = gst_caps_get_structure (player->v_stream_caps, 0);
16703                 if ( !gst_structure_get_int (str, "orientation", &org_angle))
16704                 {
16705                         debug_log ("missing 'orientation' field in video caps");
16706                 }
16707         }
16708
16709         debug_log("orientation: %d", org_angle);
16710         *angle = org_angle;
16711
16712         MMPLAYER_FLEAVE();
16713         return MM_ERROR_NONE;
16714 }
16715
16716 gboolean
16717 __mmplayer_is_streaming(mm_player_t* player)
16718 {
16719         gboolean result = FALSE;
16720
16721         MMPLAYER_FENTER();
16722
16723         return_val_if_fail (player, FALSE);
16724         result = __is_streaming (player) ;
16725
16726         MMPLAYER_FLEAVE();
16727         return result;
16728 }
16729
16730 static gboolean
16731 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
16732 {
16733         return_val_if_fail (player, FALSE);
16734         return_val_if_fail (element, FALSE);
16735
16736         gchar *factory_name = GST_PLUGIN_FEATURE_NAME (gst_element_get_factory(element));
16737         gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
16738         int len = PLAYER_INI_MAX_STRLEN*2;
16739
16740         int idx = 0;
16741
16742         for ( idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++ )
16743         {
16744                 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx]))
16745                 {
16746                         debug_log("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
16747                         mm_player_dump_t *dump_s;
16748                         dump_s = g_malloc (sizeof(mm_player_dump_t));
16749
16750                         if (dump_s == NULL)
16751                         {
16752                                 debug_error ("malloc fail");
16753                                 return FALSE;
16754                         }
16755
16756                         dump_s->dump_element_file = NULL;
16757                         dump_s->dump_pad = NULL;
16758                         dump_s->dump_pad = gst_element_get_static_pad (element, "sink");
16759
16760                         if (dump_s->dump_pad)
16761                         {
16762                                 memset (dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
16763                                 snprintf (dump_file_name, len, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
16764                                 dump_s->dump_element_file = fopen(dump_file_name,"w+");
16765                                 dump_s->probe_handle_id = gst_pad_add_buffer_probe (dump_s->dump_pad, G_CALLBACK(__mmplayer_dump_buffer_probe_cb), dump_s->dump_element_file);
16766                                 /* add list for removed buffer probe and close FILE */
16767                                 player->dump_list = g_list_append (player->dump_list, dump_s);
16768                                 debug_log ("%s sink pad added buffer probe for dump", factory_name);
16769                                 return TRUE;
16770                         }
16771                         else
16772                         {
16773                                 g_free(dump_s);
16774                                 dump_s = NULL;
16775                                 debug_error ("failed to get %s sink pad added", factory_name);
16776                         }
16777
16778
16779                 }
16780         }
16781         return FALSE;
16782 }
16783
16784 static gboolean
16785 __mmplayer_dump_buffer_probe_cb(GstPad *pad, GstBuffer *buffer, gpointer u_data)
16786 {
16787         FILE *dump_data = (FILE *) u_data;
16788 //      int written = 0;
16789
16790         return_val_if_fail ( dump_data, FALSE );
16791
16792 //      debug_log ("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS( GST_BUFFER_TIMESTAMP(buffer)));
16793
16794         fwrite ( GST_BUFFER_DATA(buffer), 1, GST_BUFFER_SIZE(buffer), dump_data);
16795
16796         return TRUE;
16797 }
16798
16799 static void
16800 __mmplayer_release_dump_list (GList *dump_list)
16801 {
16802         if (dump_list)
16803         {
16804                 GList *d_list = dump_list;
16805                 for ( ;d_list ; d_list = g_list_next(d_list))
16806                 {
16807                         mm_player_dump_t *dump_s = d_list->data;
16808                         if (dump_s->dump_pad)
16809                         {
16810                                 if (dump_s->probe_handle_id)
16811                                 {
16812                                         gst_pad_remove_buffer_probe (dump_s->dump_pad, dump_s->probe_handle_id);
16813                                 }
16814
16815                         }
16816                         if (dump_s->dump_element_file)
16817                         {
16818                                 fclose(dump_s->dump_element_file);
16819                                 dump_s->dump_element_file = NULL;
16820                         }
16821                         MMPLAYER_FREEIF(dump_s);
16822                 }
16823                 g_list_free(dump_list);
16824                 dump_list = NULL;
16825         }
16826 }
16827
16828 static int
16829 __mmplayer_ignore_current_external_display_mode(mm_player_t* player)
16830 {
16831         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16832         MMPLAYER_VIDEO_SINK_CHECK(player);
16833
16834         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "keep-external-fullscreen-prev", TRUE, NULL);
16835         debug_log("set keep-external-fullscreen-prev property to TRUE");
16836
16837         return MM_ERROR_NONE;
16838 }
16839
16840 int
16841 _mmplayer_enable_media_packet_video_stream(MMHandleType hplayer, bool enable)
16842 {
16843         mm_player_t* player = (mm_player_t*) hplayer;
16844
16845         MMPLAYER_FENTER();
16846
16847         return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
16848         return_val_if_fail (enable == TRUE || enable == FALSE, MM_ERROR_INVALID_ARGUMENT);
16849
16850         player->set_mode.media_packet_video_stream = enable;
16851
16852         MMPLAYER_FLEAVE();
16853
16854         return MM_ERROR_NONE;
16855 }