support video texture(MM_DISPLAY_SURFACE_X_EXT), remove codes related to non-standard...
[platform/core/multimedia/libmm-player.git] / src / mm_player_priv.c
1 /*
2  * libmm-player
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 /*===========================================================================================
23 |                                                                                                                                                                                       |
24 |  INCLUDE FILES                                                                                                                                                        |
25 |                                                                                                                                                                                       |
26 ========================================================================================== */
27 #include <glib.h>
28 #include <gst/gst.h>
29 #include <gst/app/gstappsrc.h>
30 #include <gst/interfaces/xoverlay.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <sys/time.h>
34 #include <stdlib.h>
35
36 #include <mm_error.h>
37 #include <mm_attrs.h>
38 #include <mm_attrs_private.h>
39 #include <mm_debug.h>
40
41 #include "mm_player_priv.h"
42 #include "mm_player_ini.h"
43 #include "mm_player_attrs.h"
44 #include "mm_player_capture.h"
45
46 /*===========================================================================================
47 |                                                                                                                                                                                       |
48 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
49 |                                                                                                                                                                                       |
50 ========================================================================================== */
51
52 /*---------------------------------------------------------------------------
53 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
54 ---------------------------------------------------------------------------*/
55
56 /*---------------------------------------------------------------------------
57 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
58 ---------------------------------------------------------------------------*/
59
60 /*---------------------------------------------------------------------------
61 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
62 ---------------------------------------------------------------------------*/
63
64 /*---------------------------------------------------------------------------
65 |    LOCAL #defines:                                                                                                            |
66 ---------------------------------------------------------------------------*/
67 #define TRICK_PLAY_MUTE_THRESHOLD_MAX   2.0
68 #define TRICK_PLAY_MUTE_THRESHOLD_MIN   0.0
69
70 #define MM_VOLUME_FACTOR_DEFAULT                1.0
71 #define MM_VOLUME_FACTOR_MIN                            0
72 #define MM_VOLUME_FACTOR_MAX                            1.0
73
74 #define MM_PLAYER_FADEOUT_TIME_DEFAULT  700000 // 700 msec
75
76 #define MM_PLAYER_MPEG_VNAME                            "mpegversion"
77 #define MM_PLAYER_DIVX_VNAME                            "divxversion"
78 #define MM_PLAYER_WMV_VNAME                             "wmvversion"
79 #define MM_PLAYER_WMA_VNAME                             "wmaversion"
80
81 #define DEFAULT_PLAYBACK_RATE                   1.0
82
83 #define GST_QUEUE_DEFAULT_TIME                  2
84 #define GST_QUEUE_HLS_TIME                              8
85
86 /* video capture callback*/
87 gulong ahs_appsrc_cb_probe_id = 0;
88
89 #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) )
90 #define MMPLAYER_PLAY_SUBTITLE(player) ((player)->play_subtitle)
91
92 #define LAZY_PAUSE_TIMEOUT_MSEC 700     
93
94 /*---------------------------------------------------------------------------
95 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
96 ---------------------------------------------------------------------------*/
97
98 /*---------------------------------------------------------------------------
99 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
100 ---------------------------------------------------------------------------*/
101
102 /*---------------------------------------------------------------------------
103 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
104 ---------------------------------------------------------------------------*/
105
106 /*---------------------------------------------------------------------------
107 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
108 ---------------------------------------------------------------------------*/
109
110 /*---------------------------------------------------------------------------
111 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
112 ---------------------------------------------------------------------------*/
113 static gboolean __mmplayer_set_state(mm_player_t* player, int state);
114 static int              __mmplayer_get_state(mm_player_t* player);
115 static int              __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
116 static int              __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
117 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player);
118 static int              __mmplayer_gst_create_subtitle_pipeline(mm_player_t* player);
119 static int              __mmplayer_gst_create_pipeline(mm_player_t* player);
120 static int              __mmplayer_gst_destroy_pipeline(mm_player_t* player);
121 static int              __mmplayer_gst_element_link_bucket(GList* element_bucket);
122
123 static gboolean __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data);
124 static void     __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gboolean last, gpointer data);
125
126 static void     __mmplayer_typefind_have_type(  GstElement *tf, guint probability, GstCaps *caps, gpointer data);
127 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
128 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
129 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
130 static gboolean __mmplayer_is_amr_type (gchar *str_caps);
131 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
132
133 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
134 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
135 static void     __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
136
137 static void             __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data);
138 static void             __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
139 static gboolean __mmplayer_update_stream_service_type( mm_player_t* player );
140 static gboolean __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
141
142
143 static void     __mmplayer_init_factories(mm_player_t* player);
144 static void     __mmplayer_release_factories(mm_player_t* player);
145 static void     __mmplayer_release_misc(mm_player_t* player);
146 static gboolean __mmplayer_gstreamer_init(void);
147
148 static int              __mmplayer_gst_set_state (mm_player_t* player, GstElement * pipeline,  GstState state, gboolean async, gint timeout );
149 gboolean __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param);
150 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
151 int             __mmplayer_switch_audio_sink (mm_player_t* player);
152 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
153 static int              __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
154 static gboolean __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data);
155
156 static gboolean __mmplayer_dump_pipeline_state( mm_player_t* player );
157 static gboolean __mmplayer_check_subtitle( mm_player_t* player );
158 static gboolean __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error );
159 static gboolean __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message );
160 static void             __mmplayer_post_delayed_eos( mm_player_t* player, int delay_in_ms );
161 static void     __mmplayer_cancel_delayed_eos( mm_player_t* player );
162 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
163 static gboolean __mmplayer_link_decoder( mm_player_t* player,GstPad *srcpad);
164 static gboolean __mmplayer_link_sink( mm_player_t* player,GstPad *srcpad);
165 static int      __mmplayer_post_missed_plugin(mm_player_t* player);
166 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, gchar* mime);
167 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
168 static void     __mmplayer_add_sink( mm_player_t* player, GstElement* sink);
169 static void     __mmplayer_del_sink( mm_player_t* player, GstElement* sink);
170 static void             __mmplayer_release_signal_connection(mm_player_t* player);
171 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force);
172 static gpointer __mmplayer_repeat_thread(gpointer data);
173 int _mmplayer_get_track_count(MMHandleType hplayer,  MMPlayerTrackType track_type, int *count);
174
175 static int              __gst_realize(mm_player_t* player);
176 static int              __gst_unrealize(mm_player_t* player);
177 static int              __gst_start(mm_player_t* player);
178 static int              __gst_stop(mm_player_t* player);
179 int             __gst_pause(mm_player_t* player, gboolean async);
180 int             __gst_resume(mm_player_t* player, gboolean async);
181 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
182                                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
183                                         gint64 cur, GstSeekType stop_type, gint64 stop );
184 static int __gst_pending_seek ( mm_player_t* player );
185
186 static int              __gst_set_position(mm_player_t* player, int format, unsigned long position);
187 static int              __gst_get_position(mm_player_t* player, int format, unsigned long *position);
188 static int              __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
189 static int              __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
190 static int              __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
191 static void     __gst_set_async_state_change(mm_player_t* player, gboolean async);
192
193 static gint     __gst_handle_core_error( mm_player_t* player, int code );
194 static gint     __gst_handle_library_error( mm_player_t* player, int code );
195 static gint     __gst_handle_resource_error( mm_player_t* player, int code );
196 static gint     __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message );
197 static gint             __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error);
198 static gboolean __gst_send_event_to_sink( mm_player_t* player, GstEvent* event );
199
200 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
201 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
202
203 /*fadeout */
204 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
205 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
206
207 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
208 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
209
210 /* util */
211 const gchar * __get_state_name ( int state );
212 static gboolean __is_streaming( mm_player_t* player );
213 static gboolean __is_rtsp_streaming( mm_player_t* player );
214 static gboolean __is_live_streaming ( mm_player_t* player );
215 static gboolean __is_http_streaming( mm_player_t* player );
216 static gboolean __is_http_live_streaming( mm_player_t* player );
217 static gboolean __is_http_progressive_down(mm_player_t* player);
218
219 static gboolean __mmplayer_warm_up_video_codec( mm_player_t* player,  GstElementFactory *factory);
220 static GstBusSyncReply __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data);
221
222 /*===========================================================================================
223 |                                                                                                                                                                                       |
224 |  FUNCTION DEFINITIONS                                                                                                                                         |
225 |                                                                                                                                                                                       |
226 ========================================================================================== */
227
228 /* implementing player FSM */
229 /* FIXIT : We need to handle state transition also at here since start api is no more sync */
230 static int
231 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
232 {
233         MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
234         MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
235         MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
236         MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
237
238         debug_fenter();
239
240         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
241
242         //debug_log("incomming command : %d \n", command );
243
244         current_state = MMPLAYER_CURRENT_STATE(player);
245         pending_state = MMPLAYER_PENDING_STATE(player);
246         target_state = MMPLAYER_TARGET_STATE(player);
247         prev_state = MMPLAYER_PREV_STATE(player);
248
249         MMPLAYER_PRINT_STATE(player);
250
251         switch( command )
252         {
253                 case MMPLAYER_COMMAND_CREATE:
254                 {
255                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
256                         
257                         if ( current_state == MM_PLAYER_STATE_NULL ||
258                                 current_state == MM_PLAYER_STATE_READY ||
259                                 current_state == MM_PLAYER_STATE_PAUSED ||
260                                 current_state == MM_PLAYER_STATE_PLAYING )
261                                 goto NO_OP;
262                 }
263                 break;
264
265                 case MMPLAYER_COMMAND_DESTROY:
266                 {
267                         /* destroy can called anytime */
268
269                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
270                 }
271                 break;
272
273                 case MMPLAYER_COMMAND_REALIZE:
274                 {
275                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
276
277                         if ( pending_state != MM_PLAYER_STATE_NONE )
278                         {
279                                 goto INVALID_STATE;
280                         }
281                         else
282                         {
283                                 /* need ready state to realize */
284                                 if ( current_state == MM_PLAYER_STATE_READY )
285                                         goto NO_OP;
286
287                                 if ( current_state != MM_PLAYER_STATE_NULL )
288                                         goto INVALID_STATE;
289                         }
290                 }
291                 break;
292
293                 case MMPLAYER_COMMAND_UNREALIZE:
294                 {
295                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
296
297                         if ( current_state == MM_PLAYER_STATE_NULL )
298                                 goto NO_OP;
299                 }
300                 break;
301
302                 case MMPLAYER_COMMAND_START:
303                 {
304                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
305
306                         if ( pending_state == MM_PLAYER_STATE_NONE )
307                         {
308                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
309                                         goto NO_OP;
310                                 else if ( current_state  != MM_PLAYER_STATE_READY &&
311                                         current_state != MM_PLAYER_STATE_PAUSED )
312                                         goto INVALID_STATE;
313                         }
314                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
315                         {
316                                 goto ALREADY_GOING;
317                         }
318                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
319                         {
320                                 debug_log("player is going to paused state, just change the pending state as playing");
321                         }
322                         else
323                         {
324                                 goto INVALID_STATE;
325                         }
326                 }
327                 break;
328
329                 case MMPLAYER_COMMAND_STOP:
330                 {
331                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
332
333                         if ( current_state == MM_PLAYER_STATE_READY )
334                                 goto NO_OP;
335                         
336                         /* need playing/paused state to stop */
337                         if ( current_state != MM_PLAYER_STATE_PLAYING &&
338                                  current_state != MM_PLAYER_STATE_PAUSED )
339                                 goto INVALID_STATE;
340                 }
341                 break;
342
343                 case MMPLAYER_COMMAND_PAUSE:
344                 {
345                         if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
346                                 goto NO_OP;
347
348                         if (player->doing_seek)
349                                 goto NOT_COMPLETED_SEEK;
350
351                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
352
353                         if ( pending_state == MM_PLAYER_STATE_NONE )
354                         {
355                                 if ( current_state == MM_PLAYER_STATE_PAUSED )
356                                         goto NO_OP;
357                                 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
358                                         goto INVALID_STATE;
359                         }
360                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
361                         {
362                                 goto ALREADY_GOING;
363                         }
364                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
365                         {
366                                 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
367                                         debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
368                                 } else {
369                                         goto INVALID_STATE;
370                                 }
371                         }
372                 }
373                 break;
374
375                 case MMPLAYER_COMMAND_RESUME:
376                 {
377                         if ( MMPLAYER_IS_LIVE_STREAMING(player) )
378                                 goto NO_OP;
379
380                         if (player->doing_seek)
381                                 goto NOT_COMPLETED_SEEK;
382
383                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
384
385                         if ( pending_state == MM_PLAYER_STATE_NONE )
386                         {
387                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
388                                         goto NO_OP;
389                                 else if (  current_state != MM_PLAYER_STATE_PAUSED )
390                                         goto INVALID_STATE;
391                         }
392                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
393                         {
394                                 goto ALREADY_GOING;
395                         }
396                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
397                         {
398                                 debug_log("player is going to paused state, just change the pending state as playing");
399                         }
400                         else
401                         {
402                                 goto INVALID_STATE;
403                         }
404                 }
405                 break;
406
407                 default:
408                 break;
409         }
410         player->cmd = command;
411
412         debug_fleave();
413         return MM_ERROR_NONE;
414
415 INVALID_STATE:
416         debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
417                 MMPLAYER_STATE_GET_NAME(current_state), command);
418         return MM_ERROR_PLAYER_INVALID_STATE;
419
420 NOT_COMPLETED_SEEK:
421         debug_warning("not completed seek");
422         return MM_ERROR_PLAYER_DOING_SEEK;
423
424 NO_OP:
425         debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
426         return MM_ERROR_PLAYER_NO_OP;
427
428 ALREADY_GOING:
429         debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
430         return MM_ERROR_PLAYER_NO_OP;
431 }
432
433 int
434 __mmplayer_gst_set_state (mm_player_t* player, GstElement * element,  GstState state, gboolean async, gint timeout) // @
435 {
436         GstState element_state = GST_STATE_VOID_PENDING;
437         GstState element_pending_state = GST_STATE_VOID_PENDING;
438         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
439
440         debug_fenter();
441         
442         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
443         return_val_if_fail ( element, MM_ERROR_INVALID_ARGUMENT );
444
445         debug_log("setting [%s] element state to : %d\n", GST_ELEMENT_NAME(element),  state);
446
447         /* set state */
448         ret = gst_element_set_state(element, state);
449
450         if ( ret == GST_STATE_CHANGE_FAILURE )
451         {
452                 debug_error("failed to set  [%s] state to [%d]\n", GST_ELEMENT_NAME(element), state);
453                 return MM_ERROR_PLAYER_INTERNAL;
454         }
455         
456         /* return here so state transition to be done in async mode */
457         if ( async )
458         {
459                 debug_log("async state transition. not waiting for state complete.\n");
460                 return MM_ERROR_NONE;
461         }
462
463         /* wait for state transition */
464         ret = gst_element_get_state( element, &element_state, &element_pending_state, timeout * GST_SECOND );
465
466         if ( ret == GST_STATE_CHANGE_FAILURE || ( state != element_state ) )
467         {
468                 debug_error("failed to change [%s] element state to [%s] within %d sec\n",
469                         GST_ELEMENT_NAME(element), 
470                         gst_element_state_get_name(state), timeout );
471                 
472                 debug_error(" [%s] state : %s   pending : %s \n", 
473                         GST_ELEMENT_NAME(element), 
474                         gst_element_state_get_name(element_state), 
475                         gst_element_state_get_name(element_pending_state) );
476
477                 return MM_ERROR_PLAYER_INTERNAL;
478         }
479
480         debug_log("[%s] element state has changed to %s \n",
481                 GST_ELEMENT_NAME(element), 
482                 gst_element_state_get_name(element_state));
483
484         debug_fleave();
485         
486         return MM_ERROR_NONE;
487 }
488
489
490 static void
491 __mmplayer_videostream_cb(GstElement *element, void *stream,
492 int width, int height, gpointer data) // @
493 {
494         mm_player_t* player = (mm_player_t*)data;
495         int length = 0;
496
497         return_if_fail ( player );
498
499         if (player->video_stream_cb )
500         {
501                 length = width * height * 4; // for rgb 32bit
502                 player->video_stream_cb(stream, length, player->video_stream_cb_user_param, width, height);
503         }
504 }
505
506 gboolean
507 _mmplayer_update_content_attrs(mm_player_t* player) // @
508 {
509         GstFormat fmt  = GST_FORMAT_TIME;
510         gint64 dur_nsec = 0;
511         GstStructure* p = NULL;
512         MMHandleType attrs = 0;
513         gint retry_count = 0;
514         gint retry_count_max = 10;
515         gchar *path = NULL;
516         struct stat sb;
517
518         return_val_if_fail ( player, FALSE );
519
520         if ( ! player->need_update_content_attrs )
521         {
522                 debug_log("content attributes are already updated");
523                 return TRUE;
524         }
525
526         /* get content attribute first */
527         attrs = MMPLAYER_GET_ATTRS(player);
528         if ( !attrs )
529         {
530                 debug_error("cannot get content attribute");
531                 return FALSE;
532         }
533
534         /* update duration
535          * NOTE : we need to wait for a while until is possible to get duration from pipeline
536          * as getting duration timing is depends on behavier of demuxers ( or etc ).
537          * we set timeout 100ms * 10 as initial value. fix it if needed.
538          */
539         if ( player->need_update_content_dur  )
540         {
541                 while ( retry_count <  retry_count_max)
542                 {
543                         if ( FALSE == gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
544                                 &fmt, &dur_nsec ) )
545                         {
546                                 /* retry if failed */
547                                 debug_warning("failed to get duraton. waiting 100ms and then retrying...");
548                                 usleep(100000);
549                                 retry_count++;
550                                 continue;
551                         }
552
553                         if ( dur_nsec == 0 && ( !MMPLAYER_IS_LIVE_STREAMING( player ) ) )
554                         {
555                                 /* retry if duration is zero in case of not live stream */
556                                 debug_warning("returned duration is zero. but it's not an live stream. retrying...");
557                                 usleep(100000);
558                                 retry_count++;
559                                 continue;
560                         }
561
562                         break;
563                 }
564
565                 player->duration = dur_nsec;
566                 debug_log("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
567
568                 /* try to get streaming service type */
569                 __mmplayer_update_stream_service_type( player );
570
571                 /* check duration is OK */
572                 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
573                 {
574                         /* FIXIT : find another way to get duration here. */
575                         debug_error("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
576                 }
577                 else
578                 {
579                         player->need_update_content_dur = FALSE;
580                 }
581
582                 /*update duration */
583                 mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
584         }
585         else
586         {
587                 debug_log("not ready to get duration or already updated");
588         }
589
590         /* update rate, channels */
591         if ( player->pipeline->audiobin &&
592                  player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
593         {
594                 GstCaps *caps_a = NULL;
595                 GstPad* pad = NULL;
596                 gint samplerate = 0, channels = 0;
597
598                 pad = gst_element_get_static_pad(
599                                 player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
600
601                 if ( pad )
602                 {
603                         caps_a = gst_pad_get_negotiated_caps( pad );
604
605                         if ( caps_a )
606                         {
607                                 p = gst_caps_get_structure (caps_a, 0);
608
609                                 mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
610                                 if ( ! samplerate ) // check if update already or not
611                                 {
612                                         gst_structure_get_int (p, "rate", &samplerate);
613                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
614
615                                         gst_structure_get_int (p, "channels", &channels);
616                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
617
618                                         debug_log("samplerate : %d      channels : %d", samplerate, channels);
619                                 }
620                                 gst_caps_unref( caps_a );
621                                 caps_a = NULL;
622                         }
623                         else
624                         {
625                                 debug_warning("not ready to get audio caps");
626                         }
627
628                         gst_object_unref( pad );
629                 }
630                 else
631                 {
632                         debug_warning("failed to get pad from audiosink");
633                 }
634         }
635
636         /* update width, height, framerate */
637         if ( player->pipeline->videobin &&
638                  player->pipeline->videobin[MMPLAYER_V_SINK].gst )
639         {
640                 GstCaps *caps_v = NULL;
641                 GstPad* pad = NULL;
642                 gint tmpNu, tmpDe;
643                 gint width, height;
644
645                 pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
646                 if ( pad )
647                 {
648                         caps_v = gst_pad_get_negotiated_caps( pad );
649                         if (caps_v)
650                         {
651                                 p = gst_caps_get_structure (caps_v, 0);
652                                 gst_structure_get_int (p, "width", &width);
653                                 mm_attrs_set_int_by_name(attrs, "content_video_width", width);
654
655                                 gst_structure_get_int (p, "height", &height);
656                                 mm_attrs_set_int_by_name(attrs, "content_video_height", height);
657
658                                 gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
659
660                                 debug_log("width : %d     height : %d", width, height );
661
662                                 gst_caps_unref( caps_v );
663                                 caps_v = NULL;
664
665                                 if (tmpDe > 0)
666                                 {
667                                         mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
668                                         debug_log("fps : %d", tmpNu / tmpDe);
669                                 }
670                         }
671                         else
672                         {
673                                 debug_warning("failed to get negitiated caps from videosink");
674                         }
675                         gst_object_unref( pad );
676                         pad = NULL;
677                 }
678                 else
679                 {
680                         debug_warning("failed to get pad from videosink");
681                 }
682         }
683
684         if (player->duration)
685         {
686                 guint64 data_size = 0;
687
688                 if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
689                 {
690                         mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
691
692                         if (stat(path, &sb) == 0)
693                         {
694                                 data_size = (guint64)sb.st_size;
695                         }
696                 }
697                 else if (MMPLAYER_IS_HTTP_STREAMING(player))
698                 {
699                         data_size = player->http_content_size;
700                 }
701
702                 if (data_size)
703                 {
704                         guint64 bitrate = 0;
705                         guint64 msec_dur = 0;
706
707                         msec_dur = GST_TIME_AS_MSECONDS(player->duration);
708                         bitrate = data_size * 8 * 1000 / msec_dur;
709                         debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
710                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
711                 }
712         }
713
714
715         /* validate all */
716         if (  mmf_attrs_commit ( attrs ) )
717         {
718                 debug_error("failed to update attributes\n");
719                 return FALSE;
720         }
721
722         player->need_update_content_attrs = FALSE;
723
724         return TRUE;
725 }
726
727 gboolean __mmplayer_update_stream_service_type( mm_player_t* player )
728 {
729         MMHandleType attrs = 0;
730         gint streaming_type = STREAMING_SERVICE_NONE;
731
732         debug_fenter();
733
734         return_val_if_fail ( player &&
735                                         player->pipeline &&
736                                         player->pipeline->mainbin &&
737                                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
738                                         FALSE );
739
740         /* streaming service type if streaming */
741         if ( ! MMPLAYER_IS_STREAMING(player) );
742                 return FALSE;
743
744         if (MMPLAYER_IS_RTSP_STREAMING(player))
745         {
746                 /* get property from rtspsrc element */
747                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "service_type", &streaming_type, NULL);
748         }
749         else if (MMPLAYER_IS_HTTP_STREAMING(player))
750         {
751                 if ( player->duration <= 0)
752                         streaming_type = STREAMING_SERVICE_LIVE;
753                 else
754                         streaming_type = STREAMING_SERVICE_VOD;                 
755         }
756                 
757         player->streaming_type = streaming_type;
758
759         if ( player->streaming_type == STREAMING_SERVICE_LIVE)
760         {
761                 debug_log("It's live streaming. pause/resume/seek are not working.\n");
762         }
763         else if (player->streaming_type == STREAMING_SERVICE_LIVE)
764         {
765                 debug_log("It's vod streaming. pause/resume/seek are working.\n");
766         }
767         else
768         {
769                 debug_warning("fail to determine streaming type. pause/resume/seek may not working properly if stream is live stream\n");
770         }
771
772         /* get profile attribute */
773         attrs = MMPLAYER_GET_ATTRS(player);
774         if ( !attrs )
775         {
776                 debug_error("cannot get content attribute\n");
777                 return FALSE;
778         }
779
780         mm_attrs_set_int_by_name ( attrs, "streaming_type", streaming_type );
781         /* validate all */
782         if (  mmf_attrs_commit ( attrs ) )
783         {
784                 debug_warning("updating streaming service type failed. pause/resume/seek may not working properly if stream is live stream\n");
785                 return FALSE;
786         }
787
788         debug_fleave();
789
790         return TRUE;
791 }
792
793
794 /* this function sets the player state and also report
795  * it to applicaton by calling callback function
796  */
797 static gboolean
798 __mmplayer_set_state(mm_player_t* player, int state) // @
799 {
800         MMMessageParamType msg = {0, };
801         int asm_result = MM_ERROR_NONE;
802
803         debug_fenter();
804         return_val_if_fail ( player, FALSE );
805
806         if ( MMPLAYER_CURRENT_STATE(player) == state )
807         {
808                 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
809                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
810                 return TRUE;
811         }
812
813         /* post message to application */
814         if (MMPLAYER_TARGET_STATE(player) == state)
815         {
816                 /* fill the message with state of player */
817                 msg.state.previous = MMPLAYER_CURRENT_STATE(player);
818                 msg.state.current = state;
819
820                 /* state changed by asm callback */
821                 if ( player->sm.by_asm_cb )
822                 {
823                         msg.union_type = MM_MSG_UNION_CODE;
824                         msg.code = player->sm.event_src;
825                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
826                 }
827                 /* state changed by usecase */
828                 else
829                 {
830                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
831                 }
832
833                 debug_log ("player reach the target state, then do something in each state(%s).\n", 
834                         MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
835         }
836         else
837         {
838                 debug_log ("intermediate state, do nothing.\n");
839                 MMPLAYER_PRINT_STATE(player);
840
841                 return TRUE;
842         }
843
844         /* update player states */
845         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
846         MMPLAYER_CURRENT_STATE(player) = state;
847         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
848                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
849
850         /* print state */
851         MMPLAYER_PRINT_STATE(player);
852         
853         switch ( MMPLAYER_TARGET_STATE(player) )
854         {
855                 case MM_PLAYER_STATE_NULL:      
856                 case MM_PLAYER_STATE_READY:
857                 {
858                         if (player->cmd == MMPLAYER_COMMAND_STOP)
859                         {
860                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP);
861                                 if ( asm_result != MM_ERROR_NONE )
862                                 {
863                                         debug_error("failed to set asm state to stop\n");
864                                         return FALSE;
865                                 }
866                         }
867                 }
868                 break;
869                         
870                 case MM_PLAYER_STATE_PAUSED:
871                 {
872                         /* special care for local playback. normaly we can get some content attribute
873                          * when the demuxer is changed to PAUSED. so we are trying it. it will be tried again
874                          * when PLAYING state has signalled if failed.
875                          * note that this is only happening pause command has come before the state of pipeline
876                          * reach to the PLAYING.
877                          */
878                         player->need_update_content_dur = TRUE;
879                         _mmplayer_update_content_attrs( player );
880
881                         /* add audio callback probe if condition is satisfied */
882                         if ( ! player->audio_cb_probe_id && player->is_sound_extraction )
883                                 __mmplayer_configure_audio_callback(player);
884
885                         asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE);
886                         if ( asm_result )
887                         {
888                                 debug_error("failed to set asm state to PAUSE\n");
889                                 return FALSE;
890                         }
891                 }
892                 break;
893
894                 case MM_PLAYER_STATE_PLAYING:
895                 {
896                         /* update attributes which are only available on playing status */
897                         player->need_update_content_attrs = TRUE;
898                         _mmplayer_update_content_attrs ( player );
899
900                         if ( player->cmd == MMPLAYER_COMMAND_START  && !player->sent_bos )
901                         {
902                                 __mmplayer_post_missed_plugin ( player );
903
904                                 /* update video resource status */
905                                 if ( ( player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO )
906                                 {
907                                         asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING);
908                                         if ( asm_result )
909                                         {
910                                                 MMMessageParamType msg = {0, };
911                                                                 
912                                                 debug_error("failed to go ahead because of video conflict\n");
913                                                                                                         
914                                                 msg.union_type = MM_MSG_UNION_CODE;
915                                                 msg.code = MM_ERROR_POLICY_INTERRUPTED;
916                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
917
918                                                 _mmplayer_unrealize((MMHandleType)player);
919                                                                                                                 
920                                                 return FALSE;                                                           
921                                         }
922                                 }
923                         }
924
925                         if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
926                         {
927                                 /* initialize because auto resume is done well. */
928                                 player->resumed_by_rewind = FALSE;
929                                 player->playback_rate = 1.0;
930                         }
931
932                         if ( !player->sent_bos )
933                         {
934                                 /* check audio codec field is set or not
935                                  * we can get it from typefinder or codec's caps.
936                                  */
937                                 gchar *audio_codec = NULL;
938                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
939
940                                 /* The codec format can't be sent for audio only case like amr, mid etc.
941                                  * Because, parser don't make related TAG.
942                                  * So, if it's not set yet, fill it with found data.
943                                  */
944                                 if ( ! audio_codec )
945                                 {
946                                         if ( g_strrstr(player->type, "audio/midi"))
947                                         {
948                                                 audio_codec = g_strdup("MIDI");
949
950                                         }
951                                         else if ( g_strrstr(player->type, "audio/x-amr"))
952                                         {
953                                                 audio_codec = g_strdup("AMR");
954                                         }
955                                         else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
956                                         {
957                                                 audio_codec = g_strdup("AAC");
958                                         }
959                                         else
960                                         {
961                                                 audio_codec = g_strdup("unknown");
962                                         }
963                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
964
965                                         MMPLAYER_FREEIF(audio_codec);
966                                         mmf_attrs_commit(player->attrs);
967                                         debug_log("set audio codec type with caps\n");
968                                 }
969
970                                 MMTA_ACUM_ITEM_END("[KPI] start media player service", FALSE);
971                                 MMTA_ACUM_ITEM_END("[KPI] media player service create->playing", FALSE);
972
973                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
974                                 player->sent_bos = TRUE;
975                         }
976                 }
977                 break;
978
979                 case MM_PLAYER_STATE_NONE:
980                 default:
981                         debug_warning("invalid target state, there is nothing to do.\n");
982                         break;
983         }
984
985         debug_fleave();
986
987         return TRUE;
988 }
989
990
991 gboolean
992 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
993 {
994         return_val_if_fail( player, FALSE );
995
996         debug_fenter();
997
998         if ( !player->msg_cb )
999         {
1000                 debug_warning("no msg callback. can't post\n");
1001                 return FALSE;
1002         }
1003
1004         //debug_log("Message (type : %d)  will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
1005
1006         player->msg_cb(msgtype, param, player->msg_cb_param);
1007
1008         debug_fleave();
1009
1010         return TRUE;
1011 }
1012
1013
1014 static int
1015 __mmplayer_get_state(mm_player_t* player) // @
1016 {
1017         int state = MM_PLAYER_STATE_NONE;
1018
1019         debug_fenter();
1020         
1021         return_val_if_fail ( player, MM_PLAYER_STATE_NONE );
1022
1023         state = MMPLAYER_CURRENT_STATE(player);
1024
1025         debug_log("player state is %s.\n", MMPLAYER_STATE_GET_NAME(state));
1026
1027         debug_fleave();
1028         
1029         return state;
1030 }
1031
1032 static void
1033 __gst_set_async_state_change(mm_player_t* player, gboolean async)
1034 {
1035         //debug_fenter();
1036         return_if_fail( player && player->pipeline && player->pipeline->mainbin );
1037
1038         /* need only when we are using decodebin */
1039         if ( ! PLAYER_INI()->use_decodebin )
1040                 return;
1041
1042         /* audio sink */
1043         if ( player->pipeline->audiobin &&
1044                  player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
1045         {
1046                 debug_log("audiosink async : %d\n", async);
1047                 g_object_set (G_OBJECT (player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "async", async, NULL);
1048         }
1049
1050         /* video sink */
1051         if ( player->pipeline->videobin &&
1052                  player->pipeline->videobin[MMPLAYER_V_SINK].gst )
1053         {
1054                 debug_log("videosink async : %d\n", async);
1055                 g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "async", async, NULL);
1056         }
1057
1058         /* decodebin if enabled */
1059         if ( PLAYER_INI()->use_decodebin )
1060         {
1061                 debug_log("decodebin async : %d\n", async);
1062                 g_object_set (G_OBJECT (player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst), "async-handling", async, NULL);
1063         }
1064
1065         //debug_fleave();
1066 }
1067
1068 static gpointer __mmplayer_repeat_thread(gpointer data)
1069 {
1070         mm_player_t* player = (mm_player_t*) data;
1071         gboolean ret_value = FALSE;
1072         MMHandleType attrs = 0;
1073         gint count = 0;
1074
1075         return_val_if_fail ( player, NULL );
1076
1077         while ( ! player->repeat_thread_exit )
1078         {
1079                 debug_log("repeat thread started. waiting for signal.\n");
1080                 g_cond_wait( player->repeat_thread_cond, player->repeat_thread_mutex );
1081
1082                 if ( player->repeat_thread_exit )
1083                 {
1084                         debug_log("exiting repeat thread\n");
1085                         break;
1086                 }
1087
1088                 /* lock */
1089                 MMPLAYER_CMD_LOCK( player );
1090
1091                 return_val_if_fail(     player, NULL );
1092
1093                 attrs = MMPLAYER_GET_ATTRS(player);
1094
1095                 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1096                 {
1097                         debug_error("can not get play count\n");
1098                                 break;
1099                 }
1100
1101                 if ( player->section_repeat )
1102                 {
1103                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1104                 }
1105                 else
1106                 {
1107                         if ( player->playback_rate < 0.0 )
1108                         {
1109                                 player->resumed_by_rewind = TRUE;
1110                                 _mmplayer_set_mute((MMHandleType)player, 0);
1111                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1112                         }
1113
1114                         ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
1115                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1116                                 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1117
1118                         /* initialize */
1119                         player->sent_bos = FALSE;
1120                 }
1121
1122                 if ( ! ret_value )
1123                 {
1124                         debug_error("failed to set position to zero for rewind\n");
1125                                 continue;
1126                 }
1127
1128                 /* decrease play count */
1129                 if ( count > 1 )
1130                 {
1131                         /* we successeded to rewind. update play count and then wait for next EOS */
1132                         count--;
1133
1134                         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1135
1136                         /* commit attribute */
1137                         if ( mmf_attrs_commit ( attrs ) )
1138                         {
1139                                 debug_error("failed to commit attribute\n");
1140                         }
1141                 }
1142
1143                 /* unlock */
1144                 MMPLAYER_CMD_UNLOCK( player );
1145         }
1146
1147         return NULL;
1148 }
1149
1150 static void
1151 __mmplayer_handle_buffering_message ( mm_player_t* player )
1152 {
1153         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1154         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1155         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1156         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1157
1158         return_if_fail ( player );
1159
1160         prev_state = MMPLAYER_PREV_STATE(player),
1161         current_state = MMPLAYER_CURRENT_STATE(player);
1162         target_state = MMPLAYER_TARGET_STATE(player);
1163         pending_state = MMPLAYER_PENDING_STATE(player);
1164
1165         if ( MMPLAYER_IS_RTSP_STREAMING(player) )
1166                 return;
1167
1168         if ( !player->streamer->is_buffering )
1169         {
1170                 debug_log( "player state : prev %s, current %s, pending %s, target %s \n",
1171                         MMPLAYER_STATE_GET_NAME(prev_state),
1172                         MMPLAYER_STATE_GET_NAME(current_state),
1173                         MMPLAYER_STATE_GET_NAME(pending_state),
1174                         MMPLAYER_STATE_GET_NAME(target_state));
1175
1176                 /* NOTE : if buffering has done, player has to go to target state. */
1177                 switch ( target_state )
1178                 {
1179                         case MM_PLAYER_STATE_PAUSED :
1180                         {
1181                                 switch ( pending_state )
1182                                 {
1183                                         case MM_PLAYER_STATE_PLAYING:
1184                                         {
1185                                                 __gst_pause ( player, TRUE );
1186                                         }
1187                                         break;
1188
1189                                         case MM_PLAYER_STATE_PAUSED:
1190                                         {
1191                                                  debug_log("player is already going to paused state, there is nothing to do.\n");
1192                                         }
1193                                         break;
1194
1195                                         case MM_PLAYER_STATE_NONE:
1196                                         case MM_PLAYER_STATE_NULL:
1197                                         case MM_PLAYER_STATE_READY:
1198                                         default :
1199                                         {
1200                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1201                                         }
1202                                                 break;
1203                                 }
1204                         }
1205                         break;
1206
1207                         case MM_PLAYER_STATE_PLAYING :
1208                         {
1209                                 switch ( pending_state )
1210                                 {
1211                                         case MM_PLAYER_STATE_NONE:
1212                                         {
1213                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
1214                                                         __gst_resume ( player, TRUE );
1215                                         }
1216                                         break;
1217
1218                                         case MM_PLAYER_STATE_PAUSED:
1219                                         {
1220                                                 __gst_resume ( player, TRUE );
1221                                         }
1222                                         break;
1223
1224                                         case MM_PLAYER_STATE_PLAYING:
1225                                         {
1226                                                  debug_log("player is already going to playing state, there is nothing to do.\n");
1227                                         }
1228                                         break;
1229
1230                                         case MM_PLAYER_STATE_NULL:
1231                                         case MM_PLAYER_STATE_READY:
1232                                         default :
1233                                         {
1234                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1235                                         }
1236                                                 break;
1237                                 }
1238                         }
1239                         break;
1240
1241                         case MM_PLAYER_STATE_NULL :
1242                         case MM_PLAYER_STATE_READY :
1243                         case MM_PLAYER_STATE_NONE :
1244                         default:
1245                         {
1246                                 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1247                         }
1248                                 break;
1249                 }
1250         }
1251         else
1252         {
1253                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1254                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
1255                  */
1256                 switch ( pending_state )
1257                 {
1258                         case MM_PLAYER_STATE_NONE:
1259                         {
1260                                 if (current_state != MM_PLAYER_STATE_PAUSED)
1261                                         __gst_pause ( player, TRUE );
1262                         }
1263                         break;
1264
1265                         case MM_PLAYER_STATE_PLAYING:
1266                         {
1267                                 __gst_pause ( player, TRUE );
1268                         }
1269                         break;
1270
1271                         case MM_PLAYER_STATE_PAUSED:
1272                         {
1273                                  debug_log("player is already going to paused state, there is nothing to do.\n");
1274                         }
1275                         break;
1276
1277                         case MM_PLAYER_STATE_NULL:
1278                         case MM_PLAYER_STATE_READY:
1279                         default :
1280                         {
1281                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1282                         }
1283                                 break;
1284                 }
1285         }
1286 }
1287
1288 static gboolean
1289 __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
1290 {
1291         mm_player_t* player = (mm_player_t*) data;
1292         gboolean ret = TRUE;
1293         static gboolean async_done = FALSE;
1294
1295         return_val_if_fail ( player, FALSE );
1296         return_val_if_fail ( msg && GST_IS_MESSAGE(msg), FALSE );
1297
1298         switch ( GST_MESSAGE_TYPE( msg ) )
1299         {
1300                 case GST_MESSAGE_UNKNOWN:
1301                         debug_warning("unknown message received\n");
1302                 break;
1303
1304                 case GST_MESSAGE_EOS:
1305                 {
1306                         MMHandleType attrs = 0;
1307                         gint count = 0;
1308
1309                         debug_log("GST_MESSAGE_EOS received\n");
1310
1311                         /* NOTE : EOS event is comming multiple time. watch out it */
1312                         /* check state. we only process EOS when pipeline state goes to PLAYING */
1313                         if ( ! (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) )
1314                         {
1315                                 debug_warning("EOS received on non-playing state. ignoring it\n");
1316                                 break;
1317                         }
1318
1319                         if ( (player->audio_stream_cb) && (player->is_sound_extraction) )
1320                         {
1321                                 GstPad *pad = NULL;
1322         
1323                                 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1324
1325                                 debug_error("release audio callback\n");
1326                                 
1327                                 /* release audio callback */
1328                                 gst_pad_remove_buffer_probe (pad, player->audio_cb_probe_id);
1329                                 player->audio_cb_probe_id = 0;
1330                                 /* audio callback should be free because it can be called even though probe remove.*/
1331                                 player->audio_stream_cb = NULL;
1332                                 player->audio_stream_cb_user_param = NULL;
1333
1334                         }
1335
1336                         /* rewind if repeat count is greater then zero */
1337                         /* get play count */
1338                         attrs = MMPLAYER_GET_ATTRS(player);
1339
1340                         if ( attrs )
1341                         {
1342                                 gboolean smooth_repeat = FALSE;
1343
1344                                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1345                                 mm_attrs_get_int_by_name(attrs, "profile_smooth_repeat", &smooth_repeat);
1346
1347                                 debug_log("remaining play count: %d, playback rate: %f\n", count, player->playback_rate);
1348
1349                                 if ( count > 1 || count == -1 || player->playback_rate < 0.0 ) /* default value is 1 */
1350                                 {
1351                                         if ( smooth_repeat )
1352                                         {
1353                                                 debug_log("smooth repeat enabled. seeking operation will be excuted in new thread\n");
1354
1355                                                 g_cond_signal( player->repeat_thread_cond );
1356
1357                                                 break;
1358                                         }
1359                                         else
1360                                         {
1361                                                 gint ret_value = 0;
1362
1363                                                 if ( player->section_repeat )
1364                                                 {
1365                                                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1366                                                 }
1367                                                 else
1368                                                 {
1369
1370                                                         if ( player->playback_rate < 0.0 )
1371                                                         {
1372                                                         player->resumed_by_rewind = TRUE;
1373                                                                 _mmplayer_set_mute((MMHandleType)player, 0);
1374                                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1375                                                         }
1376
1377                                                         ret_value = __gst_set_position( player, MM_PLAYER_POS_FORMAT_TIME, 0 );
1378
1379                                                         /* initialize */
1380                                                         player->sent_bos = FALSE;
1381                                                 }
1382
1383                                                 if ( MM_ERROR_NONE != ret_value )
1384                                                 {
1385                                                         debug_error("failed to set position to zero for rewind\n");
1386                                                 }
1387                                                 else
1388                                                 {
1389                                                         if ( count > 1 )
1390                                                         {
1391                                                                 /* we successeded to rewind. update play count and then wait for next EOS */
1392                                                                 count--;
1393
1394                                                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1395
1396                                                                 if ( mmf_attrs_commit ( attrs ) )
1397                                                                         debug_error("failed to commit attrs\n");
1398                                                         }
1399                                                 }
1400
1401                                                 break;
1402                                         }
1403                                 }
1404                         }
1405
1406                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-eos" );
1407
1408                         /* post eos message to application */
1409                         __mmplayer_post_delayed_eos( player, PLAYER_INI()->eos_delay );
1410
1411                         /* reset last position */
1412                         player->last_position = 0;
1413                 }
1414                 break;
1415
1416                 case GST_MESSAGE_ERROR:
1417                 {
1418                         GError *error = NULL;
1419                         gchar* debug = NULL;
1420                         gchar *msg_src_element = NULL;
1421
1422                         /* generating debug info before returning error */
1423                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-error" );
1424
1425                         /* get error code */
1426                         gst_message_parse_error( msg, &error, &debug );
1427
1428                         msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( msg->src ) );
1429                         if ( gst_structure_has_name ( msg->structure, "streaming_error" ) )
1430                         {
1431                                 /* Note : the streaming error from the streaming source is handled
1432                                  *   using __mmplayer_handle_streaming_error.
1433                                  */
1434                                 __mmplayer_handle_streaming_error ( player, msg );
1435
1436                                 /* dump state of all element */
1437                                 __mmplayer_dump_pipeline_state( player );
1438                         }
1439                         else
1440                         {
1441                                 /* traslate gst error code to msl error code. then post it
1442                                  * to application if needed
1443                                  */
1444                                 __mmplayer_handle_gst_error( player, msg, error );
1445
1446                                 /* dump state of all element */
1447                                 __mmplayer_dump_pipeline_state( player );
1448
1449                         }
1450
1451                         if (MMPLAYER_IS_HTTP_PD(player))
1452                         {       
1453                                 _mmplayer_pd_stop ((MMHandleType)player);
1454                         }
1455                         
1456                         MMPLAYER_FREEIF( debug );
1457                         g_error_free( error );
1458                 }
1459                 break;
1460
1461                 case GST_MESSAGE_WARNING:
1462                 {
1463                         char* debug = NULL;
1464                         GError* error = NULL;
1465
1466                         gst_message_parse_warning(msg, &error, &debug);
1467
1468                         debug_warning("warning : %s\n", error->message);
1469                         debug_warning("debug : %s\n", debug);
1470
1471                         MMPLAYER_POST_MSG( player, MM_MESSAGE_WARNING, NULL );
1472
1473                         MMPLAYER_FREEIF( debug );
1474                         g_error_free( error );
1475                 }
1476                 break;
1477
1478                 case GST_MESSAGE_INFO:                          debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
1479
1480                 case GST_MESSAGE_TAG:
1481                 {
1482                         debug_log("GST_MESSAGE_TAG\n");
1483                         if ( ! __mmplayer_gst_extract_tag_from_msg( player, msg ) )
1484                         {
1485                                 debug_warning("failed to extract tags from gstmessage\n");
1486                         }
1487                 }
1488                 break;
1489
1490                 case GST_MESSAGE_BUFFERING:
1491                 {
1492                         MMMessageParamType msg_param = {0, };
1493                         gboolean update_buffering_percent = TRUE;
1494
1495                         if ( !MMPLAYER_IS_STREAMING(player) || (player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS) ) // pure hlsdemux case, don't consider buffering of msl currently
1496                                 break;
1497
1498                         __mm_player_streaming_buffering (player->streamer, msg);
1499
1500                         __mmplayer_handle_buffering_message ( player );
1501
1502                         update_buffering_percent = player->pipeline_is_constructed || MMPLAYER_IS_RTSP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player);
1503                         if (update_buffering_percent)
1504                         {
1505                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1506                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param );
1507                         }
1508                 }
1509                 break;
1510
1511                 case GST_MESSAGE_STATE_CHANGED:
1512                 {
1513                         MMPlayerGstElement *mainbin;
1514                         const GValue *voldstate, *vnewstate, *vpending;
1515                         GstState oldstate, newstate, pending;
1516
1517                         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
1518                         {
1519                                 debug_error("player pipeline handle is null");
1520
1521                                 break;
1522                         }
1523
1524                         mainbin = player->pipeline->mainbin;
1525
1526                         /* get state info from msg */
1527                         voldstate = gst_structure_get_value (msg->structure, "old-state");
1528                         vnewstate = gst_structure_get_value (msg->structure, "new-state");
1529                         vpending = gst_structure_get_value (msg->structure, "pending-state");
1530
1531                         oldstate = (GstState)voldstate->data[0].v_int;
1532                         newstate = (GstState)vnewstate->data[0].v_int;
1533                         pending = (GstState)vpending->data[0].v_int;
1534
1535                         if (oldstate == newstate)
1536                                 break;
1537
1538                         debug_log("state changed [%s] : %s ---> %s     final : %s\n",
1539                                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
1540                                 gst_element_state_get_name( (GstState)oldstate ),
1541                                 gst_element_state_get_name( (GstState)newstate ),
1542                                 gst_element_state_get_name( (GstState)pending ) );
1543
1544                         /* we only handle messages from pipeline */
1545                         if( msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst )
1546                                 break;
1547
1548                         switch(newstate)
1549                         {
1550                                 case GST_STATE_VOID_PENDING:
1551                                 break;
1552
1553                                 case GST_STATE_NULL:
1554                                 break;
1555
1556                                 case GST_STATE_READY:
1557                                 break;
1558
1559                                 case GST_STATE_PAUSED:
1560                                 {
1561                                         if ( ! player->audio_cb_probe_id && player->is_sound_extraction )
1562                                                 __mmplayer_configure_audio_callback(player);
1563                                         
1564
1565                                         if ( MMPLAYER_IS_STREAMING(player) )
1566                                         {
1567                                                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
1568
1569                                                 __mm_player_streaming_set_content_bitrate(player->streamer, player->total_maximum_bitrate, player->total_bitrate);
1570
1571                                                 /* check pending seek and do now */
1572                                                 if ( player->pending_seek.is_pending )
1573                                                         __gst_pending_seek ( player );
1574                                         }
1575
1576                                         player->need_update_content_dur = TRUE;
1577                                 }                                       
1578                                 break;
1579
1580                                 case GST_STATE_PLAYING:
1581                                 {
1582
1583                                         gboolean is_async = FALSE;
1584
1585                            if (player->doing_seek && async_done)
1586                                         {
1587                                                 player->doing_seek = FALSE;
1588                                                 async_done = FALSE;
1589                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
1590                                         }
1591
1592                                         /* It should be called in case of async start only.
1593                                           * don't need to call in the case of resume and sync start (currently, resume is sync.)
1594                                           */
1595                                         mm_attrs_get_int_by_name(player->attrs,"profile_async_start", &is_async);
1596                                         if (is_async && player->cmd == MMPLAYER_COMMAND_START)
1597                                                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING );
1598                                 }
1599                                 break;
1600
1601                                 default:
1602                                 break;
1603                         }
1604                 }
1605                 break;
1606
1607                 case GST_MESSAGE_STATE_DIRTY:           debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
1608                 case GST_MESSAGE_STEP_DONE:                     debug_log("GST_MESSAGE_STEP_DONE\n"); break;
1609                 case GST_MESSAGE_CLOCK_PROVIDE:         debug_log("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
1610                 
1611                 case GST_MESSAGE_CLOCK_LOST:
1612                         {
1613                                 GstClock *clock = NULL;
1614                                 gst_message_parse_clock_lost (msg, &clock);
1615                                 debug_log("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
1616                                 g_print ("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
1617
1618                                 if (PLAYER_INI()->provide_clock)
1619                                 {
1620                                         debug_log ("Provide clock is TRUE, do pause->resume\n");
1621                                         __gst_pause(player, FALSE);
1622                                         __gst_resume(player, FALSE);
1623                                 }
1624                         }
1625                         break;
1626                         
1627                 case GST_MESSAGE_NEW_CLOCK:
1628                         {
1629                                 GstClock *clock = NULL;
1630                                 gst_message_parse_new_clock (msg, &clock);
1631                                 debug_log("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
1632                         }
1633                         break;
1634
1635                 case GST_MESSAGE_STRUCTURE_CHANGE:      debug_log("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
1636                 case GST_MESSAGE_STREAM_STATUS:         debug_log("GST_MESSAGE_STREAM_STATUS\n"); break;
1637                 case GST_MESSAGE_APPLICATION:           debug_log("GST_MESSAGE_APPLICATION\n"); break;
1638
1639                 case GST_MESSAGE_ELEMENT:
1640                 {
1641                         debug_log("GST_MESSAGE_ELEMENT\n");
1642                 }
1643                 break;
1644                 
1645                 case GST_MESSAGE_SEGMENT_START:         debug_log("GST_MESSAGE_SEGMENT_START\n"); break;
1646                 case GST_MESSAGE_SEGMENT_DONE:          debug_log("GST_MESSAGE_SEGMENT_DONE\n"); break;
1647                 
1648                 case GST_MESSAGE_DURATION:
1649                 {
1650                         debug_log("GST_MESSAGE_DURATION\n");
1651                 }
1652                 break;
1653                 
1654                 case GST_MESSAGE_LATENCY:                               debug_log("GST_MESSAGE_LATENCY\n"); break;
1655                 case GST_MESSAGE_ASYNC_START:           debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", gst_element_get_name(GST_MESSAGE_SRC(msg))); break;
1656                 
1657                 case GST_MESSAGE_ASYNC_DONE:    
1658                 {
1659                         debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", gst_element_get_name(GST_MESSAGE_SRC(msg)));
1660
1661                         if (player->doing_seek)
1662                         {
1663                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
1664                                 {
1665                                         player->doing_seek = FALSE;
1666                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
1667                                 }
1668                                 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
1669                                 {
1670                                         async_done = TRUE;
1671                                 }
1672                         }
1673                 }
1674                 break;
1675                 
1676                 case GST_MESSAGE_REQUEST_STATE:         debug_log("GST_MESSAGE_REQUEST_STATE\n"); break;
1677                 case GST_MESSAGE_STEP_START:            debug_log("GST_MESSAGE_STEP_START\n"); break;
1678                 case GST_MESSAGE_QOS:                                   debug_log("GST_MESSAGE_QOS\n"); break;
1679                 case GST_MESSAGE_PROGRESS:                      debug_log("GST_MESSAGE_PROGRESS\n"); break;
1680                 case GST_MESSAGE_ANY:                           debug_log("GST_MESSAGE_ANY\n"); break;
1681
1682                 default:
1683                         debug_warning("unhandled message\n");
1684                 break;
1685         }
1686
1687         /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
1688          * gst_element_post_message api takes ownership of the message.
1689          */
1690         //gst_message_unref( msg );
1691
1692         return ret;
1693 }
1694
1695 static gboolean
1696 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg) // @
1697 {
1698
1699 /* macro for better code readability */
1700 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
1701 if (gst_tag_list_get_string(tag_list, gsttag, &string)) \
1702 {\
1703         if (string != NULL)\
1704         {\
1705                 debug_log ( "update tag string : %s\n", string); \
1706                 mm_attrs_set_string_by_name(attribute, playertag, string); \
1707                 g_free(string);\
1708                 string = NULL;\
1709         }\
1710 }
1711
1712 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
1713 value = gst_tag_list_get_value_index(tag_list, gsttag, index); \
1714 if (value) \
1715 {\
1716         buffer = gst_value_get_buffer (value); \
1717         debug_log ( "update album cover data : %p, size : %d\n", GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); \
1718         player->album_art = (gchar *)g_malloc(GST_BUFFER_SIZE(buffer)); \
1719         if (player->album_art); \
1720         { \
1721                 memcpy(player->album_art, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); \
1722                 mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, GST_BUFFER_SIZE(buffer)); \
1723         } \
1724 }
1725
1726 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
1727 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint))\
1728 {\
1729         if(v_uint)\
1730         {\
1731                 if(gsttag==GST_TAG_BITRATE)\
1732                 {\
1733                         if (player->updated_bitrate_count == 0) \
1734                                 mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
1735                         if (player->updated_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
1736                         {\
1737                                 player->bitrate[player->updated_bitrate_count] = v_uint;\
1738                                 player->total_bitrate += player->bitrate[player->updated_maximum_bitrate_count]; \
1739                                 player->updated_bitrate_count++; \
1740                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate);\
1741                                 debug_log ( "update bitrate %d[bps] of stream #%d.\n", v_uint, player->updated_bitrate_count);\
1742                         }\
1743                 }\
1744                 else if (gsttag==GST_TAG_MAXIMUM_BITRATE)\
1745                 {\
1746                         if (player->updated_maximum_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
1747                         {\
1748                                 player->maximum_bitrate[player->updated_maximum_bitrate_count] = v_uint;\
1749                                 player->total_maximum_bitrate += player->maximum_bitrate[player->updated_maximum_bitrate_count]; \
1750                                 player->updated_maximum_bitrate_count++; \
1751                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate); \
1752                                 debug_log ( "update maximum bitrate %d[bps] of stream #%d\n", v_uint, player->updated_maximum_bitrate_count);\
1753                         }\
1754                 }\
1755                 else\
1756                 {\
1757                         mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
1758                 }\
1759                 v_uint = 0;\
1760         }\
1761 }
1762
1763 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
1764 if (gst_tag_list_get_date(tag_list, gsttag, &date))\
1765 {\
1766         if (date != NULL)\
1767         {\
1768                 string = g_strdup_printf("%d", g_date_get_year(date));\
1769                 mm_attrs_set_string_by_name(attribute, playertag, string);\
1770                 debug_log ( "metainfo year : %s\n", string);\
1771                 MMPLAYER_FREEIF(string);\
1772                 g_date_free(date);\
1773         }\
1774 }
1775
1776 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
1777 if(gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64))\
1778 {\
1779         if(v_uint64)\
1780         {\
1781                 /* FIXIT : don't know how to store date */\
1782                 g_assert(1);\
1783                 v_uint64 = 0;\
1784         }\
1785 }
1786
1787 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
1788 if(gst_tag_list_get_double(tag_list, gsttag, &v_double))\
1789 {\
1790         if(v_double)\
1791         {\
1792                 /* FIXIT : don't know how to store date */\
1793                 g_assert(1);\
1794                 v_double = 0;\
1795         }\
1796 }
1797
1798         /* function start */
1799         GstTagList* tag_list = NULL;
1800
1801         MMHandleType attrs = 0;
1802
1803         char *string = NULL;
1804         guint v_uint = 0;
1805         GDate *date = NULL;
1806         /* album cover */
1807         GstBuffer *buffer = NULL;
1808         gint index = 0;
1809         const GValue *value;
1810
1811         /* currently not used. but those are needed for above macro */
1812         //guint64 v_uint64 = 0;
1813         //gdouble v_double = 0;
1814
1815         return_val_if_fail( player && msg, FALSE );
1816
1817         attrs = MMPLAYER_GET_ATTRS(player);
1818
1819         return_val_if_fail( attrs, FALSE );
1820
1821         /* get tag list from gst message */
1822         gst_message_parse_tag(msg, &tag_list);
1823
1824         /* store tags to player attributes */
1825         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
1826         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
1827         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
1828         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
1829         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
1830         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
1831         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
1832         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
1833         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
1834         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
1835         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
1836         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
1837         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
1838         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
1839         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
1840         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
1841         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
1842         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
1843         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
1844         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
1845         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
1846         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
1847         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
1848         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
1849         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
1850         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
1851         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
1852         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
1853         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
1854         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
1855         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
1856         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
1857         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
1858         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
1859         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
1860         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
1861         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
1862         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
1863         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
1864         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
1865         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
1866         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
1867         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
1868         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
1869         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
1870
1871         if ( mmf_attrs_commit ( attrs ) )
1872                 debug_error("failed to commit.\n");
1873
1874         gst_tag_list_free(tag_list);
1875
1876         return TRUE;
1877 }
1878
1879 static void
1880 __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data)  // @
1881 {
1882         mm_player_t* player = (mm_player_t*) data;
1883
1884         debug_fenter();
1885
1886         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
1887           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
1888           * num_dynamic_pad. and this is no-more-pad situation which means mo more pad will be added.
1889           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
1890
1891           * [1] audio and video will be dumped with filesink.
1892           * [2] autoplugging is done by just using pad caps.
1893           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
1894           * and the video will be dumped via filesink.
1895           */
1896         if ( player->num_dynamic_pad == 0 )
1897         {
1898                 debug_log("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
1899
1900                 if ( ! __mmplayer_gst_remove_fakesink( player,
1901                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) );
1902         }
1903
1904         /* create dot before error-return. for debugging */
1905         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-no-more-pad" );
1906
1907         /* NOTE : if rtspsrc goes to PLAYING before adding it's src pads, a/v sink elements will
1908          * not goes to PLAYING. they will just remain in PAUSED state. simply we are giving
1909          * PLAYING state again.
1910          */
1911         __mmplayer_gst_set_state(player,
1912                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, TRUE, 5000 );
1913
1914         player->no_more_pad = TRUE;
1915
1916         debug_fleave();
1917 }
1918
1919 static gboolean
1920 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink) // @
1921 {
1922         GstElement* parent = NULL;
1923
1924         return_val_if_fail(player && player->pipeline && fakesink, FALSE);
1925
1926         /* lock */
1927         g_mutex_lock( player->fsink_lock );
1928
1929         if ( ! fakesink->gst )
1930         {
1931                 goto ERROR;
1932         }
1933
1934         /* get parent of fakesink */
1935         parent = (GstElement*)gst_object_get_parent( (GstObject*)fakesink->gst );
1936         if ( ! parent )
1937         {
1938                 debug_log("fakesink already removed\n");
1939                 goto ERROR;
1940         }
1941
1942         gst_element_set_locked_state( fakesink->gst, TRUE );
1943
1944         /* setting the state to NULL never returns async
1945          * so no need to wait for completion of state transiton
1946          */
1947         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (fakesink->gst, GST_STATE_NULL) )
1948         {
1949                 debug_error("fakesink state change failure!\n");
1950
1951                 /* FIXIT : should I return here? or try to proceed to next? */
1952                 /* return FALSE; */
1953         }
1954
1955         /* remove fakesink from it's parent */
1956         if ( ! gst_bin_remove( GST_BIN( parent ), fakesink->gst ) )
1957         {
1958                 debug_error("failed to remove fakesink\n");
1959
1960                 gst_object_unref( parent );
1961
1962                 goto ERROR;
1963         }
1964
1965         gst_object_unref( parent );
1966
1967         /* FIXIT : releasing fakesink takes too much time (around 700ms)
1968          * we need to figure out the reason why. just for now, fakesink will be released
1969          * in __mmplayer_gst_destroy_pipeline()
1970          */
1971         //      gst_object_unref ( fakesink->gst );
1972         //      fakesink->gst = NULL;
1973
1974         debug_log("state-holder removed\n");
1975
1976         gst_element_set_locked_state( fakesink->gst, FALSE );
1977
1978         g_mutex_unlock( player->fsink_lock );
1979         return TRUE;
1980
1981 ERROR:
1982         if ( fakesink->gst )
1983         {
1984                 gst_element_set_locked_state( fakesink->gst, FALSE );
1985         }
1986
1987         g_mutex_unlock( player->fsink_lock );
1988         return FALSE;
1989 }
1990
1991
1992 static void
1993 __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
1994 {
1995         GstPad *sinkpad = NULL;
1996         GstCaps* caps = NULL;
1997         GstElement* new_element = NULL;
1998         enum MainElementID element_id = MMPLAYER_M_NUM;
1999
2000         mm_player_t* player = (mm_player_t*) data;
2001
2002         debug_fenter();
2003
2004         return_if_fail( element && pad );
2005         return_if_fail( player &&
2006                                         player->pipeline &&
2007                                         player->pipeline->mainbin );
2008
2009
2010         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2011          * num_dynamic_pad will decreased after creating a sinkbin.
2012          */
2013         player->num_dynamic_pad++;
2014         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2015
2016         /* perform autoplugging if dump is disabled */
2017         if ( PLAYER_INI()->rtsp_do_typefinding )
2018         {
2019                 /* create typefind */
2020                 new_element = gst_element_factory_make( "typefind", NULL );
2021                 if ( ! new_element )
2022                 {
2023                         debug_error("failed to create typefind\n");
2024                         goto ERROR;
2025                 }
2026
2027                 MMPLAYER_SIGNAL_CONNECT(        player,
2028                                                                         G_OBJECT(new_element),
2029                                                                         "have-type",
2030                                                                         G_CALLBACK(__mmplayer_typefind_have_type),
2031                                                                         (gpointer)player);
2032
2033                 /* FIXIT : try to remove it */
2034                 player->have_dynamic_pad = FALSE;
2035         }
2036         else  /* NOTE : use pad's caps directely. if enabled. what I am assuming is there's no elemnt has dynamic pad */
2037         {
2038                 debug_log("using pad caps to autopluging instead of doing typefind\n");
2039
2040                 caps = gst_pad_get_caps( pad );
2041
2042                 MMPLAYER_CHECK_NULL( caps );
2043
2044                 /* clear  previous result*/
2045                 player->have_dynamic_pad = FALSE;
2046
2047                 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
2048                 {
2049                         debug_error("failed to autoplug for caps : %s\n", gst_caps_to_string( caps ) );
2050                         goto ERROR;
2051                 }
2052
2053                 /* check if there's dynamic pad*/
2054                 if( player->have_dynamic_pad )
2055                 {
2056                         debug_error("using pad caps assums there's no dynamic pad !\n");
2057                         debug_error("try with enalbing rtsp_do_typefinding\n");
2058                         goto ERROR;
2059                 }
2060
2061                 gst_caps_unref( caps );
2062                 caps = NULL;
2063         }
2064
2065         /* excute new_element if created*/
2066         if ( new_element )
2067         {
2068                 debug_log("adding new element to pipeline\n");
2069
2070                 /* set state to READY before add to bin */
2071                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2072
2073                 /* add new element to the pipeline */
2074                 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2075                 {
2076                         debug_error("failed to add autoplug element to bin\n");
2077                         goto ERROR;
2078                 }
2079
2080                 /* get pad from element */
2081                 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2082                 if ( !sinkpad )
2083                 {
2084                         debug_error("failed to get sinkpad from autoplug element\n");
2085                         goto ERROR;
2086                 }
2087
2088                 /* link it */
2089                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2090                 {
2091                         debug_error("failed to link autoplug element\n");
2092                         goto ERROR;
2093                 }
2094
2095                 gst_object_unref (sinkpad);
2096                 sinkpad = NULL;
2097
2098                 /* run. setting PLAYING here since streamming source is live source */
2099                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2100         }
2101
2102         /* store handle to futher manipulation */
2103         player->pipeline->mainbin[element_id].id = element_id;
2104         player->pipeline->mainbin[element_id].gst = new_element;
2105
2106         debug_fleave();
2107
2108         return;
2109
2110 STATE_CHANGE_FAILED:
2111 ERROR:
2112         /* FIXIT : take care if new_element has already added to pipeline */
2113         if ( new_element )
2114                 gst_object_unref(GST_OBJECT(new_element));
2115
2116         if ( sinkpad )
2117                 gst_object_unref(GST_OBJECT(sinkpad));
2118
2119         if ( caps )
2120                 gst_object_unref(GST_OBJECT(caps));
2121
2122         /* FIXIT : how to inform this error to MSL ????? */
2123         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2124          * then post an error to application
2125          */
2126 }
2127
2128
2129 static void
2130 __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gboolean last, gpointer data) // @
2131 {
2132         mm_player_t* player = NULL;
2133         MMHandleType attrs = 0;
2134         GstElement* pipeline = NULL;
2135         GstCaps* caps = NULL;
2136         GstStructure* str = NULL;
2137         const gchar* name = NULL;
2138         GstPad* sinkpad = NULL;
2139         GstElement* sinkbin = NULL;
2140
2141         /* check handles */
2142         player = (mm_player_t*) data;
2143
2144         return_if_fail( decodebin && pad );
2145         return_if_fail(player && player->pipeline && player->pipeline->mainbin);
2146
2147         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
2148
2149         attrs = MMPLAYER_GET_ATTRS(player);
2150         if ( !attrs )
2151         {
2152                 debug_error("cannot get content attribute\n");
2153                 goto ERROR;
2154         }
2155
2156         /* get mimetype from caps */
2157         caps = gst_pad_get_caps( pad );
2158         if ( !caps )
2159         {
2160                 debug_error("cannot get caps from pad.\n");
2161                 goto ERROR;
2162         }
2163
2164         str = gst_caps_get_structure( caps, 0 );
2165         if ( ! str )
2166         {
2167                 debug_error("cannot get structure from capse.\n");
2168                 goto ERROR;
2169         }
2170
2171         name = gst_structure_get_name(str);
2172         if ( ! name )
2173         {
2174                 debug_error("cannot get mimetype from structure.\n");
2175                 goto ERROR;
2176         }
2177
2178         debug_log("detected mimetype : %s\n", name);
2179
2180         if (strstr(name, "audio"))
2181         {
2182                 if (player->pipeline->audiobin == NULL)
2183                 {
2184                         __ta__("__mmplayer_gst_create_audio_pipeline",
2185                                 if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player))
2186                                 {
2187                                         debug_error("failed to create audiobin. continuing without audio\n");
2188                                         goto ERROR;
2189                                 }
2190                         )
2191
2192                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
2193                         debug_log("creating audiosink bin success\n");
2194                 }
2195                 else
2196                 {
2197                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
2198                         debug_log("re-using audiobin\n");
2199                 }
2200
2201                 /* FIXIT : track number shouldn't be hardcoded */
2202                 mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
2203
2204                 player->audiosink_linked  = 1;
2205                 debug_msg("player->audsink_linked set to 1\n");
2206
2207         }
2208         else if (strstr(name, "video"))
2209         {
2210                 if (player->pipeline->videobin == NULL)
2211                 {
2212                         /*      NOTE : not make videobin because application dose not want to play it even though file has video stream.
2213                         */
2214
2215                         /* get video surface type */
2216                         int surface_type = 0;
2217                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
2218                         debug_log("check display surface type attribute: %d", surface_type);
2219                         if (surface_type == MM_DISPLAY_SURFACE_NULL)
2220                         {
2221                                 debug_log("not make videobin because it dose not want\n");
2222                                 goto ERROR;
2223                         }
2224
2225                         __ta__("__mmplayer_gst_create_video_pipeline",
2226                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type) )
2227                         {
2228                                 debug_error("failed to create videobin. continuing without video\n");
2229                                 goto ERROR;
2230                         }
2231                         )
2232
2233                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
2234                         debug_log("creating videosink bin success\n");
2235                 }
2236                 else
2237                 {
2238                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
2239                         debug_log("re-using videobin\n");
2240                 }
2241
2242                 /* FIXIT : track number shouldn't be hardcoded */
2243                 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 1);
2244
2245                 player->videosink_linked  = 1;
2246                 debug_msg("player->videosink_linked set to 1\n");
2247
2248         }
2249         else if (strstr(name, "text"))
2250         {
2251                 if (player->pipeline->textbin == NULL)
2252                 {
2253                         __ta__("__mmplayer_gst_create_text_pipeline",
2254                                 if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
2255                                 {
2256                                         debug_error("failed to create textbin. continuing without text\n");
2257                                         goto ERROR;
2258                                 }
2259                         )
2260
2261                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
2262                         debug_log("creating textink bin success\n");
2263                 }
2264                 else
2265                 {
2266                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
2267                         debug_log("re-using textbin\n");
2268                 }
2269
2270                 /* FIXIT : track number shouldn't be hardcoded */
2271                 mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
2272
2273                 player->textsink_linked  = 1;
2274                 debug_msg("player->textsink_linked set to 1\n");
2275         }
2276         else
2277         {
2278                 debug_warning("unknown type of elementary stream! ignoring it...\n");
2279                 goto ERROR;
2280         }
2281
2282         if ( sinkbin )
2283         {
2284                 /* warm up */
2285                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_READY ) )
2286                 {
2287                         debug_error("failed to set state(READY) to sinkbin\n");
2288                         goto ERROR;
2289                 }
2290
2291                 /* add */
2292                 if ( FALSE == gst_bin_add( GST_BIN(pipeline), sinkbin ) )
2293                 {
2294                         debug_error("failed to add sinkbin to pipeline\n");
2295                         goto ERROR;
2296                 }
2297
2298                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
2299
2300                 if ( !sinkpad )
2301                 {
2302                         debug_error("failed to get pad from sinkbin\n");
2303                         goto ERROR;
2304                 }
2305
2306                 /* link */
2307                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2308                 {
2309                         debug_error("failed to get pad from sinkbin\n");
2310                         goto ERROR;
2311                 }
2312
2313                 /* run */
2314                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_PAUSED ) )
2315                 {
2316                         debug_error("failed to set state(PLAYING) to sinkbin\n");
2317                         goto ERROR;
2318                 }
2319
2320                 gst_object_unref( sinkpad );
2321                 sinkpad = NULL;
2322         }
2323
2324         /* update track number attributes */
2325         if ( mmf_attrs_commit ( attrs ) )
2326                 debug_error("failed to commit attrs\n");
2327
2328         debug_log("linking sink bin success\n");
2329
2330
2331         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
2332          * streaming task. if the task blocked, then buffer will not flow to the next element
2333          * ( autoplugging element ). so this is special hack for streaming. please try to remove it
2334          */
2335         /* dec stream count. we can remove fakesink if it's zero */
2336         player->num_dynamic_pad--;
2337
2338         debug_log("stream count dec : %d (num of dynamic pad)\n", player->num_dynamic_pad);
2339
2340         if ( ( player->no_more_pad ) && ( player->num_dynamic_pad == 0 ) )
2341         {
2342                 __mmplayer_pipeline_complete( NULL, player );
2343         }
2344
2345 ERROR:
2346         if ( caps )
2347                 gst_caps_unref( caps );
2348
2349         if ( sinkpad )
2350                 gst_object_unref(GST_OBJECT(sinkpad));
2351
2352         return;
2353 }
2354
2355 int
2356 _mmplayer_update_video_param(mm_player_t* player) // @
2357 {
2358         MMHandleType attrs = 0;
2359         MMDisplaySurfaceType surface_type = 0;
2360
2361         debug_fenter();
2362
2363         /* check video sinkbin is created */
2364         return_val_if_fail ( player && 
2365                 player->pipeline &&
2366                 player->pipeline->videobin &&
2367                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
2368                 player->pipeline->videobin[MMPLAYER_V_SINK].gst, 
2369                 MM_ERROR_PLAYER_NOT_INITIALIZED );
2370
2371         attrs = MMPLAYER_GET_ATTRS(player);
2372         if ( !attrs )
2373         {
2374                 debug_error("cannot get content attribute");
2375                 return MM_ERROR_PLAYER_INTERNAL;
2376         }
2377
2378         /* update display surface */
2379         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
2380         debug_log("check display surface type attribute: %d", surface_type);
2381
2382         /* check video stream callback is used */
2383         if( player->use_video_stream )
2384         {
2385                 int rotate, width, height, orientation;
2386
2387                 rotate = width = height = orientation = 0;
2388
2389                 debug_log("using video stream callback with memsink. player handle : [%p]", player);
2390
2391                 mm_attrs_get_int_by_name(attrs, "display_width", &width);
2392                 mm_attrs_get_int_by_name(attrs, "display_height", &height);
2393                 mm_attrs_get_int_by_name(attrs, "display_rotation", &rotate);
2394                 mm_attrs_get_int_by_name(attrs, "display_orientation", &orientation);
2395
2396                 if (rotate < MM_DISPLAY_ROTATION_NONE || rotate > MM_DISPLAY_ROTATION_270)
2397                         rotate = 0;
2398                 else
2399                         rotate *= 90;
2400
2401                 if(orientation == 1)        rotate = 90;
2402                 else if(orientation == 2)   rotate = 180;
2403                 else if(orientation == 3)   rotate = 270;
2404
2405                 if (width)
2406                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "width", width, NULL);
2407
2408                 if (height)
2409                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "height", height, NULL);
2410
2411                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "rotate", rotate,NULL);
2412                 
2413                 return MM_ERROR_NONE;
2414         }
2415
2416         /* configuring display */
2417         switch ( surface_type )
2418         {
2419                 case MM_DISPLAY_SURFACE_X:
2420                 {
2421                 /* ximagesink or xvimagesink */
2422                         void *xid = NULL;
2423                         int zoom = 0;
2424                         int degree = 0;
2425                         int display_method = 0;
2426                         int roi_x = 0;
2427                         int roi_y = 0;
2428                         int roi_w = 0;
2429                         int roi_h = 0;
2430                         int force_aspect_ratio = 0;
2431
2432                         gboolean visible = TRUE;
2433
2434                         /* common case if using x surface */
2435                         mm_attrs_get_data_by_name(attrs, "display_overlay", &xid);
2436                         if ( xid )
2437                         {
2438                                 debug_log("set video param : xid %d", *(int*)xid);
2439                                 gst_x_overlay_set_xwindow_id( GST_X_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)xid );
2440                         }
2441                         else
2442                         {
2443                                 /* FIXIT : is it error case? */
2444                                 debug_warning("still we don't have xid on player attribute. create it's own surface.");
2445                         }
2446
2447                         /* if xvimagesink */
2448                         if (!strcmp(PLAYER_INI()->videosink_element_x,"xvimagesink"))
2449                         {
2450                                 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
2451                                 mm_attrs_get_int_by_name(attrs, "display_zoom", &zoom);
2452                                 mm_attrs_get_int_by_name(attrs, "display_rotation", &degree);
2453                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
2454                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
2455                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
2456                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
2457                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
2458                                 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
2459
2460                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
2461                                         "force-aspect-ratio", force_aspect_ratio,
2462                                         "zoom", zoom,
2463                                         "rotate", degree,
2464                                         "handle-events", TRUE,
2465                                         "display-geometry-method", display_method,
2466                                         "draw-borders", FALSE,
2467                                         "dst-roi-x", roi_x,
2468                                         "dst-roi-y", roi_y,
2469                                         "dst-roi-w", roi_w,
2470                                         "dst-roi-h", roi_h,
2471                                         "visible", visible,
2472                                         NULL );
2473
2474                                 debug_log("set video param : zoom %d", zoom);
2475                                 debug_log("set video param : rotate %d", degree);
2476                                 debug_log("set video param : method %d", display_method);
2477                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
2478                                                                 roi_x, roi_y, roi_w, roi_h );
2479                                 debug_log("set video param : visible %d", visible);
2480                                 debug_log("set video param : force aspect ratio %d", force_aspect_ratio);
2481                         }
2482                 }
2483                 break;
2484                 case MM_DISPLAY_SURFACE_EVAS:
2485                 {
2486                         void *object = NULL;
2487                         int scaling = 0;
2488                         gboolean visible = TRUE;
2489
2490                         /* common case if using evas surface */
2491                         mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
2492                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
2493                         mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
2494                         if (object)
2495                         {
2496                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
2497                                                 "evas-object", object,
2498                                                 "visible", visible,
2499                                                 NULL);
2500                                 debug_log("set video param : evas-object %x", object);
2501                                 debug_log("set video param : visible %d", visible);
2502                         }
2503                         else
2504                         {
2505                                 debug_error("no evas object");
2506                                 return MM_ERROR_PLAYER_INTERNAL;
2507                         }
2508
2509                         /* if evaspixmapsink */
2510                         if (!strcmp(PLAYER_INI()->videosink_element_evas,"evaspixmapsink"))
2511                         {
2512                                 int display_method = 0;
2513                                 int roi_x = 0;
2514                                 int roi_y = 0;
2515                                 int roi_w = 0;
2516                                 int roi_h = 0;
2517                                 int force_aspect_ratio = 0;
2518                                 int origin_size = !scaling;
2519
2520                                 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
2521                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
2522                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
2523                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
2524                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
2525                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
2526
2527                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
2528                                         "force-aspect-ratio", force_aspect_ratio,
2529                                         "origin-size", origin_size,
2530                                         "dst-roi-x", roi_x,
2531                                         "dst-roi-y", roi_y,
2532                                         "dst-roi-w", roi_w,
2533                                         "dst-roi-h", roi_h,
2534                                         "display-geometry-method", display_method,
2535                                         NULL );
2536
2537                                 debug_log("set video param : method %d", display_method);
2538                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
2539                                                                 roi_x, roi_y, roi_w, roi_h );
2540                                 debug_log("set video param : force aspect ratio %d", force_aspect_ratio);
2541                                 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
2542                         }
2543                 }
2544                 break;
2545                 case MM_DISPLAY_SURFACE_X_EXT:  /* NOTE : this surface type is for the video texture(canvas texture) */
2546                 {
2547                         void *pixmap_id_cb = NULL;
2548                         void *pixmap_id_cb_user_data = NULL;
2549                         int zoom = 0;
2550                         int degree = 0;
2551                         int display_method = 0;
2552                         int roi_x = 0;
2553                         int roi_y = 0;
2554                         int roi_w = 0;
2555                         int roi_h = 0;
2556                         int force_aspect_ratio = 0;
2557                         gboolean visible = TRUE;
2558
2559                         /* if xvimagesink */
2560                         if (strcmp(PLAYER_INI()->videosink_element_x,"xvimagesink"))
2561                         {
2562                                 debug_error("videosink is not xvimagesink");
2563                                 return MM_ERROR_PLAYER_INTERNAL;
2564                         }
2565
2566                         /* get information from attributes */
2567                         mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
2568                         mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
2569                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
2570
2571                         if ( pixmap_id_cb )
2572                         {
2573                                 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
2574                                 if (pixmap_id_cb_user_data)
2575                                 {
2576                                         debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
2577                                 }
2578                         }
2579                         else
2580                         {
2581                                 debug_error("failed to set pixmap-id-callback");
2582                                 return MM_ERROR_PLAYER_INTERNAL;
2583                         }
2584                         debug_log("set video param : method %d", display_method);
2585                         debug_log("set video param : visible %d", visible);
2586
2587                         /* set properties of videosink plugin */
2588                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
2589                                 "display-geometry-method", display_method,
2590                                 "draw-borders", FALSE,
2591                                 "visible", visible,
2592                                 "pixmap-id-callback", pixmap_id_cb,
2593                                 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
2594                                 NULL );
2595                 }
2596                 break;
2597                 case MM_DISPLAY_SURFACE_NULL:
2598                 {
2599                         /* do nothing */
2600                 }
2601                 break;
2602         }
2603
2604         debug_fleave();
2605
2606         return MM_ERROR_NONE;
2607 }
2608
2609 static int
2610 __mmplayer_gst_element_link_bucket(GList* element_bucket) // @
2611 {
2612         GList* bucket = element_bucket;
2613         MMPlayerGstElement* element = NULL;
2614         MMPlayerGstElement* prv_element = NULL;
2615         gint successful_link_count = 0;
2616
2617         debug_fenter();
2618
2619         return_val_if_fail(element_bucket, -1);
2620
2621         prv_element = (MMPlayerGstElement*)bucket->data;
2622         bucket = bucket->next;
2623
2624         for ( ; bucket; bucket = bucket->next )
2625         {
2626                 element = (MMPlayerGstElement*)bucket->data;
2627
2628                 if ( element && element->gst )
2629                 {
2630                         if ( GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst)) )
2631                         {
2632                                 debug_log("linking [%s] to [%s] success\n",
2633                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
2634                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
2635                                 successful_link_count ++;
2636                         }
2637                         else
2638                         {
2639                                 debug_log("linking [%s] to [%s] failed\n",
2640                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
2641                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
2642                                 return -1;
2643                         }
2644
2645                 }
2646
2647                 prv_element = element;
2648         }
2649
2650         debug_fleave();
2651
2652         return successful_link_count;
2653 }
2654
2655 static int
2656 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket) // @
2657 {
2658         GList* bucket = element_bucket;
2659         MMPlayerGstElement* element = NULL;
2660         int successful_add_count = 0;
2661
2662         debug_fenter();
2663
2664         return_val_if_fail(element_bucket, 0);
2665         return_val_if_fail(bin, 0);
2666
2667         for ( ; bucket; bucket = bucket->next )
2668         {
2669                 element = (MMPlayerGstElement*)bucket->data;
2670
2671                 if ( element && element->gst )
2672                 {
2673                         if( !gst_bin_add(bin, GST_ELEMENT(element->gst)) )
2674                         {
2675                                 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
2676                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
2677                                         GST_ELEMENT_NAME(GST_ELEMENT(bin) ) );
2678                                 return 0;
2679                         }
2680                         successful_add_count ++;
2681                 }
2682         }
2683
2684         debug_fleave();
2685
2686         return successful_add_count;
2687 }
2688
2689
2690
2691 /**
2692  * This function is to create audio pipeline for playing.
2693  *
2694  * @param       player          [in]    handle of player
2695  *
2696  * @return      This function returns zero on success.
2697  * @remark
2698  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
2699  */
2700 #define MMPLAYER_CREATEONLY_ELEMENT(x_bin, x_id, x_factory, x_name) \
2701 x_bin[x_id].id = x_id;\
2702 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
2703 if ( ! x_bin[x_id].gst )\
2704 {\
2705         debug_critical("failed to create %s \n", x_factory);\
2706         goto ERROR;\
2707 }\
2708
2709 /* macro for code readability. just for sinkbin-creation functions */
2710 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket) \
2711 do \
2712 { \
2713         x_bin[x_id].id = x_id;\
2714         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
2715         if ( ! x_bin[x_id].gst )\
2716         {\
2717                 debug_critical("failed to create %s \n", x_factory);\
2718                 goto ERROR;\
2719         }\
2720         if ( x_add_bucket )\
2721                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
2722 } while(0);
2723
2724
2725 /**
2726   * AUDIO PIPELINE 
2727   * - Local playback    : audioconvert !volume ! capsfilter ! dnse ! audiosink
2728   * - Streaming                 : audioconvert !volume ! audiosink
2729   * - PCM extraction    : audioconvert ! audioresample ! capsfilter ! fakesink 
2730   */
2731 static int
2732 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
2733 {
2734         MMPlayerGstElement* first_element = NULL;
2735         MMPlayerGstElement* audiobin = NULL;
2736         MMHandleType attrs = 0;
2737         GstPad *pad = NULL;
2738         GstPad *ghostpad = NULL;
2739         GList* element_bucket = NULL;
2740         char *device_name = NULL;
2741         gboolean link_audio_sink_now = TRUE;
2742         int i =0;
2743
2744         debug_fenter();
2745
2746         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
2747
2748         /* alloc handles */
2749         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
2750         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
2751         if ( ! audiobin )
2752         {
2753                 debug_error("failed to allocate memory for audiobin\n");
2754                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
2755         }
2756
2757         attrs = MMPLAYER_GET_ATTRS(player);
2758
2759         /* create bin */
2760         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
2761         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
2762         if ( !audiobin[MMPLAYER_A_BIN].gst )
2763         {
2764                 debug_critical("failed to create audiobin\n");
2765                 goto ERROR;
2766         }
2767
2768         /* take it */
2769         player->pipeline->audiobin = audiobin;
2770
2771         player->is_sound_extraction = __mmplayer_can_extract_pcm(player);
2772
2773         /* Adding audiotp plugin for reverse trickplay feature */
2774         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audiotrickplay", TRUE);
2775
2776         /* converter */
2777         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audioconverter", TRUE);
2778
2779         if ( ! player->is_sound_extraction )
2780         {
2781                 GstCaps* caps = NULL;
2782
2783                 /* for logical volume control */
2784                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE);
2785                 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
2786
2787                 if (player->sound.mute)
2788                 {
2789                         debug_log("mute enabled\n");
2790                         g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
2791                 }
2792
2793                 /*capsfilter */
2794                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE);
2795
2796                 caps = gst_caps_from_string(            "audio/x-raw-int, "
2797                                                                                 "endianness = (int) LITTLE_ENDIAN, "
2798                                                                                 "signed = (boolean) true, "
2799                                                                                 "width = (int) 16, "
2800                                                                                 "depth = (int) 16"      );
2801
2802                 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
2803
2804                 gst_caps_unref( caps );
2805
2806                 /* audio filter. if enabled */
2807                 if ( PLAYER_INI()->use_audio_filter_preset || PLAYER_INI()->use_audio_filter_custom )
2808                 {
2809                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, "soundalive", "audiofilter", TRUE);
2810                 }
2811
2812                 /* create audio sink */
2813                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, PLAYER_INI()->name_of_audiosink,
2814                         "audiosink", link_audio_sink_now);
2815
2816                 /* sync on */
2817                 if (MMPLAYER_IS_RTSP_STREAMING(player))
2818                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);   /* sync off */
2819                 else
2820                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", TRUE, NULL);    /* sync on */
2821
2822                 /* qos on */
2823                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);     /* qos on */
2824
2825                 /* FIXIT : using system clock. isn't there another way? */
2826                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", PLAYER_INI()->provide_clock,  NULL);
2827
2828                 __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
2829
2830                 if(player->audio_buffer_cb)
2831                 {
2832                     g_object_set(audiobin[MMPLAYER_A_SINK].gst, "audio-handle", player->audio_buffer_cb_user_param, NULL);
2833                     g_object_set(audiobin[MMPLAYER_A_SINK].gst, "audio-callback", player->audio_buffer_cb, NULL);
2834                 }
2835
2836                 if ( g_strrstr(PLAYER_INI()->name_of_audiosink, "avsysaudiosink") )
2837                 {
2838                         gint volume_type = 0;
2839                         gint audio_route = 0;
2840                         gint sound_priority = FALSE;
2841                         gint is_spk_out_only = 0;
2842
2843                         /* set volume table
2844                          * It should be set after player creation through attribute.
2845                          * But, it can not be changed during playing.
2846                          */
2847                         mm_attrs_get_int_by_name(attrs, "sound_volume_type", &volume_type);
2848                         mm_attrs_get_int_by_name(attrs, "sound_route", &audio_route);
2849                         mm_attrs_get_int_by_name(attrs, "sound_priority", &sound_priority);
2850                         mm_attrs_get_int_by_name(attrs, "sound_spk_out_only", &is_spk_out_only);
2851
2852                         /* hook sound_type if emergency case */
2853                         if ( player->sm.event == ASM_EVENT_EMERGENCY)
2854                         {
2855                                 debug_log ("This is emergency session, hook sound_type from [%d] to [%d]\n", volume_type, MM_SOUND_VOLUME_TYPE_EMERGENCY);
2856                                 volume_type = MM_SOUND_VOLUME_TYPE_EMERGENCY;
2857                         }
2858
2859                         g_object_set(audiobin[MMPLAYER_A_SINK].gst,
2860                                                                 "volumetype", volume_type,
2861                                                                 "audio-route", audio_route,
2862                                                                 "priority", sound_priority,
2863                                                                 "user-route", is_spk_out_only,
2864                                                                 NULL);
2865
2866                         debug_log("audiosink property status...volume type:%d, route:%d, priority=%d, user-route=%d\n",
2867                                 volume_type, audio_route, sound_priority, is_spk_out_only);
2868                 }
2869
2870                 /* Antishock can be enabled when player is resumed by soundCM.
2871                  * But, it's not used in MMS, setting and etc.
2872                  * Because, player start seems like late.
2873                  */
2874                 __mmplayer_set_antishock( player , FALSE );
2875         }
2876         else // pcm extraction only and no sound output 
2877         {
2878                 int dst_samplerate = 0;
2879                 int dst_channels = 0;
2880                 int dst_depth = 0;
2881                 char *caps_type = NULL;
2882                 GstCaps* caps = NULL;
2883
2884                 /* resampler */
2885                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER, "audioresample", "resampler", TRUE);
2886
2887                 /* get conf. values */
2888                 mm_attrs_multiple_get(player->attrs, 
2889                                                 NULL,
2890                                                 "pcm_extraction_samplerate", &dst_samplerate,
2891                                                 "pcm_extraction_channels", &dst_channels,
2892                                                 "pcm_extraction_depth", &dst_depth,
2893                                                 NULL);
2894                 /* capsfilter */
2895                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE);
2896
2897                 caps = gst_caps_new_simple ("audio/x-raw-int",
2898                                                "rate", G_TYPE_INT, dst_samplerate,
2899                                                "channels", G_TYPE_INT, dst_channels,
2900                                                "depth", G_TYPE_INT, dst_depth,
2901                                                 NULL);
2902
2903                 caps_type = gst_caps_to_string(caps);
2904                 debug_log("resampler new caps : %s\n", caps_type);
2905
2906                         g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
2907
2908                         /* clean */
2909                         gst_caps_unref( caps );
2910                         MMPLAYER_FREEIF( caps_type );
2911
2912                 /* fake sink */
2913                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE);
2914
2915                 /* set sync */
2916                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
2917
2918                 __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
2919         }
2920
2921         /* adding created elements to bin */
2922         debug_log("adding created elements to bin\n");
2923         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket ))
2924         {
2925                 debug_error("failed to add elements\n");
2926                 goto ERROR;
2927         }
2928
2929         /* linking elements in the bucket by added order. */
2930         debug_log("Linking elements in the bucket by added order.\n");
2931         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
2932         {
2933                 debug_error("failed to link elements\n");
2934                 goto ERROR;
2935         }
2936
2937         /* get first element's sinkpad for creating ghostpad */
2938         first_element = (MMPlayerGstElement *)element_bucket->data;
2939
2940         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
2941         if ( ! pad )
2942         {
2943                 debug_error("failed to get pad from first element of audiobin\n");
2944                 goto ERROR;
2945         }
2946
2947         ghostpad = gst_ghost_pad_new("sink", pad);
2948         if ( ! ghostpad )
2949         {
2950                 debug_error("failed to create ghostpad\n");
2951                 goto ERROR;
2952         }
2953
2954         if ( FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad) )
2955         {
2956                 debug_error("failed to add ghostpad to audiobin\n");
2957                 goto ERROR;
2958         }
2959
2960         gst_object_unref(pad);
2961
2962         if ( !player->bypass_sound_effect && (PLAYER_INI()->use_audio_filter_preset || PLAYER_INI()->use_audio_filter_custom) )
2963         {
2964                 if ( player->audio_filter_info.filter_type == MM_AUDIO_FILTER_TYPE_PRESET )
2965                 {
2966                         if (!_mmplayer_sound_filter_preset_apply(player, player->audio_filter_info.preset))
2967                         {
2968                                 debug_msg("apply sound effect(preset:%d) setting success\n",player->audio_filter_info.preset);
2969                         }
2970                 }
2971                 else if ( player->audio_filter_info.filter_type == MM_AUDIO_FILTER_TYPE_CUSTOM )
2972                 {
2973                         if (!_mmplayer_sound_filter_custom_apply(player))
2974                         {
2975                                 debug_msg("apply sound effect(custom) setting success\n");
2976                         }
2977                 }
2978         }
2979
2980         /* done. free allocated variables */
2981         MMPLAYER_FREEIF( device_name );
2982         g_list_free(element_bucket);
2983
2984         mm_attrs_set_int_by_name(attrs, "content_audio_found", TRUE);
2985         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
2986                 debug_error("failed to commit attribute ""content_audio_found"".\n");
2987
2988         debug_fleave();
2989
2990         return MM_ERROR_NONE;
2991
2992 ERROR:
2993
2994         debug_log("ERROR : releasing audiobin\n");
2995
2996         MMPLAYER_FREEIF( device_name );
2997
2998         if ( pad )
2999                 gst_object_unref(GST_OBJECT(pad));
3000
3001         if ( ghostpad )
3002                 gst_object_unref(GST_OBJECT(ghostpad));
3003
3004         g_list_free( element_bucket );
3005
3006
3007         /* release element which are not added to bin */
3008         for ( i = 1; i < MMPLAYER_A_NUM; i++ )  /* NOTE : skip bin */
3009         {
3010                 if ( audiobin[i].gst )
3011                 {
3012                         GstObject* parent = NULL;
3013                         parent = gst_element_get_parent( audiobin[i].gst );
3014
3015                         if ( !parent )
3016                         {
3017                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
3018                                 audiobin[i].gst = NULL;
3019                         }
3020                         else
3021                         {
3022                                 gst_object_unref(GST_OBJECT(parent));
3023                         }
3024                 }
3025         }
3026
3027         /* release audiobin with it's childs */
3028         if ( audiobin[MMPLAYER_A_BIN].gst )
3029         {
3030                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
3031         }
3032
3033         MMPLAYER_FREEIF( audiobin );
3034
3035         player->pipeline->audiobin = NULL;
3036
3037         return MM_ERROR_PLAYER_INTERNAL;
3038 }
3039
3040 static gboolean
3041 __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data)
3042 {
3043         mm_player_t* player = (mm_player_t*) u_data;
3044         gint size;
3045         guint8 *data;
3046
3047         data = GST_BUFFER_DATA(buffer);
3048         size = GST_BUFFER_SIZE(buffer);
3049
3050         if (player->audio_stream_cb && size && data)
3051                 player->audio_stream_cb((void *)data, size, player->audio_stream_cb_user_param);
3052
3053         return TRUE;
3054 }
3055
3056 gboolean
3057 __mmplayer_ahs_appsrc_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data)
3058 {       
3059         mm_player_t* player = (mm_player_t*) u_data;
3060
3061         //g_print ("appsrc buf : timestamp = %"GST_TIME_FORMAT", duration = %"GST_TIME_FORMAT"\n", 
3062         //      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (GST_BUFFER_DURATION(buffer)));
3063
3064         if (ahs_check_allow_cache (player->ahs_player))
3065         {
3066                 ahs_store_media_presentation (player->ahs_player, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
3067         }
3068         return TRUE;
3069 }
3070
3071 /**
3072  * This function is to create video pipeline.
3073  *
3074  * @param       player          [in]    handle of player
3075  *              caps            [in]    src caps of decoder
3076  *              surface_type    [in]    surface type for video rendering
3077  *
3078  * @return      This function returns zero on success.
3079  * @remark
3080  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
3081  */
3082 /**
3083   * VIDEO PIPELINE
3084   * - x surface (arm/x86) : xvimagesink
3085   * - evas surface  (arm) : ffmpegcolorspace ! evasimagesink
3086   * - evas surface  (x86) : videoconvertor ! evasimagesink
3087   */
3088 static int
3089 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
3090 {
3091         GstPad *pad = NULL;
3092         MMHandleType attrs;
3093         GList*element_bucket = NULL;
3094         MMPlayerGstElement* first_element = NULL;
3095         MMPlayerGstElement* videobin = NULL;
3096         gchar* vconv_factory = NULL;
3097         gchar *videosink_element = NULL;
3098
3099         debug_fenter();
3100
3101         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3102
3103         /* alloc handles */
3104         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
3105         if ( !videobin )
3106                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
3107
3108         player->pipeline->videobin = videobin;
3109
3110         attrs = MMPLAYER_GET_ATTRS(player);
3111
3112         /* create bin */
3113         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
3114         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
3115         if ( !videobin[MMPLAYER_V_BIN].gst )
3116         {
3117                 debug_critical("failed to create videobin");
3118                 goto ERROR;
3119         }
3120
3121         if( player->use_video_stream ) // video stream callack, so send raw video data to application
3122         {
3123                 GstStructure *str = NULL;
3124                 guint32 fourcc = 0;
3125                 gint ret = 0;
3126
3127                 debug_log("using memsink\n");
3128
3129                 /* first, create colorspace convert */
3130                 if (strlen(PLAYER_INI()->name_of_video_converter) > 0)
3131                 {
3132                                 vconv_factory = PLAYER_INI()->name_of_video_converter;
3133                 }
3134
3135                 if (vconv_factory)
3136                 {
3137                         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_CONV, vconv_factory, "video converter", TRUE);
3138                 }
3139                 
3140                 /* then, create video scale to resize if needed */
3141                 str = gst_caps_get_structure (caps, 0);
3142
3143                 if ( ! str )
3144                 {
3145                         debug_error("cannot get structure\n");
3146                         goto ERROR;
3147                 }
3148
3149                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3150
3151                 ret = gst_structure_get_fourcc (str, "format", &fourcc);
3152
3153                 if ( !ret )
3154                         debug_log("not fixed format at this point, and not consider this case\n")
3155
3156                 /* NOTE :  if the width of I420 format is not multiple of 8, it should be resize before colorspace conversion.
3157                   * so, video scale is required for this case only.
3158                   */
3159                 if ( GST_MAKE_FOURCC ('I', '4', '2', '0') == fourcc )
3160                 {
3161                         gint width = 0;                         //width of video
3162                         gint height = 0;                        //height of video
3163                         gint framerate_n = 0;           //numerator of frame rate
3164                         gint framerate_d = 0;           //denominator of frame rate
3165                         GstCaps* video_caps = NULL;
3166                         GValue *fps = NULL;
3167
3168                         /* video scale  */
3169                         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SCALE, "videoscale", "videoscale", TRUE);
3170
3171                         /*to limit width as multiple of 8 */
3172                         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_CAPS, "capsfilter", "videocapsfilter", TRUE);
3173
3174                         /* get video stream caps parsed by demuxer */
3175                         str = gst_caps_get_structure (player->v_stream_caps, 0);
3176                         if ( ! str )
3177                         {
3178                                 debug_error("cannot get structure\n");
3179                                 goto ERROR;
3180                         }
3181
3182                         /* check the width if it's a multiple of 8 or not */
3183                         ret = gst_structure_get_int (str, "width", &width);
3184                         if ( ! ret )
3185                         {
3186                                 debug_error("cannot get width\n");
3187                                 goto ERROR;
3188                         }
3189                         width = GST_ROUND_UP_8(width);
3190
3191                         ret = gst_structure_get_int(str, "height", &height);
3192                         if ( ! ret )
3193                         {
3194                                 debug_error("cannot get height\n");
3195                                 goto ERROR;
3196                         }
3197
3198                         fps = gst_structure_get_value (str, "framerate");
3199                         if ( ! fps )
3200                         {
3201                                 debug_error("cannot get fps\n");
3202                                 goto ERROR;
3203                         }
3204                         framerate_n = gst_value_get_fraction_numerator (fps);
3205                         framerate_d = gst_value_get_fraction_denominator (fps);
3206
3207                         video_caps = gst_caps_new_simple( "video/x-raw-yuv",
3208                                                                                         "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
3209                                                                                         "width", G_TYPE_INT, width,
3210                                                                                         "height", G_TYPE_INT, height,
3211                                                                                         "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
3212                                                                                         NULL);
3213
3214                         g_object_set (GST_ELEMENT(videobin[MMPLAYER_V_CAPS].gst), "caps", video_caps, NULL );
3215
3216                         gst_caps_unref( video_caps );
3217                 }
3218
3219                 /* finally, create video sink. its oupput should be BGRX8888 for application like cario surface. */
3220                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, "avsysmemsink", "videosink", TRUE);
3221
3222                 MMPLAYER_SIGNAL_CONNECT( player,
3223                                                                          videobin[MMPLAYER_V_SINK].gst,
3224                                                                          "video-stream",
3225                                                                          G_CALLBACK(__mmplayer_videostream_cb),
3226                                                                          player );
3227         }
3228         else // render video data using sink pugin like xvimagesink
3229         {
3230                 debug_log("using videosink");
3231                 
3232                 /*set video converter */
3233                 if (strlen(PLAYER_INI()->name_of_video_converter) > 0)
3234                 {
3235                         vconv_factory = PLAYER_INI()->name_of_video_converter;
3236                         if (vconv_factory)
3237                         {
3238                                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_CONV, vconv_factory, "video converter", TRUE);
3239                                 debug_log("using video converter: %s", vconv_factory);
3240                         }
3241                 }
3242
3243                 /* videoscaler */ /* NOTE : ini parsing method seems to be more suitable rather than define method */
3244                 #if !defined(__arm__)
3245                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SCALE, "videoscale", "videoscaler", TRUE);
3246                 #endif
3247
3248                 /* set video sink */
3249                 switch (surface_type)
3250                 {
3251                 case MM_DISPLAY_SURFACE_X:
3252                         if (strlen(PLAYER_INI()->videosink_element_x) > 0)
3253                                 videosink_element = PLAYER_INI()->videosink_element_x;
3254                         else
3255                                 goto ERROR;
3256                         break;
3257                 case MM_DISPLAY_SURFACE_EVAS:
3258                         if (strlen(PLAYER_INI()->videosink_element_evas) > 0)
3259                                 videosink_element = PLAYER_INI()->videosink_element_evas;
3260                         else
3261                                 goto ERROR;
3262                         break;
3263                 case MM_DISPLAY_SURFACE_X_EXT:
3264                 {
3265                         void *pixmap_id_cb = NULL;
3266                         mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
3267                         if (pixmap_id_cb) /* this is for the video textue(canvas texture) */
3268                         {
3269                                 videosink_element = PLAYER_INI()->videosink_element_x;
3270                                 debug_warning("video texture usage");
3271                         }
3272                         else
3273                         {
3274                                 debug_error("something wrong.. callback function for getting pixmap id is null");
3275                                 goto ERROR;
3276                         }
3277                         break;
3278                 }
3279                 case MM_DISPLAY_SURFACE_NULL:
3280                         if (strlen(PLAYER_INI()->videosink_element_fake) > 0)
3281                                 videosink_element = PLAYER_INI()->videosink_element_fake;
3282                         else
3283                                 goto ERROR;
3284                         break;
3285                 default:
3286                         debug_error("unidentified surface type");
3287                         goto ERROR;
3288                 }
3289
3290                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, videosink_element, TRUE);
3291                 debug_log("selected videosink name: %s", videosink_element);
3292         }
3293
3294         if ( _mmplayer_update_video_param(player) != MM_ERROR_NONE)
3295                 goto ERROR;
3296
3297         /* qos on */
3298         g_object_set (G_OBJECT (videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
3299
3300         /* store it as it's sink element */
3301         __mmplayer_add_sink( player, videobin[MMPLAYER_V_SINK].gst );
3302
3303         /* adding created elements to bin */
3304         if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket) )
3305         {
3306                 debug_error("failed to add elements\n");
3307                 goto ERROR;
3308         }
3309
3310         /* Linking elements in the bucket by added order */
3311         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
3312         {
3313                 debug_error("failed to link elements\n");
3314                 goto ERROR;
3315         }
3316
3317         /* get first element's sinkpad for creating ghostpad */
3318         first_element = (MMPlayerGstElement *)element_bucket->data;
3319         if ( !first_element )
3320         {
3321                 debug_error("failed to get first element from bucket\n");
3322                 goto ERROR;
3323         }
3324
3325         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
3326         if ( !pad )
3327         {
3328                 debug_error("failed to get pad from first element\n");
3329                 goto ERROR;
3330         }
3331
3332         /* create ghostpad */
3333         if ( FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, gst_ghost_pad_new("sink", pad)) )
3334         {
3335                 debug_error("failed to add ghostpad to videobin\n");
3336                 goto ERROR;
3337         }
3338         gst_object_unref(pad);
3339
3340         /* done. free allocated variables */
3341         g_list_free(element_bucket);
3342
3343         mm_attrs_set_int_by_name(attrs, "content_video_found", TRUE);
3344         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
3345                 debug_error("failed to commit attribute ""content_video_found"".\n");
3346
3347         debug_fleave();
3348
3349         return MM_ERROR_NONE;
3350
3351 ERROR:
3352         debug_error("ERROR : releasing videobin\n");
3353
3354         g_list_free( element_bucket );
3355
3356         if (pad)
3357                 gst_object_unref(GST_OBJECT(pad));
3358
3359         /* release videobin with it's childs */
3360         if ( videobin[MMPLAYER_V_BIN].gst )
3361         {
3362                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
3363         }
3364
3365
3366         MMPLAYER_FREEIF( videobin );
3367
3368         player->pipeline->videobin = NULL;
3369
3370         return MM_ERROR_PLAYER_INTERNAL;
3371 }
3372
3373 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player)
3374 {
3375         MMPlayerGstElement* first_element = NULL;
3376         MMPlayerGstElement* textbin = NULL;
3377         GList* element_bucket = NULL;
3378         GstPad *pad = NULL;
3379         GstPad *ghostpad = NULL;
3380         gint i = 0;
3381
3382         debug_fenter();
3383
3384         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3385
3386         /* alloc handles */
3387         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
3388         if ( ! textbin )
3389         {
3390                 debug_error("failed to allocate memory for textbin\n");
3391                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
3392         }
3393
3394         /* create bin */
3395         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
3396         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
3397         if ( !textbin[MMPLAYER_T_BIN].gst )
3398         {
3399                 debug_critical("failed to create textbin\n");
3400                 goto ERROR;
3401         }
3402
3403         /* take it */
3404         player->pipeline->textbin = textbin;
3405
3406         /* fakesink */
3407         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_SINK, "fakesink", "text_sink", TRUE);
3408
3409         g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "sync", TRUE, NULL);
3410         g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "async", FALSE, NULL);
3411         g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "signal-handoffs", TRUE, NULL);
3412
3413         MMPLAYER_SIGNAL_CONNECT( player,
3414                                                         G_OBJECT(textbin[MMPLAYER_T_SINK].gst),
3415                                                         "handoff",
3416                                                         G_CALLBACK(__mmplayer_update_subtitle),
3417                                                         (gpointer)player );
3418
3419         __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_SINK].gst));
3420
3421         /* adding created elements to bin */
3422         debug_log("adding created elements to bin\n");
3423         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
3424         {
3425                 debug_error("failed to add elements\n");
3426                 goto ERROR;
3427         }
3428
3429         /* linking elements in the bucket by added order. */
3430         debug_log("Linking elements in the bucket by added order.\n");
3431         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
3432         {
3433                 debug_error("failed to link elements\n");
3434                 goto ERROR;
3435         }
3436
3437         /* get first element's sinkpad for creating ghostpad */
3438         first_element = (MMPlayerGstElement *)element_bucket->data;
3439
3440         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
3441         if ( ! pad )
3442         {
3443                 debug_error("failed to get pad from first element of textbin\n");
3444                 goto ERROR;
3445         }
3446
3447         ghostpad = gst_ghost_pad_new("sink", pad);
3448         if ( ! ghostpad )
3449         {
3450                 debug_error("failed to create ghostpad\n");
3451                 goto ERROR;
3452         }
3453
3454         if ( FALSE == gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad) )
3455         {
3456                 debug_error("failed to add ghostpad to textbin\n");
3457                 goto ERROR;
3458         }
3459
3460         gst_object_unref(pad);
3461
3462
3463         /* done. free allocated variables */
3464         g_list_free(element_bucket);
3465
3466         debug_fleave();
3467
3468         return MM_ERROR_NONE;
3469
3470 ERROR:
3471
3472         debug_log("ERROR : releasing textbin\n");
3473
3474         if ( pad )
3475                 gst_object_unref(GST_OBJECT(pad));
3476
3477         if ( ghostpad )
3478                 gst_object_unref(GST_OBJECT(ghostpad));
3479
3480         g_list_free( element_bucket );
3481
3482
3483         /* release element which are not added to bin */
3484         for ( i = 1; i < MMPLAYER_T_NUM; i++ )  /* NOTE : skip bin */
3485         {
3486                 if ( textbin[i].gst )
3487                 {
3488                         GstObject* parent = NULL;
3489                         parent = gst_element_get_parent( textbin[i].gst );
3490
3491                         if ( !parent )
3492                         {
3493                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
3494                                 textbin[i].gst = NULL;
3495                         }
3496                         else
3497                         {
3498                                 gst_object_unref(GST_OBJECT(parent));
3499                         }
3500                 }
3501         }
3502
3503         /* release textbin with it's childs */
3504         if ( textbin[MMPLAYER_T_BIN].gst )
3505         {
3506                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
3507         }
3508
3509         MMPLAYER_FREEIF( textbin );
3510
3511         player->pipeline->textbin = NULL;
3512
3513         return MM_ERROR_PLAYER_INTERNAL;
3514 }
3515
3516
3517 static int
3518 __mmplayer_gst_create_subtitle_pipeline(mm_player_t* player)
3519 {
3520         MMPlayerGstElement* subtitlebin = NULL;
3521         MMHandleType attrs = 0;
3522         gchar *subtitle_uri =NULL;
3523         GList*element_bucket = NULL;
3524
3525         #define USE_MESSAGE_FOR_PLAYING_SUBTITLE 
3526 #ifndef USE_MESSAGE_FOR_PLAYING_SUBTITLE
3527         void *xid = NULL;
3528         gint width =0, height = 0;
3529         gboolean silent=FALSE;
3530 #endif
3531
3532         debug_fenter();
3533
3534         /* get mainbin */
3535         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3536
3537         attrs = MMPLAYER_GET_ATTRS(player);
3538         if ( !attrs )
3539         {
3540                 debug_error("cannot get content attribute\n");
3541                 return MM_ERROR_PLAYER_INTERNAL;
3542         }
3543
3544         mm_attrs_get_string_by_name ( attrs, "subtitle_uri", &subtitle_uri );
3545         if ( !subtitle_uri || strlen(subtitle_uri) < 1)
3546         {
3547                 debug_error("subtitle uri is not proper filepath.\n");
3548                 return MM_ERROR_PLAYER_INVALID_URI;     
3549         }
3550         debug_log("subtitle file path is [%s].\n", subtitle_uri);
3551
3552
3553         /* alloc handles */
3554         subtitlebin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_SUB_NUM);
3555         if ( !subtitlebin )
3556         {
3557                 debug_error("failed to allocate memory\n");
3558                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
3559         }
3560
3561         /* create bin */
3562         subtitlebin[MMPLAYER_SUB_PIPE].id = MMPLAYER_SUB_PIPE;
3563         subtitlebin[MMPLAYER_SUB_PIPE].gst = gst_pipeline_new("subtitlebin");
3564         if ( !subtitlebin[MMPLAYER_SUB_PIPE].gst )
3565         {
3566                 debug_error("failed to create text pipeline\n");
3567                 goto ERROR;
3568         }
3569         player->pipeline->subtitlebin = subtitlebin;
3570
3571         /* create the text file source */
3572         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SRC, "filesrc", "subtitle_source", TRUE);
3573         g_object_set(G_OBJECT (subtitlebin[MMPLAYER_SUB_SRC].gst), "location", subtitle_uri, NULL);
3574
3575         /* queue */
3576         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_QUEUE, "queue", NULL, TRUE);
3577
3578         /* subparse */
3579         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SUBPARSE, "subparse", "subtitle_parser", TRUE);
3580
3581 #ifndef USE_MESSAGE_FOR_PLAYING_SUBTITLE
3582         /* textrender */
3583         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_TEXTRENDER, "textrender", "subtitle_render", TRUE);
3584
3585         mm_attrs_get_int_by_name(attrs,"width", &width);
3586         mm_attrs_get_int_by_name(attrs,"height", &height);
3587         mm_attrs_get_int_by_name(attrs,"silent", &silent);
3588         g_object_set ( G_OBJECT (subtitlebin[MMPLAYER_SUB_TEXTRENDER].gst),"width", width, NULL);
3589         g_object_set ( G_OBJECT (subtitlebin[MMPLAYER_SUB_TEXTRENDER].gst),"height", height, NULL);
3590         g_object_set ( G_OBJECT (subtitlebin[MMPLAYER_SUB_TEXTRENDER].gst),"silent", silent, NULL);
3591
3592         debug_log ( "subtitle winow size is [%dX%d].\n", width, height );
3593         debug_log ( "subtitle silent is [%d].\n", silent );
3594
3595         /* converter1 */
3596         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_CONV1, "ffmpegcolorspace", "subtitle_converter1", TRUE);
3597
3598         /* videofliper */
3599         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_FLIP, "videoflip", "subtitle_fliper", TRUE);
3600
3601         /* converter2 */
3602         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_CONV2, "ffmpegcolorspace", "subtitle_converter2", TRUE);
3603
3604         /* text sink */
3605         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SINK, "ximagesink", "subtitle_sink", TRUE);
3606
3607         mm_attrs_get_data_by_name(attrs, "xid", &xid);
3608         if ( xid )
3609         {
3610                 debug_log("setting subtitle xid = %d\n", *(int*)xid);
3611                 gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(subtitlebin[MMPLAYER_SUB_SINK].gst), *(int*)xid);
3612         }
3613         else
3614         {
3615                 /* FIXIT : is it error case? */
3616                 debug_warning("still we don't have xid on player attribute. create it's own surface.\n");
3617         }
3618 #else
3619         /* text sink */
3620         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SINK, "fakesink", "subtitle_sink", TRUE);
3621
3622         g_object_set (G_OBJECT (subtitlebin[MMPLAYER_SUB_SINK].gst), "sync", TRUE, NULL);
3623         g_object_set (G_OBJECT (subtitlebin[MMPLAYER_SUB_SINK].gst), "async", FALSE, NULL);
3624         g_object_set (G_OBJECT (subtitlebin[MMPLAYER_SUB_SINK].gst), "signal-handoffs", TRUE, NULL);
3625
3626         MMPLAYER_SIGNAL_CONNECT( player,
3627                                                         G_OBJECT(subtitlebin[MMPLAYER_SUB_SINK].gst),
3628                                                         "handoff",
3629                                                         G_CALLBACK(__mmplayer_update_subtitle),
3630                                                         (gpointer)player );
3631 #endif
3632
3633         /* adding created elements to bin */
3634         if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(subtitlebin[MMPLAYER_SUB_PIPE].gst), element_bucket) )
3635         {
3636                 debug_error("failed to add elements\n");
3637                 goto ERROR;
3638         }
3639
3640         /* Linking elements in the bucket by added order */
3641         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
3642         {
3643                 debug_error("failed to link elements\n");
3644                 goto ERROR;
3645         }
3646
3647         /* done. free allocated variables */
3648         g_list_free(element_bucket);
3649
3650         player->play_subtitle = TRUE;
3651
3652         debug_fleave();
3653         
3654         return MM_ERROR_NONE;
3655
3656
3657 ERROR:
3658         debug_error("ERROR : releasing text pipeline\n");
3659
3660         g_list_free( element_bucket );
3661
3662         /* release subtitlebin with it's childs */
3663         if ( subtitlebin[MMPLAYER_SUB_PIPE].gst )
3664         {
3665                 gst_object_unref(GST_OBJECT(subtitlebin[MMPLAYER_SUB_PIPE].gst));
3666         }
3667
3668         MMPLAYER_FREEIF( subtitlebin );
3669
3670         player->pipeline->subtitlebin = NULL;
3671
3672         return MM_ERROR_PLAYER_INTERNAL;
3673 }
3674
3675 gboolean
3676 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
3677 {
3678         mm_player_t* player = (mm_player_t*) data;
3679         MMMessageParamType msg = {0, };
3680         GstClockTime duration = 0;
3681         guint8 *text = NULL;
3682         gboolean ret = TRUE;
3683
3684         debug_fenter();
3685
3686         return_val_if_fail ( player, FALSE );
3687         return_val_if_fail ( buffer, FALSE );
3688
3689         text = GST_BUFFER_DATA(buffer);
3690         duration = GST_BUFFER_DURATION(buffer);
3691
3692         if ( player->is_subtitle_off )
3693         {
3694                 debug_log("subtitle is OFF.\n" );
3695                 return TRUE;
3696         }
3697
3698         if ( !text )
3699         {
3700                 debug_log("There is no subtitle to be displayed.\n" );
3701                 return TRUE;
3702         }
3703
3704         msg.data = (void *) text;
3705         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
3706
3707         debug_warning("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
3708
3709         MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
3710
3711         debug_fleave();
3712
3713         return ret;
3714 }
3715
3716
3717 static int      __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
3718 {
3719         GstEvent* event = NULL;
3720         gint64 current_pos = 0;
3721         gint64 adusted_pos = 0;
3722         gboolean ret = TRUE;
3723
3724         debug_fenter();
3725
3726         /* check player and subtitlebin are created */
3727         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3728         return_val_if_fail ( MMPLAYER_PLAY_SUBTITLE(player),    MM_ERROR_PLAYER_NOT_INITIALIZED );
3729
3730         if (position == 0)
3731         {
3732                 debug_log("adjusted values is 0, no need to adjust subtitle position.\n");
3733                 return MM_ERROR_NONE;
3734         }
3735
3736         switch (format)
3737         {
3738                 case MM_PLAYER_POS_FORMAT_TIME:
3739                 {
3740                         /* check current postion */
3741                         ret = gst_element_query_position( GST_ELEMENT(player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst), &format, &current_pos );
3742                         if ( !ret )
3743                         {
3744                                 debug_warning("fail to query current postion.\n");
3745                                 return MM_ERROR_PLAYER_SEEK;
3746                         }
3747                         else
3748                         {
3749                                 adusted_pos = current_pos + ((gint64)position * G_GINT64_CONSTANT(1000000));
3750                                 if (adusted_pos < 0)
3751                                         adusted_pos = G_GINT64_CONSTANT(0);
3752                                 debug_log("adjust subtitle postion : %lu -> %lu [msec]\n", GST_TIME_AS_MSECONDS(current_pos), GST_TIME_AS_MSECONDS(adusted_pos));
3753                         }
3754
3755                         event = gst_event_new_seek (1.0,        GST_FORMAT_TIME,
3756                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3757                                         GST_SEEK_TYPE_SET, adusted_pos,
3758                                         GST_SEEK_TYPE_SET, -1);
3759                 }
3760                 break;
3761
3762                 case MM_PLAYER_POS_FORMAT_PERCENT:
3763                 {
3764                         debug_warning("percent format is not supported yet.\n");
3765                         return MM_ERROR_INVALID_ARGUMENT;
3766                 }
3767                 break;
3768
3769                 default:
3770                 {
3771                         debug_warning("invalid format.\n");
3772                         return MM_ERROR_INVALID_ARGUMENT;
3773                 }
3774         }
3775
3776         /* keep ref to the event */
3777         gst_event_ref (event);
3778
3779         debug_log("sending event[%s] to sink element [%s]\n",
3780                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst) );
3781
3782         if ( ret = gst_element_send_event (player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst, event) )
3783         {
3784                 debug_log("sending event[%s] to sink element [%s] success!\n",
3785                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst) );
3786         }
3787
3788         /* unref to the event */
3789         gst_event_unref (event);
3790
3791
3792         debug_fleave();
3793
3794         return MM_ERROR_NONE;
3795
3796 }
3797
3798 static void
3799 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data) // @
3800 {
3801         GstElement *appsrc = element;
3802         tBuffer *buf = (tBuffer *)user_data;
3803         GstBuffer *buffer = NULL;
3804         GstFlowReturn ret = GST_FLOW_OK;
3805         gint len = size;
3806
3807         return_if_fail ( element );
3808         return_if_fail ( buf );
3809
3810         buffer = gst_buffer_new ();
3811
3812         if (buf->offset >= buf->len)
3813         {
3814                 debug_log("call eos appsrc\n");
3815                g_signal_emit_by_name (appsrc, "end-of-stream", &ret);
3816                return;
3817         }
3818
3819         if ( buf->len - buf->offset < size)
3820         {
3821                 len = buf->len - buf->offset + buf->offset;
3822         }
3823
3824         GST_BUFFER_DATA(buffer) = (guint8*)(buf->buf + buf->offset);
3825         GST_BUFFER_SIZE(buffer) = len;
3826         GST_BUFFER_OFFSET(buffer) = buf->offset;
3827         GST_BUFFER_OFFSET_END(buffer) = buf->offset + len;
3828
3829         debug_log("feed buffer %p, offset %u-%u length %u\n", buffer, buf->offset, buf->len,len);
3830         g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
3831
3832         buf->offset += len;
3833 }
3834
3835 static gboolean
3836 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data) // @
3837 {
3838         tBuffer *buf = (tBuffer *)user_data;
3839
3840         return_val_if_fail ( buf, FALSE );
3841
3842         buf->offset  = (int)size;
3843
3844         return TRUE;
3845 }
3846
3847 static void
3848 __gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data) // @
3849 {
3850        mm_player_t *player  = (mm_player_t*)user_data;
3851
3852         return_if_fail ( player );
3853
3854         debug_msg("app-src: feed data\n");
3855              
3856         if(player->need_data_cb)
3857                 player->need_data_cb(size, player->buffer_cb_user_param);
3858 }
3859
3860 static gboolean
3861 __gst_appsrc_seek_data(GstElement *element, guint64 offset, gpointer user_data) // @
3862 {
3863         mm_player_t *player  = (mm_player_t*)user_data;
3864
3865         return_val_if_fail ( player, FALSE );
3866
3867         debug_msg("app-src: seek data\n");
3868
3869         if(player->seek_data_cb)
3870                 player->seek_data_cb(offset, player->buffer_cb_user_param);
3871
3872         return TRUE;
3873 }
3874
3875
3876 static gboolean
3877 __gst_appsrc_enough_data(GstElement *element, gpointer user_data) // @
3878 {
3879         mm_player_t *player  = (mm_player_t*)user_data;
3880
3881         return_val_if_fail ( player, FALSE );
3882
3883         debug_msg("app-src: enough data:%p\n", player->enough_data_cb);
3884         
3885         if(player->enough_data_cb)
3886                 player->enough_data_cb(player->buffer_cb_user_param);
3887
3888         return TRUE;
3889 }
3890
3891 int
3892 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
3893 {
3894         mm_player_t* player = (mm_player_t*)hplayer;
3895         GstBuffer *buffer = NULL;
3896         GstFlowReturn gst_ret = GST_FLOW_OK;
3897         int ret = MM_ERROR_NONE;
3898
3899         debug_fenter();
3900
3901         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3902
3903         /* check current state */
3904 //      MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
3905
3906
3907         /* NOTE : we should check and create pipeline again if not created as we destroy
3908          * whole pipeline when stopping in streamming playback
3909          */
3910         if ( ! player->pipeline )
3911         {
3912                 if ( MM_ERROR_NONE != __gst_realize( player ) )
3913                 {
3914                         debug_error("failed to realize before starting. only in streamming\n");
3915                         return MM_ERROR_PLAYER_INTERNAL;
3916                 }
3917         }
3918
3919         debug_msg("app-src: pushing data\n");
3920
3921         if ( buf == NULL )
3922         {
3923                 debug_error("buf is null\n");
3924                 return MM_ERROR_NONE;
3925         }
3926
3927         buffer = gst_buffer_new ();
3928
3929         if (size <= 0)
3930         {
3931                 debug_log("call eos appsrc\n");
3932                 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
3933                 return MM_ERROR_NONE;
3934         }
3935
3936         GST_BUFFER_DATA(buffer) = (guint8*)(buf);
3937         GST_BUFFER_SIZE(buffer) = size;
3938
3939         debug_log("feed buffer %p, length %u\n", buf, size);
3940         g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
3941
3942         debug_fleave();
3943
3944         return ret;
3945 }
3946
3947 static GstBusSyncReply
3948 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
3949 {
3950         mm_player_t *player = (mm_player_t *)data;
3951         GstElement *sender = (GstElement *) GST_MESSAGE_SRC (message);
3952         const gchar *name = gst_element_get_name (sender);
3953
3954         switch (GST_MESSAGE_TYPE (message))
3955         {
3956                 case GST_MESSAGE_TAG:
3957                         __mmplayer_gst_extract_tag_from_msg(player, message);
3958                         break;
3959
3960                 case GST_MESSAGE_DURATION:
3961                                 if (MMPLAYER_IS_STREAMING(player))
3962                                 {
3963                                         GstFormat format;
3964                                         gint64 bytes = 0;
3965
3966                                         gst_message_parse_duration (message, &format, &bytes);
3967                                         if (format == GST_FORMAT_BYTES)
3968                                         {
3969                                                 debug_log("data total size of http content: %lld", bytes);
3970                                                 player->http_content_size = bytes;
3971                                         }
3972                                 }
3973                                 else
3974                                 {
3975                                         player->need_update_content_attrs = TRUE;
3976                                         _mmplayer_update_content_attrs(player);
3977                                 }
3978                 default:
3979                         return GST_BUS_PASS;
3980         }
3981         gst_message_unref (message);
3982
3983         return GST_BUS_DROP;
3984 }
3985
3986 /**
3987  * This function is to create  audio or video pipeline for playing.
3988  *
3989  * @param       player          [in]    handle of player
3990  *
3991  * @return      This function returns zero on success.
3992  * @remark
3993  * @see
3994  */
3995 static int
3996 __mmplayer_gst_create_pipeline(mm_player_t* player) // @
3997 {
3998         GstBus  *bus = NULL;
3999         MMPlayerGstElement *mainbin = NULL;
4000         MMHandleType attrs = 0;
4001         GstElement* element = NULL;
4002         GList* element_bucket = NULL;
4003         gboolean need_state_holder = TRUE;
4004         gint i = 0;
4005
4006         debug_fenter();
4007
4008         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4009
4010         /* get profile attribute */
4011         attrs = MMPLAYER_GET_ATTRS(player);
4012         if ( !attrs )
4013         {
4014                 debug_error("cannot get content attribute\n");
4015                 goto INIT_ERROR;
4016         }
4017
4018         /* create pipeline handles */
4019         if ( player->pipeline )
4020         {
4021                 debug_warning("pipeline should be released before create new one\n");
4022                 goto INIT_ERROR;
4023         }
4024
4025         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0( sizeof(MMPlayerGstPipelineInfo) );
4026         if (player->pipeline == NULL)
4027                 goto INIT_ERROR;
4028
4029         memset( player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo) );
4030
4031
4032         /* create mainbin */
4033         mainbin = (MMPlayerGstElement*) g_malloc0( sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM );
4034         if (mainbin == NULL)
4035                 goto INIT_ERROR;
4036
4037         memset( mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
4038
4039
4040         /* create pipeline */
4041         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
4042         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
4043         if ( ! mainbin[MMPLAYER_M_PIPE].gst )
4044         {
4045                 debug_error("failed to create pipeline\n");
4046                 goto INIT_ERROR;
4047         }
4048
4049
4050         /* create source element */
4051         switch ( player->profile.uri_type )
4052         {
4053                 /* rtsp streamming */
4054                 case MM_PLAYER_URI_TYPE_URL_RTSP:
4055                 {
4056                         gint network_bandwidth;
4057                         gchar *user_agent, *wap_profile;
4058
4059                         element = gst_element_factory_make(PLAYER_INI()->name_of_rtspsrc, "streaming_source");
4060
4061                         if ( !element )
4062                         {
4063                                 debug_critical("failed to create streaming source element\n");
4064                                 break;
4065                         }
4066
4067                         debug_log("using streamming source [%s].\n", PLAYER_INI()->name_of_rtspsrc);
4068
4069                         /* make it zero */
4070                         network_bandwidth = 0;
4071                         user_agent = wap_profile = NULL;
4072
4073                         /* get attribute */
4074                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
4075                         mm_attrs_get_string_by_name ( attrs,"streaming_wap_profile", &wap_profile );
4076                         mm_attrs_get_int_by_name ( attrs, "streaming_network_bandwidth", &network_bandwidth );
4077
4078                         debug_log("setting streaming source ----------------\n");
4079                         debug_log("user_agent : %s\n", user_agent);
4080                         debug_log("wap_profile : %s\n", wap_profile);
4081                         debug_log("network_bandwidth : %d\n", network_bandwidth);
4082                         debug_log("buffering time : %d\n", PLAYER_INI()->rtsp_buffering_time);
4083                         debug_log("rebuffering time : %d\n", PLAYER_INI()->rtsp_rebuffering_time);
4084                         debug_log("-----------------------------------------\n");
4085
4086                         /* setting property to streaming source */
4087                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
4088                         g_object_set(G_OBJECT(element), "bandwidth", network_bandwidth, NULL);
4089                         g_object_set(G_OBJECT(element), "buffering_time", PLAYER_INI()->rtsp_buffering_time, NULL);
4090                         g_object_set(G_OBJECT(element), "rebuffering_time", PLAYER_INI()->rtsp_rebuffering_time, NULL);
4091                         if ( user_agent )
4092                                 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
4093                         if ( wap_profile )
4094                                 g_object_set(G_OBJECT(element), "wap_profile", wap_profile, NULL);
4095
4096                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), "pad-added",
4097                                 G_CALLBACK (__mmplayer_gst_rtp_dynamic_pad), player );
4098                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), "no-more-pads",
4099                                 G_CALLBACK (__mmplayer_gst_rtp_no_more_pads), player );
4100
4101                         player->no_more_pad = FALSE;
4102                         player->num_dynamic_pad = 0;
4103
4104                         /* NOTE : we cannot determine it yet. this filed will be filled by
4105                          * _mmplayer_update_content_attrs() after START.
4106                          */
4107                         player->streaming_type = STREAMING_SERVICE_NONE;
4108                 }
4109                 break;
4110
4111                 /* http streaming*/
4112                 case MM_PLAYER_URI_TYPE_URL_HTTP:
4113                 {
4114                         gchar *user_agent, *proxy, *cookies, **cookie_list;
4115                         user_agent = proxy = cookies = NULL;
4116                         cookie_list = NULL;
4117                         gint mode = MM_PLAYER_PD_MODE_NONE;
4118
4119                         mm_attrs_get_int_by_name ( attrs, "pd_mode", &mode );
4120
4121                         player->pd_mode = mode;
4122
4123                         debug_log("http playback, PD mode : %d\n", player->pd_mode);
4124
4125                         if ( ! MMPLAYER_IS_HTTP_PD(player) )
4126                         {
4127                                 element = gst_element_factory_make(PLAYER_INI()->name_of_httpsrc, "http_streaming_source");
4128                                 if ( !element )
4129                                 {
4130                                         debug_critical("failed to create http streaming source element[%s].\n", PLAYER_INI()->name_of_httpsrc);
4131                                         break;
4132                                 }
4133                                 debug_log("using http streamming source [%s].\n", PLAYER_INI()->name_of_httpsrc);
4134
4135                                 /* get attribute */
4136                                 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
4137                                 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
4138                                 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
4139                                 
4140                                 /* get attribute */
4141                                 debug_log("setting http streaming source ----------------\n");
4142                                 debug_log("location : %s\n", player->profile.uri);
4143                                 debug_log("cookies : %s\n", cookies);
4144                                 debug_log("proxy : %s\n", proxy);
4145                                 debug_log("user_agent :  %s\n",  user_agent);
4146                                 debug_log("timeout : %d\n",  PLAYER_INI()->http_timeout);
4147                                 debug_log("-----------------------------------------\n");
4148
4149                                 /* setting property to streaming source */
4150                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
4151                                 g_object_set(G_OBJECT(element), "timeout", PLAYER_INI()->http_timeout, NULL);
4152                                 /* check if prosy is vailid or not */
4153                                 if ( util_check_valid_url ( proxy ) )
4154                                         g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
4155                                 /* parsing cookies */
4156                                 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
4157                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
4158                                 if ( user_agent )
4159                                         g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
4160                         }
4161                         else // progressive download 
4162                         {
4163                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
4164                                 {
4165                                         gchar *path = NULL;
4166                                         
4167                                         mm_attrs_get_string_by_name ( attrs, "pd_location", &path );
4168                                         
4169                                         MMPLAYER_FREEIF(player->pd_file_location);
4170
4171                                         debug_log("PD Location : %s\n", path);
4172
4173                                         if ( path )
4174                                         {
4175                                                 player->pd_file_location = g_strdup(path);
4176                                         }
4177                                         else
4178                                         {
4179                                                 debug_error("can't find pd location so, it should be set \n");
4180                                                 return MM_ERROR_PLAYER_FILE_NOT_FOUND;  
4181                                         }
4182                                 }
4183
4184                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
4185                                 if ( !element )
4186                                 {
4187                                         debug_critical("failed to create PD push source element[%s].\n", "pdpushsrc");
4188                                         break;
4189                                 }
4190
4191                                 g_object_set(G_OBJECT(element), "location", player->pd_file_location, NULL);
4192                         }
4193                         
4194                         player->streaming_type = STREAMING_SERVICE_NONE;
4195                 }
4196                 break;
4197
4198                 /* file source */
4199                 case MM_PLAYER_URI_TYPE_FILE:
4200                 {
4201                         char* drmsrc = PLAYER_INI()->name_of_drmsrc;
4202
4203                         debug_log("using [%s] for 'file://' handler.\n", drmsrc);
4204
4205                         element = gst_element_factory_make(drmsrc, "source");
4206                         if ( !element )
4207                         {
4208                                 debug_critical("failed to create %s\n", drmsrc);
4209                                 break;
4210                         }
4211
4212                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
4213                         //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL);
4214                 }
4215                 break;
4216
4217 #ifdef NO_USE_GST_HLSDEMUX
4218                 case MM_PLAYER_URI_TYPE_HLS:
4219                 {
4220                         guint64 stream_type = GST_APP_STREAM_TYPE_STREAM;
4221
4222                         debug_log("hsl src is selected\n");
4223
4224                         element = gst_element_factory_make("appsrc", "hls-source");
4225                         if ( !element )
4226                         {
4227                                 debug_critical("failed to create appsrc element\n");
4228                                 break;
4229                         }
4230                         g_object_set( element, "stream-type", stream_type, NULL );
4231
4232                         // TODO: need to set time based limit instead of bytes (or) remove constraint.... need to investigate more 
4233                         g_object_set( element, "max-bytes", 500000, NULL ); // Naveen made queue as un-limited
4234                 }
4235                 break;
4236 #endif
4237                 /* appsrc */
4238                 case MM_PLAYER_URI_TYPE_BUFF:
4239                 {
4240                         guint64 stream_type = GST_APP_STREAM_TYPE_STREAM;
4241
4242                         debug_log("mem src is selected\n");
4243
4244                         element = gst_element_factory_make("appsrc", "buff-source");
4245                         if ( !element )
4246                         {
4247                                 debug_critical("failed to create appsrc element\n");
4248                                 break;
4249                         }
4250
4251                         g_object_set( element, "stream-type", stream_type, NULL );
4252                         //g_object_set( element, "size", player->mem_buf.len, NULL );
4253                         //g_object_set( element, "blocksize", (guint64)20480, NULL );
4254
4255                         MMPLAYER_SIGNAL_CONNECT( player, element, "seek-data",
4256                                 G_CALLBACK(__gst_appsrc_seek_data), player);
4257                         MMPLAYER_SIGNAL_CONNECT( player, element, "need-data",
4258                                 G_CALLBACK(__gst_appsrc_feed_data), player);
4259                         MMPLAYER_SIGNAL_CONNECT( player, element, "enough-data",
4260                                 G_CALLBACK(__gst_appsrc_enough_data), player);
4261                 }
4262                 break;
4263
4264                 /* appsrc */
4265                 case MM_PLAYER_URI_TYPE_MEM:
4266                 {
4267                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
4268
4269                         debug_log("mem src is selected\n");
4270
4271                         element = gst_element_factory_make("appsrc", "mem-source");
4272                         if ( !element )
4273                         {
4274                                 debug_critical("failed to create appsrc element\n");
4275                                 break;
4276                         }
4277
4278                         g_object_set( element, "stream-type", stream_type, NULL );
4279                         g_object_set( element, "size", player->mem_buf.len, NULL );
4280                         g_object_set( element, "blocksize", (guint64)20480, NULL );
4281
4282                         MMPLAYER_SIGNAL_CONNECT( player, element, "seek-data",
4283                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->mem_buf );
4284                         MMPLAYER_SIGNAL_CONNECT( player, element, "need-data",
4285                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->mem_buf );
4286                 }
4287                 break;
4288                 case MM_PLAYER_URI_TYPE_URL:
4289                 break;
4290
4291                 case MM_PLAYER_URI_TYPE_TEMP:
4292                 break;
4293
4294                 case MM_PLAYER_URI_TYPE_NONE:
4295                 default:
4296                 break;
4297         }
4298
4299         /* check source element is OK */
4300         if ( ! element )
4301         {
4302                 debug_critical("no source element was created.\n");
4303                 goto INIT_ERROR;
4304         }
4305
4306         /* take source element */
4307         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
4308         mainbin[MMPLAYER_M_SRC].gst = element;
4309         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
4310
4311         if (MMPLAYER_IS_STREAMING(player) || (player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS))
4312         {
4313                 player->streamer = __mm_player_streaming_create();
4314                 __mm_player_streaming_initialize(player->streamer);
4315         }
4316
4317         if ( player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS )
4318         {
4319                 debug_log ("adding appsrc's pad probe...\n");
4320                 GstPad *pad = NULL;
4321                pad = gst_element_get_static_pad(mainbin[MMPLAYER_M_SRC].gst, "src" );
4322
4323                 /* register probe */
4324                 ahs_appsrc_cb_probe_id = gst_pad_add_buffer_probe (pad, 
4325                         G_CALLBACK (__mmplayer_ahs_appsrc_probe), player);
4326                                 
4327                 gst_object_unref(pad);
4328                 pad = NULL;
4329         }
4330
4331         if ( MMPLAYER_IS_HTTP_PD(player) )
4332         {       
4333                debug_log ("Picked queue2 element....\n");
4334                 element = gst_element_factory_make("queue2", "hls_stream_buffer");
4335                 if ( !element )
4336                 {
4337                         debug_critical ( "failed to create http streaming buffer element\n" );
4338                         goto INIT_ERROR;
4339                 }
4340                         
4341                 /* take it */
4342                 mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_S_BUFFER;
4343                 mainbin[MMPLAYER_M_S_BUFFER].gst = element;
4344                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
4345
4346                 __mm_player_streaming_set_buffer(player->streamer,
4347                                 element,
4348                                 TRUE,
4349                                 PLAYER_INI()->http_max_size_bytes,
4350                                 1.0,
4351                                 PLAYER_INI()->http_buffering_limit,
4352                                 PLAYER_INI()->http_buffering_time,
4353                                 FALSE,
4354                                 NULL,
4355                                 0);
4356         }
4357
4358         /* create autoplugging element if src element is not a streamming src */
4359         if ( player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP )
4360         {
4361                 element = NULL;
4362
4363                 if( PLAYER_INI()->use_decodebin )
4364                 {
4365                         /* create decodebin */
4366                         element = gst_element_factory_make("decodebin", "decodebin");
4367
4368                         g_object_set(G_OBJECT(element), "async-handling", TRUE, NULL);
4369
4370                         /* set signal handler */
4371                         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(element), "new-decoded-pad",
4372                                         G_CALLBACK(__mmplayer_gst_decode_callback), player);
4373
4374                         /* we don't need state holder, bcz decodebin is doing well by itself */
4375                         need_state_holder = FALSE;
4376                 }
4377                 else
4378                 {
4379                         element = gst_element_factory_make("typefind", "typefinder");
4380                         MMPLAYER_SIGNAL_CONNECT( player, element, "have-type",
4381                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
4382                 }
4383
4384                 /* check autoplug element is OK */
4385                 if ( ! element )
4386                 {
4387                         debug_critical("can not create autoplug element\n");
4388                         goto INIT_ERROR;
4389                 }
4390
4391                 mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
4392                 mainbin[MMPLAYER_M_AUTOPLUG].gst = element;
4393
4394                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_AUTOPLUG]);
4395         }
4396
4397
4398         /* add elements to pipeline */
4399         if( !__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket))
4400         {
4401                 debug_error("Failed to add elements to pipeline\n");
4402                 goto INIT_ERROR;
4403         }
4404
4405
4406         /* linking elements in the bucket by added order. */
4407         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
4408         {
4409                 debug_error("Failed to link some elements\n");
4410                 goto INIT_ERROR;
4411         }
4412
4413
4414         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
4415         if ( need_state_holder )
4416         {
4417                 /* create */
4418                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
4419                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make ("fakesink", "state-holder");
4420
4421                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
4422                 {
4423                         debug_error ("fakesink element could not be created\n");
4424                         goto INIT_ERROR;
4425                 }
4426                 GST_OBJECT_FLAG_UNSET (mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_IS_SINK);
4427
4428                 /* take ownership of fakesink. we are reusing it */
4429                 gst_object_ref( mainbin[MMPLAYER_M_SRC_FAKESINK].gst );
4430
4431                 /* add */
4432                 if ( FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
4433                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst) )
4434                 {
4435                         debug_error("failed to add fakesink to bin\n");
4436                         goto INIT_ERROR;
4437                 }
4438         }
4439
4440         /* now we have completed mainbin. take it */
4441         player->pipeline->mainbin = mainbin;
4442
4443         /* connect bus callback */
4444         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
4445         if ( !bus )
4446         {
4447                 debug_error ("cannot get bus from pipeline.\n");
4448                 goto INIT_ERROR;
4449         }
4450         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
4451
4452         /* Note : check whether subtitle atrribute uri is set. If uri is set, then create the text pipeline */
4453         if ( __mmplayer_check_subtitle ( player ) )
4454         {
4455                 debug_log("try to create subtitle pipeline \n");
4456
4457                 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_pipeline(player) )
4458                         debug_error("fail to create subtitle pipeline")
4459                 else
4460                         debug_log("subtitle pipeline is created successfully\n");
4461         }
4462
4463         /* set sync handler to get tag synchronously */
4464         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player);
4465
4466
4467         /* finished */
4468         gst_object_unref(GST_OBJECT(bus));
4469         g_list_free(element_bucket);
4470
4471         debug_fleave();
4472
4473         return MM_ERROR_NONE;
4474
4475 INIT_ERROR:
4476
4477         __mmplayer_gst_destroy_pipeline(player);
4478         g_list_free(element_bucket);
4479
4480         /* release element which are not added to bin */
4481         for ( i = 1; i < MMPLAYER_M_NUM; i++ )  /* NOTE : skip pipeline */
4482         {
4483                 if ( mainbin[i].gst )
4484                 {
4485                         GstObject* parent = NULL;
4486                         parent = gst_element_get_parent( mainbin[i].gst );
4487
4488                         if ( !parent )
4489                         {
4490                                 gst_object_unref(GST_OBJECT(mainbin[i].gst));
4491                                 mainbin[i].gst = NULL;
4492                         }
4493                         else
4494                         {
4495                                 gst_object_unref(GST_OBJECT(parent));
4496                         }
4497                 }
4498         }
4499
4500         /* release pipeline with it's childs */
4501         if ( mainbin[MMPLAYER_M_PIPE].gst )
4502         {
4503                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
4504         }
4505
4506         MMPLAYER_FREEIF( player->pipeline );
4507         MMPLAYER_FREEIF( mainbin );
4508
4509         return MM_ERROR_PLAYER_INTERNAL;
4510 }
4511
4512
4513 static int
4514 __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
4515 {
4516         gint timeout = 0;
4517         int ret = MM_ERROR_NONE;
4518
4519         debug_fenter();
4520         
4521         return_val_if_fail ( player, MM_ERROR_INVALID_HANDLE );
4522
4523         /* cleanup stuffs */
4524         MMPLAYER_FREEIF(player->type);
4525         player->have_dynamic_pad = FALSE;
4526         player->no_more_pad = FALSE;
4527         player->num_dynamic_pad = 0;
4528         player->last_position = 0;
4529         player->duration = 0;
4530         player->http_content_size = 0;
4531         player->not_supported_codec = MISSING_PLUGIN_NONE;
4532         player->can_support_codec = FOUND_PLUGIN_NONE;
4533         player->not_found_demuxer = 0;
4534         if (player->v_stream_caps)
4535         {
4536                 gst_caps_unref(player->v_stream_caps);
4537                 player->v_stream_caps = NULL;
4538         }
4539         
4540         player->need_update_content_dur = FALSE;
4541
4542         player->pending_seek.is_pending = FALSE;
4543         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
4544         player->pending_seek.pos = 0;
4545
4546         if (ahs_appsrc_cb_probe_id )
4547         {
4548                 GstPad *pad = NULL;
4549                 pad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "src" );
4550
4551                 gst_pad_remove_buffer_probe (pad, ahs_appsrc_cb_probe_id);
4552                 gst_object_unref(pad);
4553                 pad = NULL;
4554                 ahs_appsrc_cb_probe_id = 0;
4555         }
4556
4557         if ( player->sink_elements )
4558                 g_list_free ( player->sink_elements );
4559         player->sink_elements = NULL;
4560
4561         /* cleanup unlinked mime type */
4562         MMPLAYER_FREEIF(player->unlinked_audio_mime);
4563         MMPLAYER_FREEIF(player->unlinked_video_mime);
4564         MMPLAYER_FREEIF(player->unlinked_demuxer_mime); 
4565
4566         /* cleanup running stuffs */
4567         __mmplayer_cancel_delayed_eos( player );
4568
4569         /* cleanup gst stuffs */
4570         if ( player->pipeline )
4571         {
4572                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
4573                 GstTagList* tag_list = player->pipeline->tag_list;
4574                 GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mainbin[MMPLAYER_M_PIPE].gst));
4575
4576                 /* first we need to disconnect all signal hander */
4577                 __mmplayer_release_signal_connection( player );
4578
4579                 /* disconnecting bus watch */
4580                 if ( player->bus_watcher )
4581                         g_source_remove( player->bus_watcher );
4582                 player->bus_watcher = 0;
4583
4584                 gst_bus_set_sync_handler (bus, NULL, NULL);
4585
4586                 if ( mainbin )
4587                 {
4588                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
4589                         MMPlayerGstElement* videobin = player->pipeline->videobin;
4590                         MMPlayerGstElement* textbin = player->pipeline->textbin;
4591                         MMPlayerGstElement* subtitlebin = player->pipeline->subtitlebin;
4592
4593                         debug_log("pipeline status before set state to NULL\n");
4594                         __mmplayer_dump_pipeline_state( player );
4595
4596                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
4597                         ret = __mmplayer_gst_set_state ( player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout );
4598                         if ( ret != MM_ERROR_NONE )
4599                         {
4600                                 debug_error("fail to change state to NULL\n");
4601                                 return MM_ERROR_PLAYER_INTERNAL;
4602                         }
4603
4604                         debug_log("pipeline status before unrefering pipeline\n");
4605                         __mmplayer_dump_pipeline_state( player );
4606
4607                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
4608
4609                         /* free fakesink */
4610                         if ( mainbin[MMPLAYER_M_SRC_FAKESINK].gst )
4611                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
4612
4613                         /* free avsysaudiosink
4614                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
4615                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
4616                         */
4617                         MMPLAYER_FREEIF( audiobin );
4618                         MMPLAYER_FREEIF( videobin );
4619                         MMPLAYER_FREEIF( textbin );
4620                         MMPLAYER_FREEIF( subtitlebin);
4621                         MMPLAYER_FREEIF( mainbin );
4622                 }
4623
4624                 if ( tag_list )
4625                         gst_tag_list_free(tag_list);
4626
4627                 MMPLAYER_FREEIF( player->pipeline );
4628         }
4629
4630         player->pipeline_is_constructed = FALSE;
4631         
4632         debug_fleave();
4633
4634         return ret;
4635 }
4636
4637 static int __gst_realize(mm_player_t* player) // @
4638 {
4639         gint timeout = 0;
4640         int ret = MM_ERROR_NONE;
4641
4642         debug_fenter();
4643
4644         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4645
4646         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
4647
4648         __ta__("__mmplayer_gst_create_pipeline",
4649                 ret = __mmplayer_gst_create_pipeline(player);
4650                 if ( ret )
4651                 {
4652                         debug_critical("failed to create pipeline\n");
4653                         return ret;
4654                 }
4655         )
4656
4657         /* set pipeline state to READY */
4658         /* NOTE : state change to READY must be performed sync. */
4659         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
4660         ret = __mmplayer_gst_set_state(player,
4661                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
4662
4663         if (MMPLAYER_PLAY_SUBTITLE(player))
4664                 ret = __mmplayer_gst_set_state(player,
4665                                         player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_READY, FALSE, timeout);
4666
4667         if ( ret != MM_ERROR_NONE )
4668         {
4669                 /* return error if failed to set state */
4670                 debug_error("failed to set state PAUSED (live : READY).\n");
4671
4672                 /* dump state of all element */
4673                 __mmplayer_dump_pipeline_state( player );
4674
4675                 return ret;
4676         }
4677         else 
4678         {
4679                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
4680         }
4681
4682         /* create dot before error-return. for debugging */
4683         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-realize" );
4684
4685         debug_fleave();
4686
4687         return ret;
4688 }
4689
4690 static int __gst_unrealize(mm_player_t* player) // @
4691 {
4692         int ret = MM_ERROR_NONE;
4693
4694         debug_fenter();
4695
4696         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4697
4698         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
4699         MMPLAYER_PRINT_STATE(player);   
4700
4701         player->use_video_stream = FALSE;
4702         player->video_stream_cb = NULL;
4703         player->video_stream_cb_user_param = NULL;
4704
4705         player->audio_stream_cb = NULL;
4706         player->audio_stream_cb_user_param = NULL;
4707
4708         player->audio_buffer_cb = NULL;
4709         player->audio_buffer_cb_user_param = NULL;
4710
4711         player->sent_bos = FALSE;
4712         player->playback_rate = DEFAULT_PLAYBACK_RATE;
4713
4714         /* clean found parsers */
4715         if (player->parsers)
4716         {
4717                 g_list_free(player->parsers);
4718                 player->parsers = NULL;
4719         }
4720
4721         MMPLAYER_FREEIF(player->album_art);
4722
4723         /* destroy pipeline */
4724         ret = __mmplayer_gst_destroy_pipeline( player );
4725         if ( ret != MM_ERROR_NONE )
4726         {
4727                 debug_error("failed to destory pipeline\n");
4728                 return ret;
4729         }
4730         else 
4731         {
4732                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
4733         }
4734
4735         debug_fleave();
4736
4737         return ret;
4738 }
4739
4740 static int __gst_pending_seek ( mm_player_t* player )
4741 {
4742         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
4743         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
4744         int ret = MM_ERROR_NONE;
4745
4746         debug_fenter();
4747
4748         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
4749
4750         if ( !player->pending_seek.is_pending )
4751         {
4752                 debug_log("pending seek is not reserved. nothing to do.\n" );
4753                 return ret;
4754         }
4755
4756         /* check player state if player could pending seek or not. */
4757         current_state = MMPLAYER_CURRENT_STATE(player);
4758         pending_state = MMPLAYER_PENDING_STATE(player);
4759
4760         if ( current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING  )
4761         {
4762                 debug_warning("try to pending seek in %s state, try next time. \n",
4763                         MMPLAYER_STATE_GET_NAME(current_state));
4764                 return ret;
4765         }
4766         
4767         debug_log("trying to play from (%lu) pending position\n", player->pending_seek.pos);
4768         
4769         ret = __gst_set_position ( player, player->pending_seek.format, player->pending_seek.pos );
4770         
4771         if ( MM_ERROR_NONE != ret )
4772                 debug_error("failed to seek pending postion. just keep staying current position.\n");
4773
4774         player->pending_seek.is_pending = FALSE;
4775
4776         debug_fleave();
4777
4778         return ret;
4779 }
4780
4781
4782 static int __gst_start(mm_player_t* player) // @
4783 {
4784         gboolean sound_extraction = 0;
4785         gboolean async = FALSE;
4786         gint timeout = 0;
4787         int ret = MM_ERROR_NONE;
4788
4789         debug_fenter();
4790
4791         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
4792
4793         /* get sound_extraction property */
4794         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
4795         /* NOTE : if SetPosition was called before Start. do it now */
4796         /* streaming doesn't support it. so it should be always sync */
4797         /* !! create one more api to check if there is pending seek rather than checking variables */
4798
4799         if ( (player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player))
4800         {
4801                 ret = __gst_pause(player, FALSE);
4802                 if ( ret != MM_ERROR_NONE )
4803                 {
4804                         debug_error("failed to set state to PAUSED for pending seek\n");
4805                         return ret;
4806                 }
4807                         
4808                 if ( sound_extraction )
4809                 {
4810                         debug_log("setting pcm extraction\n");
4811
4812                         ret = __mmplayer_set_pcm_extraction(player);
4813                         if ( MM_ERROR_NONE != ret )
4814                         {
4815                                 debug_warning("failed to set pcm extraction\n");
4816                                 return ret;
4817                         }
4818                 }
4819                 else
4820                 {                       
4821                         if ( MM_ERROR_NONE != __gst_pending_seek(player) )
4822                         {
4823                                 debug_warning("failed to seek pending postion. starting from the begin of content.\n");
4824                         }
4825                 }
4826         }
4827
4828         debug_log("current state before doing transition");
4829         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
4830         MMPLAYER_PRINT_STATE(player);
4831
4832         /* NOTE : note that current variant of rtspsrc has their own buffering mechanism.
4833           * their keeping rtp packets without gst timestamping. there's no easy way to export buffering mechanism to plugin-level. and
4834           * application also not ready. thus, just for now. state transition to PLAYING will done in asyn mode.
4835           * please do not confused with async property hack which done by __gst_set_async_state_change()
4836           */
4837         /* NOTE : testing async start when local playback also */
4838
4839         mm_attrs_get_int_by_name(player->attrs,"profile_async_start", &async);
4840         debug_log("start mode : %s", (async ? "async" : "sync"));
4841
4842         /* set pipeline state to PLAYING  */
4843         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
4844         ret = __mmplayer_gst_set_state(player,
4845                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout );
4846
4847         if (MMPLAYER_PLAY_SUBTITLE(player))
4848                 ret = __mmplayer_gst_set_state(player,
4849                         player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PLAYING, FALSE, timeout );
4850
4851         if (ret == MM_ERROR_NONE)
4852         {
4853                 if (!async)
4854                 {
4855                         guint duration = 0;
4856                         debug_log("sync state changing is completed");
4857
4858                         mm_attrs_get_int_by_name(player->attrs, "content_duration", &duration);
4859                         if (!duration)
4860                         {
4861                                 debug_warning("try to update duration more");
4862                                 player->need_update_content_attrs = TRUE;
4863                                 player->need_update_content_dur = TRUE;
4864                                 _mmplayer_update_content_attrs(player);
4865                         }
4866
4867                         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
4868                 }
4869         }
4870         else
4871         {
4872                 debug_error("failed to set state to PLAYING");
4873
4874                 /* dump state of all element */
4875                 __mmplayer_dump_pipeline_state( player );
4876
4877                 return ret;
4878         }
4879
4880         /* FIXIT : analyze so called "async problem" */
4881         /* set async off */
4882         __gst_set_async_state_change( player, FALSE );
4883
4884         /* generating debug info before returning error */
4885         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-start" );
4886
4887         debug_fleave();
4888
4889         return ret;
4890 }
4891
4892 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
4893 {
4894         debug_fenter();
4895         
4896         return_if_fail(player 
4897                 && player->pipeline
4898                 && player->pipeline->audiobin
4899                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
4900
4901         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
4902         
4903         usleep(time);
4904
4905         debug_fleave();
4906 }
4907
4908 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
4909 {
4910         debug_fenter();
4911         
4912         return_if_fail(player 
4913                 && player->pipeline
4914                 && player->pipeline->audiobin
4915                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
4916         
4917         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);       
4918
4919         debug_fleave();
4920 }
4921
4922 static int __gst_stop(mm_player_t* player) // @
4923 {
4924         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
4925         MMHandleType attrs = 0;
4926         gboolean fadewown = FALSE;
4927         gboolean rewind = FALSE;
4928         gint timeout = 0;
4929         int ret = MM_ERROR_NONE;
4930
4931         debug_fenter();
4932
4933         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4934
4935         debug_log("current state before doing transition");
4936         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
4937         MMPLAYER_PRINT_STATE(player);   
4938
4939         attrs = MMPLAYER_GET_ATTRS(player);
4940         if ( !attrs )
4941         {
4942                 debug_error("cannot get content attribute\n");
4943                 return MM_ERROR_PLAYER_INTERNAL;
4944         }
4945
4946         mm_attrs_get_int_by_name(attrs,"sound_fadedown", &fadewown);
4947
4948         /* enable fadedown */
4949         if (fadewown)
4950                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
4951
4952         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
4953         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
4954         if  ( player->profile.uri_type == MM_PLAYER_URI_TYPE_BUFF || player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS)
4955         {
4956                 ret = __mmplayer_gst_set_state(player, 
4957                         player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout );
4958         }
4959         else
4960         {
4961                 ret = __mmplayer_gst_set_state( player,
4962                         player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, FALSE, timeout );
4963
4964                 if (MMPLAYER_PLAY_SUBTITLE(player))
4965                         ret = __mmplayer_gst_set_state( player,
4966                                 player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PAUSED, FALSE, timeout );
4967
4968                 if ( !MMPLAYER_IS_STREAMING(player))
4969                         rewind = TRUE;
4970         }
4971
4972         /* disable fadeout */
4973         if (fadewown)
4974                 __mmplayer_undo_sound_fadedown(player);
4975
4976
4977         /* return if set_state has failed */
4978         if ( ret != MM_ERROR_NONE )
4979         {
4980                 debug_error("failed to set state.\n");
4981
4982                 /* dump state of all element. don't care it success or not */
4983                 __mmplayer_dump_pipeline_state( player );
4984
4985                 return ret;
4986         }
4987
4988         /* rewind */
4989         if ( rewind )
4990         {
4991                 if ( ! __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
4992                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
4993                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE) )
4994                 {
4995                         debug_warning("failed to rewind\n");
4996                         ret = MM_ERROR_PLAYER_SEEK;
4997                 }
4998         }
4999
5000         /* initialize */
5001         player->sent_bos = FALSE;
5002
5003         /* wait for seek to complete */
5004         change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
5005         if (MMPLAYER_PLAY_SUBTITLE(player))
5006                 change_ret = gst_element_get_state (player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
5007
5008         if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL )
5009         {
5010                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
5011         }
5012         else
5013         {
5014                 debug_error("fail to stop player.\n");
5015                 ret = MM_ERROR_PLAYER_INTERNAL;
5016         }
5017
5018         /* generate dot file if enabled */
5019         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-stop" );
5020
5021         debug_fleave(); 
5022
5023         return ret;
5024 }
5025
5026
5027 int __gst_pause(mm_player_t* player, gboolean async) // @
5028 {
5029         gint timeout = 0;
5030         int ret = MM_ERROR_NONE;
5031
5032         debug_fenter();
5033
5034         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5035
5036         debug_log("current state before doing transition");
5037         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
5038         MMPLAYER_PRINT_STATE(player);   
5039
5040         if ( async )
5041                 debug_log("do async state transition to PAUSE.\n");
5042
5043         /* set pipeline status to PAUSED */
5044         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
5045         ret = __mmplayer_gst_set_state(player,
5046                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, timeout );
5047
5048         if (MMPLAYER_PLAY_SUBTITLE(player))
5049                 ret = __mmplayer_gst_set_state(player,
5050                         player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PAUSED, async, timeout );
5051
5052         if ( ret != MM_ERROR_NONE )
5053         {
5054                 debug_error("failed to set state to PAUSED\n");
5055
5056                 /* dump state of all element */
5057                 __mmplayer_dump_pipeline_state( player );
5058
5059                 return ret;
5060         }
5061         else
5062         {       
5063                 if ( async == FALSE ) 
5064                 {
5065                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
5066                 }
5067         } 
5068
5069         /* FIXIT : analyze so called "async problem" */
5070         /* set async off */
5071         __gst_set_async_state_change( player, TRUE);
5072
5073
5074         /* generate dot file before returning error */
5075         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-pause" );
5076
5077         debug_fleave();
5078
5079         return ret;
5080 }
5081
5082 int __gst_resume(mm_player_t* player, gboolean async) // @
5083 {
5084         int ret = MM_ERROR_NONE;
5085         gint timeout = 0;
5086
5087         debug_fenter();
5088
5089         return_val_if_fail(player && player->pipeline,
5090                 MM_ERROR_PLAYER_NOT_INITIALIZED);
5091
5092         debug_log("current state before doing transition");
5093         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
5094         MMPLAYER_PRINT_STATE(player);   
5095
5096         /* generate dot file before returning error */
5097         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
5098
5099         __mmplayer_set_antishock( player , FALSE );
5100
5101         if ( async )
5102                 debug_log("do async state transition to PLAYING.\n");
5103
5104         /* set pipeline state to PLAYING */
5105         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
5106         ret = __mmplayer_gst_set_state(player,
5107                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout );
5108
5109         if (MMPLAYER_PLAY_SUBTITLE(player))
5110                 ret = __mmplayer_gst_set_state(player,
5111                         player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PLAYING, async, timeout );
5112
5113         if (ret != MM_ERROR_NONE)
5114         {
5115                 debug_error("failed to set state to PLAYING\n");
5116
5117                 /* dump state of all element */
5118                 __mmplayer_dump_pipeline_state( player );
5119
5120                 return ret;
5121         }
5122         else
5123         {
5124                 if (async == FALSE)
5125                 {
5126                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING );
5127                 }
5128         }
5129         
5130         /* FIXIT : analyze so called "async problem" */
5131         /* set async off */
5132         __gst_set_async_state_change( player, FALSE );
5133
5134         /* generate dot file before returning error */
5135         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
5136
5137         debug_fleave();
5138
5139         return ret;
5140 }
5141
5142 static int
5143 __gst_set_position(mm_player_t* player, int format, unsigned long position) // @
5144 {
5145         GstFormat fmt  = GST_FORMAT_TIME;
5146         unsigned long dur_msec = 0;
5147         gint64 dur_nsec = 0;
5148         gint64 pos_nsec = 0;
5149         gboolean ret = TRUE;
5150
5151         debug_fenter();
5152         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5153         return_val_if_fail ( !MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP );
5154
5155         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
5156                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED )
5157                 goto PENDING;
5158
5159         /* check duration */
5160         /* NOTE : duration cannot be zero except live streaming.
5161          *              Since some element could have some timing problemn with quering duration, try again.
5162          */
5163         if ( !player->duration )
5164         {
5165                 if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec ))
5166                 {
5167                         goto SEEK_ERROR;
5168                 }
5169                 player->duration = dur_nsec;
5170         }
5171
5172         if ( player->duration )
5173         {
5174                 dur_msec = GST_TIME_AS_MSECONDS(player->duration);
5175         }
5176         else
5177         {
5178                 debug_error("could not get the duration. fail to seek.\n");
5179                 goto SEEK_ERROR;
5180         }
5181
5182         debug_log("playback rate: %f\n", player->playback_rate);
5183
5184         /* do seek */
5185         switch ( format )
5186         {
5187                 case MM_PLAYER_POS_FORMAT_TIME:
5188                 {
5189                         /* check position is valid or not */
5190                         if ( position > dur_msec )
5191                                 goto INVALID_ARGS;
5192
5193                         debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec);
5194
5195                         if (player->doing_seek)
5196                         {
5197                                 debug_log("not completed seek");
5198                                 return MM_ERROR_PLAYER_DOING_SEEK;
5199                         }
5200                         player->doing_seek = TRUE;
5201
5202                         pos_nsec = position * G_GINT64_CONSTANT(1000000);
5203                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
5204                                                         GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
5205                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
5206                         if ( !ret  )
5207                         {
5208                                 debug_error("failed to set position. dur[%lu]  pos[%lu]  pos_msec[%llu]\n", dur_msec, position, pos_nsec);
5209                                 goto SEEK_ERROR;
5210                         }
5211                 }
5212                 break;
5213
5214                 case MM_PLAYER_POS_FORMAT_PERCENT:
5215                 {
5216                         if ( position < 0 && position > 100 )
5217                                 goto INVALID_ARGS;
5218
5219                         debug_log("seeking to (%lu)%% \n", position);
5220
5221                         if (player->doing_seek)
5222                         {
5223                                 debug_log("not completed seek");
5224                                 return MM_ERROR_PLAYER_DOING_SEEK;
5225                         }
5226                         player->doing_seek = TRUE;
5227
5228                         /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
5229                         pos_nsec = (gint64) ( ( position * player->duration ) / 100 );
5230                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
5231                                                         GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
5232                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
5233                         if ( !ret  )
5234                         {
5235                                 debug_error("failed to set position. dur[%lud]  pos[%lud]  pos_msec[%llud]\n", dur_msec, position, pos_nsec);
5236                                 goto SEEK_ERROR;
5237                         }
5238                 }
5239                 break;
5240
5241                 default:
5242                         goto INVALID_ARGS;
5243                         
5244         }
5245
5246         /* NOTE : store last seeking point to overcome some bad operation 
5247           *      ( returning zero when getting current position ) of some elements 
5248           */
5249         player->last_position = pos_nsec;
5250
5251         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
5252         if ( player->playback_rate > 1.0 )
5253                 _mmplayer_set_playspeed ( (MMHandleType)player, player->playback_rate );
5254
5255         debug_fleave();
5256         return MM_ERROR_NONE;
5257
5258 PENDING:
5259         player->pending_seek.is_pending = TRUE;
5260         player->pending_seek.format = format;
5261         player->pending_seek.pos = position;
5262         
5263         debug_warning("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n", 
5264                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
5265         
5266         return MM_ERROR_NONE;
5267         
5268 INVALID_ARGS:   
5269         debug_error("invalid arguments, position : %ld  dur : %ld format : %d \n", position, dur_msec, format);
5270         return MM_ERROR_INVALID_ARGUMENT;
5271
5272 SEEK_ERROR:
5273         player->doing_seek = FALSE;
5274         return MM_ERROR_PLAYER_SEEK;
5275 }
5276
5277 #define TRICKPLAY_OFFSET GST_MSECOND
5278
5279 static int
5280 __gst_get_position(mm_player_t* player, int format, unsigned long* position) // @
5281 {
5282         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
5283         GstFormat fmt = GST_FORMAT_TIME;
5284         signed long long pos_msec = 0;
5285         gboolean ret = TRUE;
5286
5287         return_val_if_fail( player && position && player->pipeline && player->pipeline->mainbin,
5288                 MM_ERROR_PLAYER_NOT_INITIALIZED );
5289
5290         current_state = MMPLAYER_CURRENT_STATE(player);
5291
5292         /* NOTE : query position except paused state to overcome some bad operation
5293          * please refer to below comments in details
5294          */
5295         if ( current_state != MM_PLAYER_STATE_PAUSED )
5296         {
5297                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &pos_msec);
5298         }
5299
5300         /* NOTE : get last point to overcome some bad operation of some elements
5301          * ( returning zero when getting current position in paused state
5302          * and when failed to get postion during seeking
5303          */
5304         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
5305                 || ( ! ret ))
5306                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
5307         {
5308                 debug_warning ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
5309
5310                 if(player->playback_rate < 0.0)
5311                         pos_msec = player->last_position - TRICKPLAY_OFFSET;
5312                 else
5313                         pos_msec = player->last_position;
5314
5315                 if (!ret)
5316                         pos_msec = player->last_position;
5317                 else
5318                         player->last_position = pos_msec;
5319
5320                 debug_warning("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
5321
5322         }
5323         else
5324         {
5325                 player->last_position = pos_msec;
5326         }
5327
5328         switch (format) {
5329                 case MM_PLAYER_POS_FORMAT_TIME:
5330                         *position = GST_TIME_AS_MSECONDS(pos_msec);
5331                         break;
5332
5333                 case MM_PLAYER_POS_FORMAT_PERCENT:
5334                 {
5335                         int dur = 0;
5336                         int pos = 0;
5337
5338                         dur = player->duration / GST_SECOND;
5339                         if (dur <= 0)
5340                         {
5341                                 debug_log ("duration is [%d], so returning position 0\n",dur);
5342                                 *position = 0;
5343                         }
5344                         else
5345                         {
5346                                 pos = pos_msec / GST_SECOND;
5347                                 *position = pos * 100 / dur;
5348                         }
5349                         break;
5350                 }
5351                 default:
5352                         return MM_ERROR_PLAYER_INTERNAL;
5353         }
5354
5355         debug_log("current position : %lu\n", *position);
5356
5357         
5358         return MM_ERROR_NONE;
5359 }
5360
5361
5362 static int      __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
5363 {
5364         GstElement *element = NULL;
5365         GstQuery *query = NULL;
5366
5367         return_val_if_fail( player && 
5368                 player->pipeline && 
5369                 player->pipeline->mainbin,
5370                 MM_ERROR_PLAYER_NOT_INITIALIZED );
5371
5372         return_val_if_fail( start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT );
5373
5374         if ( MMPLAYER_IS_HTTP_STREAMING ( player ) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player ))       
5375         {
5376                 /* Note : In case of http streaming or HLS, the buffering queue [ queue2 ] could handle buffering query. */
5377                 element = GST_ELEMENT ( player->pipeline->mainbin[MMPLAYER_M_S_BUFFER].gst );
5378         }
5379         else if ( MMPLAYER_IS_RTSP_STREAMING ( player ) )
5380         {
5381                 debug_warning ( "it's not supported yet.\n" );
5382                 return MM_ERROR_NONE;
5383         }
5384         else
5385         {
5386                 debug_warning ( "it's only used for streaming case.\n" );
5387                 return MM_ERROR_NONE;   
5388         }
5389
5390         *start_pos = 0;
5391         *stop_pos = 0;
5392         
5393         switch ( format )
5394         {
5395                 case MM_PLAYER_POS_FORMAT_PERCENT :
5396                 {
5397                                 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
5398                                 if ( gst_element_query ( element, query ) ) 
5399                                 {
5400                                         gint64 start, stop;
5401                                         GstFormat format;
5402                                         gboolean busy;
5403                                         gint percent;
5404
5405                                         gst_query_parse_buffering_percent ( query, &busy, &percent);
5406                                         gst_query_parse_buffering_range ( query, &format, &start, &stop, NULL );
5407
5408                                         debug_log ( "buffering start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT "\n",  start, stop);
5409
5410                                         if ( start != -1)
5411                                                 *start_pos = 100 * start / GST_FORMAT_PERCENT_MAX;
5412                                         else
5413                                                 *start_pos = 0;
5414
5415                                         if ( stop != -1)
5416                                                 *stop_pos = 100 * stop / GST_FORMAT_PERCENT_MAX;
5417                                         else
5418                                                 *stop_pos = 0;
5419                                 }
5420                                 gst_query_unref (query);
5421                 }
5422                 break;
5423
5424                 case MM_PLAYER_POS_FORMAT_TIME :
5425                         debug_warning ( "Time format is not supported yet.\n" );
5426                         break;
5427                         
5428                 default :
5429                         break;
5430         }
5431
5432         debug_log("current buffer position : %lu~%lu \n", *start_pos, *stop_pos );
5433
5434         return MM_ERROR_NONE;
5435 }
5436
5437 static int
5438 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param) // @
5439 {
5440         debug_fenter();
5441
5442         if ( !player )
5443         {
5444                 debug_warning("set_message_callback is called with invalid player handle\n");
5445                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
5446         }
5447
5448         player->msg_cb = callback;
5449         player->msg_cb_param = user_param;
5450
5451         debug_log("msg_cb : 0x%x     msg_cb_param : 0x%x\n", (guint)callback, (guint)user_param);
5452
5453         debug_fleave();
5454
5455         return MM_ERROR_NONE;
5456 }
5457
5458 static gboolean __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
5459 {
5460         gboolean ret = FALSE;
5461         char *path = NULL;
5462
5463         debug_fenter();
5464
5465         return_val_if_fail ( uri , FALSE);
5466         return_val_if_fail ( data , FALSE);
5467         return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
5468
5469         memset(data, 0, sizeof(MMPlayerParseProfile));
5470
5471         if ((path = strstr(uri, "file://")))
5472         {
5473                 if (util_exist_file_path(path + 7)) {
5474                         strncpy(data->uri, path, MM_MAX_URL_LEN-1);                     
5475
5476                         if ( util_is_sdp_file ( path ) )
5477                         {
5478                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
5479                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
5480                         }
5481                         else
5482                         {
5483                         data->uri_type = MM_PLAYER_URI_TYPE_FILE;
5484                         }
5485                         ret = TRUE;
5486                 }
5487                 else
5488                 {
5489                         debug_warning("could  access %s.\n", path);
5490                 }
5491         }
5492         else if ((path = strstr(uri, "buff://")))
5493         {
5494                         data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
5495                         ret = TRUE;
5496         }
5497         else if ((path = strstr(uri, "rtsp://")))
5498         {
5499                 if (strlen(path)) {
5500                         strcpy(data->uri, uri);
5501                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
5502                         ret = TRUE;
5503                 }
5504         }
5505         else if ((path = strstr(uri, "http://")))
5506         {
5507                 if (strlen(path)) {
5508                         strcpy(data->uri, uri);
5509                         
5510 #ifdef NO_USE_GST_HLSDEMUX
5511                         if ((path = strstr(uri, "m3u")))
5512                         {
5513                                 data->uri_type = MM_PLAYER_URI_TYPE_HLS;
5514                         }
5515                         else
5516 #endif
5517                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
5518
5519                         ret = TRUE;
5520                 }
5521         }
5522         else if ((path = strstr(uri, "https://")))
5523         {
5524                 if (strlen(path)) {
5525                         strcpy(data->uri, uri);
5526
5527 #ifdef NO_USE_GST_HLSDEMUX
5528                         if ((path = strstr(uri, "m3u")))
5529                         {
5530                                 data->uri_type = MM_PLAYER_URI_TYPE_HLS;
5531                         }
5532                         else
5533 #endif
5534                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
5535                         
5536                         ret = TRUE;
5537                 }
5538         }
5539         else if ((path = strstr(uri, "rtspu://")))
5540         {
5541                 if (strlen(path)) {
5542                         strcpy(data->uri, uri);
5543                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
5544                         ret = TRUE;
5545                 }
5546         }
5547         else if ((path = strstr(uri, "rtspr://")))
5548         {
5549                 strcpy(data->uri, path);
5550                 char *separater =strstr(path, "*");
5551
5552                 if (separater) {
5553                         int urgent_len = 0;
5554                         char *urgent = separater + strlen("*");
5555
5556                         if ((urgent_len = strlen(urgent))) {
5557                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
5558                                 strcpy(data->urgent, urgent);
5559                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
5560                                 ret = TRUE;
5561                         }
5562                 }
5563         }
5564         else if ((path = strstr(uri, "mms://")))
5565         {
5566                 if (strlen(path)) {
5567                         strcpy(data->uri, uri);
5568                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
5569                         ret = TRUE;
5570                 }
5571         }
5572         else if ((path = strstr(uri, "mem://")))
5573         {
5574                 if (strlen(path)) {
5575                         int mem_size = 0;
5576                         char *buffer = NULL;
5577                         char *seperator = strchr(path, ',');
5578                         char ext[100] = {0,}, size[100] = {0,};
5579
5580                         if (seperator) {
5581                                 if ((buffer = strstr(path, "ext="))) {
5582                                         buffer += strlen("ext=");
5583
5584                                         if (strlen(buffer)) {
5585                                                 strcpy(ext, buffer);
5586
5587                                                 if ((seperator = strchr(ext, ','))
5588                                                         || (seperator = strchr(ext, ' '))
5589                                                         || (seperator = strchr(ext, '\0'))) {
5590                                                         seperator[0] = '\0';
5591                                                 }
5592                                         }
5593                                 }
5594
5595                                 if ((buffer = strstr(path, "size="))) {
5596                                         buffer += strlen("size=");
5597
5598                                         if (strlen(buffer) > 0) {
5599                                                 strcpy(size, buffer);
5600
5601                                                 if ((seperator = strchr(size, ','))
5602                                                         || (seperator = strchr(size, ' '))
5603                                                         || (seperator = strchr(size, '\0'))) {
5604                                                         seperator[0] = '\0';
5605                                                 }
5606
5607                                                 mem_size = atoi(size);
5608                                         }
5609                                 }
5610                         }
5611
5612                         debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
5613                         if ( mem_size && param) {
5614                                         data->mem = param;
5615                                         data->mem_size = mem_size;
5616                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
5617                                 ret = TRUE;
5618                         }
5619                 }
5620         }
5621         else
5622         {
5623                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
5624                 if (util_exist_file_path(uri))
5625                 {
5626                         debug_warning("uri has no protocol-prefix. giving 'file://' by default.\n");
5627
5628                         sprintf( data->uri, "file://%s", uri );
5629
5630                         if ( util_is_sdp_file( (char*)uri ) )
5631                         {
5632                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
5633                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
5634                         }
5635                         else
5636                         {
5637                         data->uri_type = MM_PLAYER_URI_TYPE_FILE;
5638                         }
5639                         ret = TRUE;
5640                 }
5641                 else
5642                 {
5643                         debug_error ("invalid uri, could not play..\n");
5644                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
5645                 }
5646         }
5647         
5648         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
5649                 ret = FALSE;
5650         }
5651
5652
5653         /* dump parse result */
5654         debug_log("profile parsing result ---\n");
5655         debug_log("incomming uri : %s\n", uri);
5656         debug_log("uri : %s\n", data->uri);
5657         debug_log("uri_type : %d\n", data->uri_type);
5658         debug_log("play_mode : %d\n", data->play_mode);
5659         debug_log("mem : 0x%x\n", (guint)data->mem);
5660         debug_log("mem_size : %d\n", data->mem_size);
5661         debug_log("urgent : %s\n", data->urgent);
5662         debug_log("--------------------------\n");
5663
5664         debug_fleave();
5665
5666         return ret;
5667 }
5668
5669 gboolean _asm_postmsg(gpointer *data)
5670 {
5671         mm_player_t* player = (mm_player_t*)data;
5672         MMMessageParamType msg = {0, };
5673
5674         debug_fenter();
5675
5676         return_val_if_fail ( player, FALSE );
5677
5678         msg.union_type = MM_MSG_UNION_CODE;
5679         msg.code = player->sm.event_src;
5680         
5681         MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
5682         
5683         return FALSE;
5684 }
5685 gboolean _asm_lazy_pause(gpointer *data)
5686 {
5687         mm_player_t* player = (mm_player_t*)data;
5688         int ret = MM_ERROR_NONE;
5689
5690         debug_fenter();
5691
5692         return_val_if_fail ( player, FALSE );
5693
5694         if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
5695         {
5696                 debug_log ("Ready to proceed lazy pause\n");
5697                 ret = _mmplayer_pause((MMHandleType)player);
5698                 if(MM_ERROR_NONE != ret)
5699                 {
5700                         debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
5701                 }       
5702         }
5703         else
5704         {
5705                 debug_log ("Invalid state to proceed lazy pause\n");
5706         }
5707
5708         /* unset mute */
5709         if (player->pipeline && player->pipeline->audiobin)
5710                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
5711
5712         player->sm.by_asm_cb = 0; //should be reset here
5713
5714         debug_fleave();
5715
5716         return FALSE;
5717 }
5718 ASM_cb_result_t
5719 __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
5720 {
5721         mm_player_t* player = (mm_player_t*) cb_data;
5722         ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
5723         int result = MM_ERROR_NONE;
5724         gboolean lazy_pause = FALSE;
5725
5726         debug_fenter();
5727
5728         return_val_if_fail ( player && player->pipeline, ASM_CB_RES_IGNORE );
5729         return_val_if_fail ( player->attrs, MM_ERROR_PLAYER_INTERNAL );
5730
5731         if (player->is_sound_extraction)
5732         {
5733                 debug_log("sound extraction is working...so, asm command is ignored.\n");
5734                 return result;
5735         }
5736         
5737         player->sm.by_asm_cb = 1; // it should be enabled for player state transition with called application command
5738         player->sm.event_src = event_src;
5739
5740         if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
5741         {
5742                 player->sm.event_src = ASM_EVENT_SOURCE_OTHER_APP;
5743         }
5744         else if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG )
5745         {
5746                 int stop_by_asm = 0;
5747
5748                 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
5749                 if (!stop_by_asm)
5750                         return cb_res;
5751         }
5752         else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
5753         {
5754                 /* can use video overlay simultaneously */
5755                 /* video resource conflict */
5756                 if(player->pipeline->videobin) 
5757                 {
5758                         if (PLAYER_INI()->multiple_codec_supported)
5759                         {
5760                                 debug_log("video conflict but, can support to use video overlay simultaneously");
5761                                 result = _mmplayer_pause((MMHandleType)player);
5762                                 cb_res = ASM_CB_RES_PAUSE;
5763                         }
5764                         else
5765                         {
5766                                 debug_log("video conflict, can't support for multiple codec instance");
5767                                 result = _mmplayer_unrealize((MMHandleType)player);
5768                                 cb_res = ASM_CB_RES_STOP;
5769                         }
5770                 }
5771                 return cb_res;
5772         }
5773
5774         switch(command)
5775         {
5776                 case ASM_COMMAND_PLAY:
5777                 case ASM_COMMAND_STOP:
5778                         debug_warning ("Got unexpected asm command (%d)", command);
5779                 break;
5780                         
5781                 case ASM_COMMAND_PAUSE:
5782                 {
5783                         debug_log("Got msg from asm to Pause");
5784                         
5785                         if(event_src == ASM_EVENT_SOURCE_CALL_START
5786                                 || event_src == ASM_EVENT_SOURCE_ALARM_START
5787                                 || event_src == ASM_EVENT_SOURCE_OTHER_APP)
5788                         {
5789                                 //hold 0.7 second to excute "fadedown mute" effect
5790                                 debug_log ("do fade down->pause->undo fade down");
5791                                         
5792                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
5793                                         
5794                                 result = _mmplayer_pause((MMHandleType)player);
5795                                 if (result != MM_ERROR_NONE)
5796                                 {
5797                                         debug_warning("fail to set Pause state by asm");
5798                                         cb_res = ASM_CB_RES_IGNORE;
5799                                         break;
5800                                 }
5801                                 __mmplayer_undo_sound_fadedown(player);
5802                         }
5803                         else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
5804                         {
5805                                 lazy_pause = TRUE; // return as soon as possible, for fast start of other app
5806
5807                                 if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
5808                                         g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
5809
5810                                 player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
5811                                 debug_log ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
5812                         }
5813                         else
5814                         {
5815                                 //immediate pause
5816                                 debug_log ("immediate pause");
5817                                 result = _mmplayer_pause((MMHandleType)player);
5818                         }
5819                         cb_res = ASM_CB_RES_PAUSE;
5820                 }
5821                 break;
5822                         
5823                 case ASM_COMMAND_RESUME:
5824                 {
5825                         debug_log("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
5826                         player->sm.by_asm_cb = 0;
5827                         //ASM server is single thread daemon. So use g_idle_add() to post resume msg
5828                         g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
5829                         cb_res = ASM_CB_RES_IGNORE;
5830                 }
5831                 break;
5832
5833                 default:
5834                 break;
5835         }
5836
5837         if (!lazy_pause)
5838                 player->sm.by_asm_cb = 0;
5839
5840         debug_fleave();
5841
5842         return cb_res;
5843 }
5844
5845 int
5846 _mmplayer_create_player(MMHandleType handle) // @
5847 {
5848         mm_player_t* player = MM_PLAYER_CAST(handle);
5849         gint i;
5850
5851         debug_fenter();
5852
5853         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5854
5855         MMTA_ACUM_ITEM_BEGIN("[KPI] media player service create->playing", FALSE);
5856
5857         /* initialize player state */
5858         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
5859         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
5860         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
5861         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
5862
5863         /* check current state */
5864         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
5865
5866         /* construct attributes */
5867         player->attrs = _mmplayer_construct_attribute(handle);
5868
5869         if ( !player->attrs )
5870         {
5871                 debug_critical("Failed to construct attributes\n");
5872                 goto ERROR;
5873         }
5874
5875         /* initialize gstreamer with configured parameter */
5876         if ( ! __mmplayer_gstreamer_init() )
5877         {
5878                 debug_critical("Initializing gstreamer failed\n");
5879                 goto ERROR;
5880         }
5881
5882         /* initialize factories if not using decodebin */
5883         if ( FALSE == PLAYER_INI()->use_decodebin )
5884         {
5885                 if( player->factories == NULL )
5886                     __mmplayer_init_factories(player);
5887         }
5888
5889         /* create lock. note that g_tread_init() has already called in gst_init() */
5890         player->fsink_lock = g_mutex_new();
5891         if ( ! player->fsink_lock )
5892         {
5893                 debug_critical("Cannot create mutex for command lock\n");
5894                 goto ERROR;
5895         }
5896
5897         /* create repeat mutex */
5898         player->repeat_thread_mutex = g_mutex_new();
5899         if ( ! player->repeat_thread_mutex )
5900         {
5901                 debug_critical("Cannot create repeat mutex\n");
5902                 goto ERROR;
5903         }
5904
5905         /* create repeat cond */
5906         player->repeat_thread_cond = g_cond_new();
5907         if ( ! player->repeat_thread_cond )
5908         {
5909                 debug_critical("Cannot create repeat cond\n");
5910                 goto ERROR;
5911         }
5912
5913         /* create repeat thread */
5914         player->repeat_thread =
5915                 g_thread_create (__mmplayer_repeat_thread, (gpointer)player, TRUE, NULL);
5916         if ( ! player->repeat_thread )
5917         {
5918                 goto ERROR;
5919         }
5920
5921         if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
5922         {
5923                 debug_error("failed to initialize video capture\n");
5924                 goto ERROR;
5925         }
5926
5927         /* register to asm */
5928         if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
5929         {
5930                 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
5931                 debug_error("failed to register asm server\n");
5932                 return MM_ERROR_POLICY_INTERNAL;
5933         }
5934
5935         if (MMPLAYER_IS_HTTP_PD(player))
5936         {
5937                 player->pd_downloader = NULL;
5938                 player->pd_file_location = NULL;
5939         }
5940
5941         /* give default value of sound effect setting */
5942         player->bypass_sound_effect = TRUE;
5943         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
5944         player->playback_rate = DEFAULT_PLAYBACK_RATE;
5945         player->no_more_pad = TRUE;
5946
5947         /* set player state to null */
5948         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout;
5949         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
5950
5951         debug_fleave();
5952         return MM_ERROR_NONE;
5953
5954 ERROR:
5955         /* free lock */
5956         if ( player->fsink_lock )
5957                 g_mutex_free( player->fsink_lock );
5958         player->fsink_lock = NULL;
5959
5960         /* free thread */
5961         if ( player->repeat_thread_cond &&
5962                  player->repeat_thread_mutex &&
5963                  player->repeat_thread )
5964         {
5965                 player->repeat_thread_exit = TRUE;
5966                 g_cond_signal( player->repeat_thread_cond );
5967
5968                 g_thread_join( player->repeat_thread );
5969                 player->repeat_thread = NULL;
5970
5971                 g_mutex_free ( player->repeat_thread_mutex );
5972                 player->repeat_thread_mutex = NULL;
5973
5974                 g_cond_free ( player->repeat_thread_cond );
5975                 player->repeat_thread_cond = NULL;
5976         }
5977         /* clear repeat thread mutex/cond if still alive
5978          * this can happen if only thread creating has failed
5979          */
5980         if ( player->repeat_thread_mutex )
5981                 g_mutex_free ( player->repeat_thread_mutex );
5982
5983         if ( player->repeat_thread_cond )
5984                 g_cond_free ( player->repeat_thread_cond );
5985
5986         /* release attributes */
5987         _mmplayer_deconstruct_attribute(handle);
5988
5989         return MM_ERROR_PLAYER_INTERNAL;
5990 }
5991
5992 static gboolean
5993 __mmplayer_gstreamer_init(void) // @
5994 {
5995         static gboolean initialized = FALSE;
5996         static const int max_argc = 50;
5997         gint* argc = NULL;
5998         gchar** argv = NULL;
5999         GError *err = NULL;
6000         int i = 0;
6001
6002         debug_fenter();
6003
6004         if ( initialized )
6005         {
6006                 debug_log("gstreamer already initialized.\n");
6007                 return TRUE;
6008         }
6009
6010         /* alloc */
6011         argc = malloc( sizeof(int) );
6012         argv = malloc( sizeof(gchar*) * max_argc );
6013
6014         if ( !argc || !argv )
6015                 goto ERROR;
6016
6017         memset( argv, 0, sizeof(gchar*) * max_argc );
6018
6019         /* add initial */
6020         *argc = 1;
6021         argv[0] = g_strdup( "mmplayer" );
6022
6023         /* add gst_param */
6024         for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
6025         {
6026                 if ( strlen( PLAYER_INI()->gst_param[i] ) > 0 )
6027                 {
6028                         argv[*argc] = g_strdup( PLAYER_INI()->gst_param[i] );
6029                         (*argc)++;
6030                 }
6031         }
6032
6033         /* we would not do fork for scanning plugins */
6034         argv[*argc] = g_strdup("--gst-disable-registry-fork");
6035         (*argc)++;
6036
6037         /* check disable registry scan */
6038         if ( PLAYER_INI()->skip_rescan )
6039         {
6040                 argv[*argc] = g_strdup("--gst-disable-registry-update");
6041                 (*argc)++;
6042         }
6043
6044         /* check disable segtrap */
6045         if ( PLAYER_INI()->disable_segtrap )
6046         {
6047                 argv[*argc] = g_strdup("--gst-disable-segtrap");
6048                 (*argc)++;
6049         }
6050
6051         debug_log("initializing gstreamer with following parameter\n");
6052         debug_log("argc : %d\n", *argc);
6053
6054         for ( i = 0; i < *argc; i++ )
6055         {
6056                 debug_log("argv[%d] : %s\n", i, argv[i]);
6057         }
6058
6059
6060         /* initializing gstreamer */
6061         __ta__("gst_init time",
6062
6063                 if ( ! gst_init_check (argc, &argv, &err))
6064                 {
6065                         debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
6066                         if (err)
6067                         {
6068                                 g_error_free (err);
6069                         }
6070
6071                         goto ERROR;
6072                 }
6073         );
6074
6075         /* release */
6076         for ( i = 0; i < *argc; i++ )
6077         {
6078                 MMPLAYER_FREEIF( argv[i] );
6079         }
6080
6081         MMPLAYER_FREEIF( argv );
6082         MMPLAYER_FREEIF( argc );
6083
6084         /* done */
6085         initialized = TRUE;
6086
6087         debug_fleave();
6088
6089         return TRUE;
6090
6091 ERROR:
6092
6093         MMPLAYER_FREEIF( argv );
6094         MMPLAYER_FREEIF( argc );
6095
6096         return FALSE;
6097 }
6098
6099 int 
6100 __mmplayer_release_extended_streaming(mm_player_t* player)
6101 {
6102         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6103
6104         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
6105         {
6106                 _mmplayer_pd_stop ((MMHandleType)player);
6107                 _mmplayer_pd_deinitialize ((MMHandleType)player);
6108                 _mmplayer_pd_destroy((MMHandleType)player);
6109         }
6110
6111 #ifdef NO_USE_GST_HLSDEMUX
6112         /* destroy can called at anytime */
6113        if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
6114        {
6115                 if (player->ahs_player)
6116                 {
6117                         __mm_player_ahs_stop (player->ahs_player);
6118                         __mm_player_ahs_deinitialize (player->ahs_player);
6119                         __mm_player_ahs_destroy(player->ahs_player);
6120                         player->ahs_player = NULL;
6121                 }
6122        }
6123 #endif
6124
6125        if (MMPLAYER_IS_STREAMING(player))
6126        {
6127                 if (player->streamer)
6128                 {
6129                         __mm_player_streaming_deinitialize (player->streamer);
6130                         __mm_player_streaming_destroy(player->streamer);
6131                         player->streamer = NULL;
6132                 }
6133        }
6134 }
6135
6136 int
6137 _mmplayer_destroy(MMHandleType handle) // @
6138 {
6139         mm_player_t* player = MM_PLAYER_CAST(handle);
6140
6141         debug_fenter();
6142
6143         /* check player handle */
6144         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6145
6146         /* destroy can called at anytime */
6147         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
6148
6149         __mmplayer_release_extended_streaming(player);
6150
6151         /* release repeat thread */
6152         if ( player->repeat_thread_cond &&
6153                  player->repeat_thread_mutex &&
6154                  player->repeat_thread )
6155         {
6156                 player->repeat_thread_exit = TRUE;
6157                 g_cond_signal( player->repeat_thread_cond );
6158
6159                 debug_log("waitting for repeat thread exit\n");
6160                 g_thread_join ( player->repeat_thread );
6161                 g_mutex_free ( player->repeat_thread_mutex );
6162                 g_cond_free ( player->repeat_thread_cond );
6163                 debug_log("repeat thread released\n");
6164         }
6165
6166         if (MM_ERROR_NONE != _mmplayer_release_video_capture(player))
6167         {
6168                 debug_error("failed to release video capture\n");
6169                 return MM_ERROR_PLAYER_INTERNAL;
6170         }
6171
6172         /* withdraw asm */
6173         if ( MM_ERROR_NONE != _mmplayer_asm_deregister(&player->sm) )
6174         {
6175                 debug_error("failed to deregister asm server\n");
6176                 return MM_ERROR_PLAYER_INTERNAL;
6177         }
6178
6179         /* release pipeline */
6180         if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
6181         {
6182                 debug_error("failed to destory pipeline\n");
6183                 return MM_ERROR_PLAYER_INTERNAL;
6184         }
6185
6186         /* release attributes */
6187         _mmplayer_deconstruct_attribute( handle );
6188
6189         /* release factories */
6190         __mmplayer_release_factories( player );
6191
6192         /* release miscellaneous information */
6193         __mmplayer_release_misc( player );
6194
6195         /* release lock */
6196         if ( player->fsink_lock )
6197                 g_mutex_free( player->fsink_lock );
6198
6199         if ( player->msg_cb_lock )
6200                 g_mutex_free( player->msg_cb_lock );
6201
6202         if (player->lazy_pause_event_id) 
6203         {
6204                 g_source_remove (player->lazy_pause_event_id);
6205                 player->lazy_pause_event_id = 0;
6206         }
6207
6208         debug_fleave();
6209
6210         return MM_ERROR_NONE;
6211 }
6212
6213
6214 int 
6215 __mmplayer_init_extended_streaming(mm_player_t* player)
6216 {
6217         int ret = MM_ERROR_NONE;
6218         
6219         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6220
6221 #ifdef NO_USE_GST_HLSDEMUX
6222         /* prepare adaptive http streaming */
6223         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS)
6224         {
6225                 player->ahs_player = __mm_player_ahs_create ();
6226                 
6227                 if (NULL == player->ahs_player)
6228                 {
6229                         debug_error ("Unable to create AHS player\n");
6230                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
6231                 }
6232                 else
6233                 {
6234                         if ( !__mm_player_ahs_initialize (player->ahs_player, player->profile.uri_type, 
6235                                 player->profile.uri, player->pipeline->mainbin[MMPLAYER_M_SRC].gst) )
6236                         {
6237                                 debug_error ("failed to initialize ahs player\n");
6238                                 ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
6239                         }
6240                 }
6241         }
6242 #endif
6243
6244         if (MMPLAYER_IS_HTTP_PD(player))
6245         {
6246                 gboolean bret = FALSE;
6247                 gchar *src_uri = NULL;
6248
6249                 player->pd_downloader = _mmplayer_pd_create ();
6250
6251                 if ( !player->pd_downloader )
6252                 {
6253                         debug_error ("Unable to create PD Downloader...");
6254                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
6255                 }
6256                 
6257                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
6258                         src_uri = player->profile.uri;
6259                 
6260                 bret = _mmplayer_pd_initialize ((MMHandleType)player, src_uri, player->pd_file_location, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
6261                 
6262                 if (FALSE == bret)
6263                 {
6264                         debug_error ("Unable to create PD Downloader...");
6265                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
6266                 }
6267         }
6268
6269         return ret;
6270 }
6271
6272 int
6273 _mmplayer_realize(MMHandleType hplayer) // @
6274 {
6275         mm_player_t* player =  (mm_player_t*)hplayer;
6276         char *uri =NULL;
6277         void *param = NULL;
6278         int application_pid = -1;
6279         gboolean update_registry = FALSE;
6280         MMHandleType attrs = 0;
6281         int ret = MM_ERROR_NONE;
6282
6283         debug_fenter();
6284
6285         /* check player handle */
6286         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
6287
6288         /* check current state */
6289         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
6290
6291         attrs = MMPLAYER_GET_ATTRS(player);
6292         if ( !attrs )
6293         {
6294                 debug_error("fail to get attributes.\n");
6295                 return MM_ERROR_PLAYER_INTERNAL;
6296         }
6297
6298         mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
6299         player->sm.pid = application_pid;
6300
6301         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
6302         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
6303
6304         if (! __mmfplayer_parse_profile((const char*)uri, param, &player->profile) )
6305         {
6306                 debug_error("failed to parse profile\n");
6307                 return MM_ERROR_PLAYER_INVALID_URI;
6308         }
6309
6310         /* FIXIT : we can use thouse in player->profile directly */
6311         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
6312         {
6313                 player->mem_buf.buf = (char *)player->profile.mem;
6314                 player->mem_buf.len = player->profile.mem_size;
6315                 player->mem_buf.offset = 0;
6316         }
6317
6318         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
6319         {
6320                 debug_warning("mms protocol is not supported format.\n");
6321                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
6322         }
6323
6324         if (MMPLAYER_IS_STREAMING(player))
6325                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->live_state_change_timeout;
6326         else
6327                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout;
6328
6329         player->videodec_linked  = 0;
6330         player->videosink_linked = 0;
6331         player->audiodec_linked  = 0;
6332         player->audiosink_linked = 0;
6333         player->textsink_linked = 0;
6334
6335         /* set the subtitle ON default */
6336         player->is_subtitle_off = FALSE;
6337
6338         /* we need to update content attrs only the content has changed */
6339         player->need_update_content_attrs = TRUE;
6340         player->need_update_content_dur = FALSE;
6341
6342         /* registry should be updated for downloadable codec */
6343         mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
6344
6345         if ( update_registry )
6346         {
6347                 debug_log("updating registry...\n");
6348                 gst_update_registry();
6349
6350                 /* then we have to rebuild factories */
6351                 __mmplayer_release_factories( player );
6352                 __mmplayer_init_factories(player);
6353         }
6354
6355         /* realize pipeline */
6356         ret = __gst_realize( player );
6357         if ( ret != MM_ERROR_NONE )
6358         {
6359                 debug_error("fail to realize the player.\n");
6360         }
6361         else
6362         {
6363                 __mmplayer_init_extended_streaming(player);
6364         }
6365
6366         debug_fleave();
6367
6368         return ret;
6369 }
6370
6371 int
6372 __mmplayer_deinit_extended_streaming(mm_player_t *player)
6373 {
6374         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6375         
6376         /* destroy can called at anytime */
6377         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
6378         {
6379                 //__mmplayer_pd_deinitalize (player->ahs_player);
6380                 _mmplayer_pd_stop ((MMHandleType)player);
6381         }
6382
6383 #ifdef NO_USE_GST_HLSDEMUX
6384         /* destroy can called at anytime */
6385         if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
6386         {
6387                 __mm_player_ahs_stop (player->ahs_player);
6388                 //__mm_player_ahs_deinitalize (player->ahs_player);
6389         }
6390 #endif
6391         return MM_ERROR_NONE;
6392
6393 }
6394
6395 int
6396 _mmplayer_unrealize(MMHandleType hplayer) // @
6397 {
6398         mm_player_t* player = (mm_player_t*)hplayer;
6399         int ret = MM_ERROR_NONE;
6400
6401         debug_fenter();
6402
6403         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
6404
6405         /* check current state */
6406         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
6407
6408         __mmplayer_deinit_extended_streaming(player);
6409
6410         /* unrealize pipeline */
6411         ret = __gst_unrealize( player );
6412
6413         /* set player state if success */
6414         if ( MM_ERROR_NONE == ret )
6415         {
6416                 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP);
6417                 if ( ret )
6418                 {
6419                         debug_error("failed to set asm state to STOP\n");
6420                         return ret;
6421                 }
6422         }
6423
6424         debug_fleave();
6425
6426         return ret;
6427 }
6428
6429 int
6430 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
6431 {
6432         mm_player_t* player = (mm_player_t*)hplayer;
6433
6434         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6435
6436         return __gst_set_message_callback(player, callback, user_param);
6437 }
6438
6439 int
6440 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
6441 {
6442         mm_player_t *player = (mm_player_t*)hplayer;
6443
6444         return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
6445
6446         *state = MMPLAYER_CURRENT_STATE(player);
6447
6448         return MM_ERROR_NONE;
6449 }
6450
6451
6452 int
6453 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
6454 {
6455         mm_player_t* player = (mm_player_t*) hplayer;
6456         GstElement* vol_element = NULL;
6457         int i = 0;
6458
6459         debug_fenter();
6460
6461         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6462
6463         debug_log("volume [L]=%f:[R]=%f\n", 
6464                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
6465
6466         /* invalid factor range or not */
6467         for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
6468         {
6469                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
6470                         debug_error("Invalid factor! (valid factor:0~1.0)\n");
6471                         return MM_ERROR_INVALID_ARGUMENT;
6472                 }
6473         }
6474
6475         /* Save volume to handle. Currently the first array element will be saved. */
6476         player->sound.volume = volume.level[0];
6477
6478         /* check pipeline handle */
6479         if ( ! player->pipeline || ! player->pipeline->audiobin )
6480         {
6481                 debug_log("audiobin is not created yet\n");
6482                 debug_log("but, current stored volume will be set when it's created.\n");
6483
6484                 /* NOTE : stored volume will be used in create_audiobin
6485                  * returning MM_ERROR_NONE here makes application to able to
6486                  * set volume at anytime.
6487                  */
6488                 return MM_ERROR_NONE;
6489         }
6490
6491         /* setting volume to volume element */
6492         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
6493
6494         if ( vol_element )
6495         {
6496                 debug_log("volume is set [%f]\n", player->sound.volume);
6497                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
6498         }
6499
6500         debug_fleave();
6501
6502         return MM_ERROR_NONE;
6503 }
6504
6505
6506 int
6507 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
6508 {
6509         mm_player_t* player = (mm_player_t*) hplayer;
6510         int i = 0;
6511
6512         debug_fenter();
6513
6514         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6515         return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
6516
6517         /* returning stored volume */
6518         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
6519                 volume->level[i] = player->sound.volume;
6520
6521         debug_fleave();
6522
6523         return MM_ERROR_NONE;
6524 }
6525
6526
6527
6528 int
6529 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
6530 {
6531         mm_player_t* player = (mm_player_t*) hplayer;
6532         GstElement* vol_element = NULL;
6533
6534         debug_fenter();
6535
6536         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6537
6538         debug_log("mute : %d\n", mute);
6539
6540         /* mute value shoud 0 or 1 */
6541         if ( mute != 0 && mute != 1 )
6542         {
6543                 debug_error("bad mute value\n");
6544
6545                 /* FIXIT : definitly, we need _BAD_PARAM error code */
6546                 return MM_ERROR_INVALID_ARGUMENT;
6547         }
6548
6549
6550         /* just hold mute value if pipeline is not ready */
6551         if ( !player->pipeline || !player->pipeline->audiobin )
6552         {
6553                 debug_log("pipeline is not ready. holding mute value\n");
6554                 player->sound.mute = mute;
6555                 return MM_ERROR_NONE;
6556         }
6557
6558
6559         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
6560
6561         /* NOTE : volume will only created when the bt is enabled */
6562         if ( vol_element )
6563         {
6564                 g_object_set(vol_element, "mute", mute, NULL);
6565         }
6566         else
6567         {
6568                 debug_log("volume elemnet is not created. using volume in audiosink\n");
6569         }
6570
6571         player->sound.mute = mute;
6572
6573         debug_fleave();
6574
6575         return MM_ERROR_NONE;
6576 }
6577
6578 int
6579 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
6580 {
6581         mm_player_t* player = (mm_player_t*) hplayer;
6582         GstElement* vol_element = NULL;
6583
6584         debug_fenter();
6585
6586         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6587         return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
6588
6589         /* just hold mute value if pipeline is not ready */
6590         if ( !player->pipeline || !player->pipeline->audiobin )
6591         {
6592                 debug_log("pipeline is not ready. returning stored value\n");
6593                 *pmute = player->sound.mute;
6594                 return MM_ERROR_NONE;
6595         }
6596
6597
6598         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
6599
6600         if ( vol_element )
6601         {
6602                 g_object_get(vol_element, "mute", pmute, NULL);
6603                 debug_log("mute=%d\n\n", *pmute);
6604         }
6605         else
6606         {
6607                 *pmute = player->sound.mute;
6608         }
6609
6610         debug_fleave();
6611
6612         return MM_ERROR_NONE;
6613 }
6614
6615 int
6616 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
6617 {
6618         mm_player_t* player = (mm_player_t*) hplayer;
6619
6620         debug_fenter();
6621
6622         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6623         return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
6624
6625         player->video_stream_cb = callback;
6626         player->video_stream_cb_user_param = user_param;
6627         player->use_video_stream = TRUE;
6628         debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
6629
6630         debug_fleave();
6631
6632         return MM_ERROR_NONE;
6633 }
6634
6635 int
6636 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
6637 {
6638         mm_player_t* player = (mm_player_t*) hplayer;
6639
6640         debug_fenter();
6641
6642         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6643         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
6644
6645         player->audio_stream_cb = callback;
6646         player->audio_stream_cb_user_param = user_param;
6647         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
6648
6649         debug_fleave();
6650
6651         return MM_ERROR_NONE;
6652 }
6653
6654 int
6655 _mmplayer_set_audiobuffer_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
6656 {
6657         mm_player_t* player = (mm_player_t*) hplayer;
6658
6659         debug_fenter();
6660
6661         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6662         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
6663
6664         player->audio_buffer_cb = callback;
6665         player->audio_buffer_cb_user_param = user_param;
6666         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_buffer_cb);
6667
6668         debug_fleave();
6669
6670         return MM_ERROR_NONE;
6671 }
6672
6673 int
6674 _mmplayer_set_buffer_need_data_cb(MMHandleType hplayer, mm_player_buffer_need_data_callback callback, void *user_param) // @
6675 {
6676         mm_player_t* player = (mm_player_t*) hplayer;
6677
6678         debug_fenter();
6679
6680         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6681         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
6682
6683         player->need_data_cb = callback;
6684         player->buffer_cb_user_param = user_param;
6685
6686         debug_log("buffer need dataHandle value is %p : %p\n", player, player->need_data_cb);
6687
6688         debug_fleave();
6689
6690         return MM_ERROR_NONE;
6691 }
6692
6693 int
6694 _mmplayer_set_buffer_enough_data_cb(MMHandleType hplayer, mm_player_buffer_enough_data_callback callback, void *user_param) // @
6695 {
6696         mm_player_t* player = (mm_player_t*) hplayer;
6697
6698         debug_fenter();
6699
6700         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6701         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
6702
6703         player->enough_data_cb = callback;
6704         player->buffer_cb_user_param = user_param;
6705
6706         debug_log("buffer enough data cb Handle value is %p : %p\n", player, player->enough_data_cb);
6707
6708         debug_fleave();
6709                 
6710         return MM_ERROR_NONE;
6711 }
6712
6713 int
6714 _mmplayer_set_buffer_seek_data_cb(MMHandleType hplayer, mm_player_buffer_seek_data_callback callback, void *user_param) // @
6715 {
6716         mm_player_t* player = (mm_player_t*) hplayer;
6717
6718         debug_fenter();
6719
6720         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6721         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
6722
6723         player->seek_data_cb = callback;
6724         player->buffer_cb_user_param = user_param;
6725
6726         debug_log("buffer seek data cb Handle value is %p : %p\n", player, player->seek_data_cb);
6727
6728         debug_fleave();
6729
6730         return MM_ERROR_NONE;
6731 }
6732
6733 int __mmplayer_start_extended_streaming(mm_player_t *player)
6734 {       
6735         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6736
6737         if (MMPLAYER_IS_HTTP_PD(player) && player->pd_downloader)
6738         {
6739                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
6740                 {
6741                         gboolean bret = FALSE;
6742                         
6743                         bret = _mmplayer_pd_start ((MMHandleType)player);
6744                         if (FALSE == bret)
6745                         {
6746                                 debug_error ("ERROR while starting PD...\n");
6747                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
6748                         }
6749                 }
6750         }
6751
6752 #ifdef NO_USE_GST_HLSDEMUX
6753         if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
6754         {               
6755                 if ( !__mm_player_ahs_start (player->ahs_player))
6756                 {
6757                         debug_error("failed to start ahs\n");
6758                         return MM_ERROR_PLAYER_INTERNAL;
6759                 }
6760         }
6761 #endif
6762         return MM_ERROR_NONE;
6763 }
6764
6765 int
6766 _mmplayer_start(MMHandleType hplayer) // @
6767 {
6768         mm_player_t* player = (mm_player_t*) hplayer;
6769         gint ret = MM_ERROR_NONE;
6770         
6771         debug_fenter();
6772
6773         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6774
6775         /* check current state */
6776         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
6777
6778         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING);
6779         if ( ret != MM_ERROR_NONE )
6780         {
6781                 debug_error("failed to set asm state to PLAYING\n");
6782                 return ret;
6783         }
6784
6785         /* NOTE : we should check and create pipeline again if not created as we destroy
6786          * whole pipeline when stopping in streamming playback
6787          */
6788         if ( ! player->pipeline )
6789         {
6790                 ret = __gst_realize( player ); 
6791                 if ( MM_ERROR_NONE != ret )
6792                 {
6793                         debug_error("failed to realize before starting. only in streamming\n");
6794                         return ret;
6795                 }
6796         }
6797
6798         if (__mmplayer_start_extended_streaming(player) != MM_ERROR_NONE)
6799                 return MM_ERROR_PLAYER_INTERNAL;
6800         
6801         /* start pipeline */
6802         ret = __gst_start( player );
6803         if ( ret != MM_ERROR_NONE )
6804         {
6805                 debug_error("failed to start player.\n");
6806         }
6807
6808         debug_fleave();
6809         
6810         return ret;
6811 }
6812
6813
6814
6815 /* NOTE: post "not supported codec message" to application
6816  * when one codec is not found during AUTOPLUGGING in MSL.
6817  * So, it's separated with error of __mmplayer_gst_callback().
6818  * And, if any codec is not found, don't send message here.
6819  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
6820  */
6821 int
6822 __mmplayer_post_missed_plugin(mm_player_t* player)
6823 {
6824         MMMessageParamType msg_param;
6825         memset (&msg_param, 0, sizeof(MMMessageParamType));
6826         gboolean post_msg_direct = FALSE;
6827
6828         debug_fenter();
6829
6830         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6831
6832         debug_log("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
6833                         player->not_supported_codec, player->can_support_codec);
6834
6835         if( player->not_found_demuxer )
6836         {
6837                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
6838                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
6839
6840                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
6841                 MMPLAYER_FREEIF(msg_param.data);
6842
6843                 return MM_ERROR_NONE;
6844         }
6845
6846         if (player->not_supported_codec)
6847         {
6848                 if ( player->can_support_codec ) // There is one codec to play
6849                 {
6850                         post_msg_direct = TRUE;
6851                 }
6852                 else
6853                 {
6854                         if ( player->pipeline->audiobin ) // Some content has only PCM data in container.
6855                                 post_msg_direct = TRUE;
6856                 }
6857
6858                 if ( post_msg_direct )
6859                 {
6860                         MMMessageParamType msg_param;
6861                         memset (&msg_param, 0, sizeof(MMMessageParamType));
6862
6863                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
6864                         {
6865                                 debug_warning("not found AUDIO codec, posting error code to application.\n");
6866
6867                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
6868                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
6869                         }
6870                         else if ( player->not_supported_codec ==  MISSING_PLUGIN_VIDEO )
6871                         {
6872                                 debug_warning("not found VIDEO codec, posting error code to application.\n");
6873
6874                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
6875                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
6876                         }
6877
6878                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
6879
6880                         MMPLAYER_FREEIF(msg_param.data);
6881
6882                         return MM_ERROR_NONE;
6883                 }
6884                 else // no any supported codec case 
6885                 {
6886                         debug_warning("not found any codec, posting error code to application.\n");
6887                         
6888                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
6889                         {
6890                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
6891                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
6892                         }
6893                         else
6894                         {
6895                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
6896                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
6897                         }
6898
6899                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
6900                         
6901                         MMPLAYER_FREEIF(msg_param.data);
6902                 }
6903         }
6904         
6905         debug_fleave();
6906
6907         return MM_ERROR_NONE;
6908 }
6909
6910 /* NOTE : it should be able to call 'stop' anytime*/
6911 int
6912 _mmplayer_stop(MMHandleType hplayer) // @
6913 {
6914         mm_player_t* player = (mm_player_t*)hplayer;
6915         int ret = MM_ERROR_NONE;
6916
6917         debug_fenter();
6918
6919         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6920
6921         if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
6922         {
6923                 __mm_player_ahs_stop (player->ahs_player);
6924         }
6925
6926         /* check current state */
6927         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
6928
6929         /* NOTE : application should not wait for EOS after calling STOP */
6930         __mmplayer_cancel_delayed_eos( player );
6931
6932         /* stop pipeline */
6933         ret = __gst_stop( player );
6934
6935         if ( ret != MM_ERROR_NONE )
6936         {
6937                 debug_error("failed to stop player.\n");
6938         }
6939
6940         debug_fleave();
6941
6942         return ret;
6943 }
6944
6945
6946 int
6947 _mmplayer_pause(MMHandleType hplayer) // @
6948 {
6949         mm_player_t* player = (mm_player_t*)hplayer;
6950         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
6951         GstFormat fmt = GST_FORMAT_TIME;
6952         signed long long pos_msec = 0;
6953         int ret = MM_ERROR_NONE;
6954
6955         debug_fenter();
6956
6957         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6958
6959         /* check current state */
6960         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
6961
6962         /* NOTE : store current point to overcome some bad operation
6963          * ( returning zero when getting current position in paused state) of some
6964          * elements
6965          */
6966         current_state = MMPLAYER_CURRENT_STATE(player);
6967         if ( current_state == MM_PLAYER_STATE_PLAYING )
6968         {
6969                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,        &fmt, &pos_msec);
6970                 if ( ! ret )
6971                         debug_warning("getting current position failed in paused\n");
6972
6973                 player->last_position = pos_msec;
6974         }
6975
6976         /* pause pipeline */
6977         ret = __gst_pause( player, FALSE );
6978
6979         if ( MMPLAYER_IS_HTTP_LIVE_STREAMING ( player ))
6980         {
6981                 //__mm_player_ahs_pause (player->ahs_player); // Not yet implemented
6982         }
6983
6984         if ( ret != MM_ERROR_NONE )
6985         {
6986                 debug_error("failed to pause player.\n");
6987         }
6988
6989         debug_fleave();
6990
6991         return ret;
6992 }
6993
6994 int
6995 _mmplayer_resume(MMHandleType hplayer)
6996 {
6997         mm_player_t* player = (mm_player_t*)hplayer;
6998         int ret = MM_ERROR_NONE;
6999
7000         debug_fenter();
7001
7002         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7003
7004         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING);
7005         if ( ret )
7006         {
7007                 debug_error("failed to set asm state to PLAYING\n");
7008                 return ret;
7009         }
7010
7011         /* check current state */
7012         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
7013
7014         /* resume pipeline */
7015         ret = __gst_resume( player, FALSE );
7016
7017         if ( ret != MM_ERROR_NONE )
7018         {
7019                 debug_error("failed to resume player.\n");
7020         }
7021
7022
7023         debug_fleave();
7024
7025         return ret;
7026 }
7027
7028 int
7029 __mmplayer_set_play_count(mm_player_t* player, gint count)
7030 {
7031         MMHandleType attrs = 0;
7032
7033         debug_fenter();
7034
7035         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7036
7037         attrs =  MMPLAYER_GET_ATTRS(player);
7038         if ( !attrs )
7039         {
7040                 debug_error("fail to get attributes.\n");
7041                 return MM_ERROR_PLAYER_INTERNAL;
7042         }
7043
7044         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
7045         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
7046                 debug_error("failed to commit\n");
7047
7048         debug_fleave();
7049
7050         return  MM_ERROR_NONE;
7051 }
7052
7053 int
7054 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
7055 {
7056         mm_player_t* player = (mm_player_t*)hplayer;
7057         gint64 start_pos = 0;
7058         gint64 end_pos = 0;
7059         gint infinity = -1;
7060
7061         debug_fenter();
7062
7063         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7064         return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
7065
7066         player->section_repeat = TRUE;
7067         player->section_repeat_start = start;
7068         player->section_repeat_end = end;
7069
7070         start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
7071         end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
7072
7073         __mmplayer_set_play_count( player, infinity );
7074
7075         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
7076                                         1.0,
7077                                         GST_FORMAT_TIME,
7078                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
7079                                         GST_SEEK_TYPE_SET, start_pos,
7080                                         GST_SEEK_TYPE_SET, end_pos)))
7081         {
7082                 debug_error("failed to activate section repeat\n");
7083
7084                 return MM_ERROR_PLAYER_SEEK;
7085         }
7086
7087         debug_log("succeeded to set section repeat from %d to %d\n",
7088                 player->section_repeat_start, player->section_repeat_end);
7089
7090         debug_fleave();
7091
7092         return  MM_ERROR_NONE;
7093 }
7094
7095 static int 
7096 __mmplayer_set_pcm_extraction(mm_player_t* player)
7097 {
7098         guint64 start_nsec = 0;
7099         guint64 end_nsec = 0;
7100         guint64 dur_nsec = 0;
7101         guint64 dur_msec = 0;
7102         GstFormat fmt = GST_FORMAT_TIME;
7103         int required_start = 0;
7104         int required_end = 0;
7105         int ret = 0;
7106
7107         debug_fenter();
7108
7109         return_val_if_fail( player, FALSE );
7110
7111         mm_attrs_multiple_get(player->attrs,
7112                 NULL,
7113                 "pcm_extraction_start_msec", &required_start,
7114                 "pcm_extraction_end_msec", &required_end,
7115                 NULL);
7116
7117         debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
7118
7119         if (required_start == 0 && required_end == 0)
7120         {
7121                 debug_log("extracting entire stream");
7122                 return MM_ERROR_NONE;
7123         }
7124         else if (required_start < 0 || required_start > required_end || required_end < 0 )
7125         {
7126                 debug_log("invalid range for pcm extraction");
7127                 return MM_ERROR_INVALID_ARGUMENT;
7128         }
7129
7130         /* get duration */
7131         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec);
7132         if ( !ret )
7133         {
7134                 debug_error("failed to get duration");
7135                 return MM_ERROR_PLAYER_INTERNAL;
7136         }
7137         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
7138
7139         if (dur_msec < required_end) // FIXME
7140         {
7141                 debug_log("invalid end pos for pcm extraction");
7142                 return MM_ERROR_INVALID_ARGUMENT;
7143         }
7144
7145         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
7146         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
7147
7148         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
7149                                         1.0,
7150                                         GST_FORMAT_TIME,
7151                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
7152                                         GST_SEEK_TYPE_SET, start_nsec,
7153                                         GST_SEEK_TYPE_SET, end_nsec)))
7154         {
7155                 debug_error("failed to seek for pcm extraction\n");
7156
7157                 return MM_ERROR_PLAYER_SEEK;
7158         }
7159
7160         debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
7161
7162         debug_fleave(); 
7163
7164         return MM_ERROR_NONE;
7165 }
7166
7167 int
7168 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
7169 {
7170         mm_player_t* player = (mm_player_t*)hplayer;
7171         gint64 cur_pos = 0;
7172         GstFormat fmt  = GST_FORMAT_TIME;
7173         gint onetime = 1;
7174
7175         debug_fenter();
7176
7177         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7178
7179         player->section_repeat = FALSE;
7180
7181         __mmplayer_set_play_count( player, onetime );
7182
7183         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &cur_pos);
7184
7185         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
7186                                         1.0,
7187                                         GST_FORMAT_TIME,
7188                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
7189                                         GST_SEEK_TYPE_SET, cur_pos,
7190                                         GST_SEEK_TYPE_SET, player->duration )))
7191         {
7192                 debug_error("failed to deactivate section repeat\n");
7193
7194                 return MM_ERROR_PLAYER_SEEK;
7195         }
7196
7197         debug_fenter();
7198
7199         return MM_ERROR_NONE;
7200 }
7201
7202 int
7203 _mmplayer_set_playspeed(MMHandleType hplayer, gdouble rate)
7204 {
7205         mm_player_t* player = (mm_player_t*)hplayer;
7206         signed long long pos_msec = 0;
7207         int ret = MM_ERROR_NONE;
7208         int mute = FALSE;
7209         GstFormat format =GST_FORMAT_TIME;
7210         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7211         debug_fenter();
7212
7213         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7214         return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
7215
7216         /* The sound of video is not supported under 0.0 and over 2.0. */
7217         if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
7218         {
7219                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
7220                         mute = TRUE;
7221         }
7222         _mmplayer_set_mute(hplayer, mute);
7223
7224         if (player->playback_rate == rate)
7225                 return MM_ERROR_NONE;
7226
7227         /* If the position is reached at start potion during fast backward, EOS is posted.
7228          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
7229          * */
7230         player->playback_rate = rate;
7231
7232         current_state = MMPLAYER_CURRENT_STATE(player);
7233
7234         if ( current_state != MM_PLAYER_STATE_PAUSED )
7235                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &pos_msec);
7236
7237         debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
7238
7239         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
7240                 || ( ! ret ))
7241                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
7242         {
7243                 debug_warning("returning last point : %lld\n", player->last_position );
7244                 pos_msec = player->last_position;
7245         }
7246
7247         if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
7248                                 rate,
7249                                 GST_FORMAT_TIME,
7250                                 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
7251                                 //( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT),
7252                                 GST_SEEK_TYPE_SET, pos_msec,
7253                                 //GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
7254                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)))
7255         {
7256                 debug_error("failed to set speed playback\n");
7257                 return MM_ERROR_PLAYER_SEEK;
7258         }
7259
7260         debug_log("succeeded to set speed playback as %fl\n", rate);
7261
7262         debug_fleave();
7263
7264         return MM_ERROR_NONE;;
7265 }
7266
7267 int
7268 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
7269 {
7270         mm_player_t* player = (mm_player_t*)hplayer;
7271         int ret = MM_ERROR_NONE;
7272
7273         debug_fenter();
7274
7275         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7276
7277         ret = __gst_set_position ( player, format, (unsigned long)position );
7278
7279         debug_fleave(); 
7280
7281         return ret;
7282 }
7283
7284 int
7285 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
7286 {
7287         mm_player_t* player = (mm_player_t*)hplayer;
7288         int ret = MM_ERROR_NONE;
7289
7290         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7291
7292         ret = __gst_get_position ( player, format, position );
7293         
7294         return ret;
7295 }
7296
7297 int
7298 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
7299 {
7300         mm_player_t* player = (mm_player_t*)hplayer;
7301         int ret = MM_ERROR_NONE;
7302
7303         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7304
7305         ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
7306
7307         return ret;
7308 }
7309
7310 int
7311 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
7312 {
7313         mm_player_t* player = (mm_player_t*)hplayer;
7314         int ret = MM_ERROR_NONE;
7315
7316         debug_fenter();
7317
7318         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7319
7320         ret = __gst_adjust_subtitle_position(player, format, position);
7321
7322         debug_fleave();
7323
7324         return ret;
7325 }
7326
7327 static gboolean
7328 __mmplayer_is_midi_type( gchar* str_caps)
7329 {
7330         if ( ( g_strrstr(str_caps, "audio/midi") ) ||
7331                 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
7332                 ( g_strrstr(str_caps, "application/x-smaf") ) ||
7333                 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
7334                 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
7335                 ( g_strrstr(str_caps, "audio/xmf") ) ||
7336                 ( g_strrstr(str_caps, "audio/mxmf") ) )
7337         {
7338                 debug_log("midi\n");
7339
7340                 return TRUE;
7341         }
7342
7343         debug_log("not midi.\n");
7344
7345         return FALSE;
7346 }
7347
7348 static gboolean
7349 __mmplayer_is_amr_type (gchar *str_caps)
7350 {
7351         if ((g_strrstr(str_caps, "AMR")) ||
7352                 (g_strrstr(str_caps, "amr")))
7353         {
7354                 return TRUE;
7355         }
7356         return FALSE;
7357 }
7358
7359 static gboolean
7360 __mmplayer_is_only_mp3_type (gchar *str_caps)
7361 {
7362         if (g_strrstr(str_caps, "application/x-id3") ||
7363                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
7364         {
7365                 return TRUE;
7366         }
7367         return FALSE;
7368 }
7369
7370 static void
7371 __mmplayer_typefind_have_type(  GstElement *tf, guint probability,  // @
7372 GstCaps *caps, gpointer data)
7373 {
7374         mm_player_t* player = (mm_player_t*)data;
7375         GstPad* pad = NULL;
7376
7377         debug_fenter();
7378
7379         return_if_fail( player && tf && caps );
7380
7381         /* store type string */
7382         MMPLAYER_FREEIF(player->type);
7383         player->type = gst_caps_to_string(caps);
7384         if (player->type)
7385                 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
7386
7387         /* midi type should be stored because it will be used to set audio gain in avsysauiosink */
7388         if ( __mmplayer_is_midi_type(player->type))
7389         {
7390                 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
7391         }
7392         else if (__mmplayer_is_amr_type(player->type))
7393         {
7394                 player->bypass_sound_effect = FALSE;
7395                 if ( (PLAYER_INI()->use_audio_filter_preset || PLAYER_INI()->use_audio_filter_custom) )
7396                 {
7397                         if ( player->audio_filter_info.filter_type == MM_AUDIO_FILTER_TYPE_PRESET )
7398                         {
7399                                 if (!_mmplayer_sound_filter_preset_apply(player, player->audio_filter_info.preset))
7400                                 {
7401                                         debug_msg("apply sound effect(preset:%d) setting success\n",player->audio_filter_info.preset);
7402                                 }
7403                         }
7404                         else if ( player->audio_filter_info.filter_type == MM_AUDIO_FILTER_TYPE_CUSTOM )
7405                         {
7406                                 if (!_mmplayer_sound_filter_custom_apply(player))
7407                                 {
7408                                         debug_msg("apply sound effect(custom) setting success\n");
7409                                 }
7410                         }
7411                 }
7412         }
7413         else if ( g_strrstr(player->type, "application/x-hls"))
7414         {
7415                 /* If it can't know exact type when it parses uri because of redirection case,
7416                   * it will be fixed by typefinder here.
7417                   */
7418                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
7419         }
7420
7421         pad = gst_element_get_static_pad(tf, "src");
7422         if ( !pad )
7423         {
7424                 debug_error("fail to get typefind src pad.\n");
7425                 return;
7426         }
7427
7428
7429         /* try to plug */
7430         if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
7431         {
7432                 debug_error("failed to autoplug for type : %s\n", player->type);
7433
7434                 if ( ( PLAYER_INI()->async_start ) &&
7435                 ( player->posted_msg == FALSE ) )
7436                 {
7437                         __mmplayer_post_missed_plugin( player );
7438                 }
7439                         
7440                 goto DONE;
7441         }
7442
7443         /* finish autopluging if no dynamic pad waiting */
7444         if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
7445         {
7446                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
7447                 {
7448                         __mmplayer_pipeline_complete( NULL, (gpointer)player );
7449                 }
7450         }
7451
7452 DONE:
7453         gst_object_unref( GST_OBJECT(pad) );
7454
7455         debug_fleave(); 
7456
7457         return;
7458 }
7459
7460 static gboolean
7461 __mmplayer_warm_up_video_codec( mm_player_t* player,  GstElementFactory *factory)
7462 {
7463         GstElement *element;
7464         GstStateChangeReturn  ret;
7465         gboolean usable = TRUE;
7466
7467         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7468         return_val_if_fail ( factory, MM_ERROR_COMMON_INVALID_ARGUMENT );
7469
7470         element = gst_element_factory_create (factory, NULL);
7471
7472         ret = gst_element_set_state (element, GST_STATE_READY);
7473
7474         if (ret != GST_STATE_CHANGE_SUCCESS)
7475         {
7476                 debug_error ("resource conflict so,  %s unusable\n", GST_PLUGIN_FEATURE_NAME (factory));
7477                 usable = FALSE;
7478         }
7479
7480         gst_element_set_state (element, GST_STATE_NULL);
7481         gst_object_unref (element);
7482
7483         return usable;
7484 }
7485
7486 /* it will return first created element */
7487 static gboolean
7488 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
7489 {
7490         MMPlayerGstElement* mainbin = NULL;
7491         const char* mime = NULL;
7492         const GList* item = NULL;
7493         const gchar* klass = NULL;
7494         GstCaps* res = NULL;
7495         gboolean skip = FALSE;
7496         GstPad* queue_pad = NULL;
7497         GstElement* queue = NULL;
7498         GstElement *element = NULL;
7499
7500         debug_fenter();
7501
7502         return_val_if_fail( player &&
7503                                                 player->pipeline &&
7504                                                 player->pipeline->mainbin,
7505                                                 FALSE );
7506
7507
7508         mainbin = player->pipeline->mainbin;
7509
7510         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
7511
7512         /* return if we got raw output */
7513         if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw") ||g_str_has_prefix(mime, "text/plain") )
7514         {
7515
7516                 element = (GstElement*)gst_pad_get_parent(pad);
7517
7518
7519 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
7520  * No queue will be added. I think it can caused breaking sound when playing raw audio
7521  * frames but there's no different. Decodebin also doesn't add with those wav fils.
7522  * Anyway, currentely raw-queue seems not necessary.
7523  */
7524 #if 1
7525
7526                 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
7527                  * has linked. if so, we need to add queue for quality of output. note that
7528                  * decodebin also has same problem.
7529                  */
7530
7531                 klass = gst_element_factory_get_klass( gst_element_get_factory(element) );
7532
7533                 /* add queue if needed */
7534                 if( g_strrstr(klass, "Demux") ||
7535                 g_strrstr(klass, "Depayloader") ||
7536                         g_strrstr(klass, "Parse") )
7537                 {
7538                         debug_log("adding raw queue\n");
7539
7540                         queue = gst_element_factory_make("queue", NULL);
7541                         if ( ! queue )
7542                         {
7543                                 debug_warning("failed to create queue\n");
7544                                 goto ERROR;
7545                         }
7546
7547                         /* warmup */
7548                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
7549                         {
7550                                 debug_warning("failed to set state READY to queue\n");
7551                                 goto ERROR;
7552                         }
7553
7554                         /* add to pipeline */
7555                         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
7556                         {
7557                                 debug_warning("failed to add queue\n");
7558                                 goto ERROR;
7559                         }
7560
7561                         /* link queue */
7562                         queue_pad = gst_element_get_static_pad(queue, "sink");
7563
7564                         if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
7565                         {
7566                                 debug_warning("failed to link queue\n");
7567                                 goto ERROR;
7568                         }
7569                         gst_object_unref ( GST_OBJECT(queue_pad) );
7570                         queue_pad = NULL;
7571
7572                         /* running */
7573                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
7574                         {
7575                                 debug_warning("failed to set state READY to queue\n");
7576                                 goto ERROR;
7577                         }
7578
7579                         /* replace given pad to queue:src */
7580                         pad = gst_element_get_static_pad(queue, "src");
7581                         if ( ! pad )
7582                         {
7583                                 debug_warning("failed to get pad from queue\n");
7584                                 goto ERROR;
7585                         }
7586                 }
7587 #endif
7588                 /* check if player can do start continually */
7589                 MMPLAYER_CHECK_CMD_IF_EXIT(player);
7590
7591                 if(__mmplayer_link_sink(player,pad))
7592                  __mmplayer_gst_decode_callback(element, pad, FALSE, player);
7593
7594                 gst_object_unref( GST_OBJECT(element));
7595                 element = NULL;
7596
7597
7598                 return TRUE;
7599         }
7600
7601         item = player->factories;
7602         for(; item != NULL ; item = item->next)
7603         {
7604
7605                 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
7606                 const GList *pads;
7607                 gint idx = 0;
7608
7609                 skip = FALSE;
7610
7611                 /* filtering exclude keyword */
7612                 for ( idx = 0; PLAYER_INI()->exclude_element_keyword[idx][0] != '\0'; idx++ )
7613                 {
7614                         if ( g_strrstr(GST_PLUGIN_FEATURE_NAME (factory),
7615                                         PLAYER_INI()->exclude_element_keyword[idx] ) )
7616                         {
7617                                 debug_warning("skipping [%s] by exculde keyword [%s]\n",
7618                                         GST_PLUGIN_FEATURE_NAME (factory),
7619                                         PLAYER_INI()->exclude_element_keyword[idx] );
7620
7621                                 skip = TRUE;
7622                                 break;
7623                         }
7624                 }
7625
7626                 if ( skip ) continue;
7627
7628
7629                 /* check factory class for filtering */
7630                 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory));
7631
7632                 /* NOTE : msl don't need to use image plugins.
7633                  * So, those plugins should be skipped for error handling.
7634                  */
7635                 if ( g_strrstr(klass, "Codec/Decoder/Image") )
7636                 {
7637                         debug_log("player doesn't need [%s] so, skipping it\n",
7638                                 GST_PLUGIN_FEATURE_NAME (factory) );
7639
7640                         continue;
7641                 }
7642
7643
7644                 /* check pad compatability */
7645                 for(pads = gst_element_factory_get_static_pad_templates(factory);
7646                      pads != NULL; pads=pads->next)
7647                {
7648                        GstStaticPadTemplate *temp1 = pads->data;
7649                         GstCaps* static_caps = NULL;
7650
7651                         if( temp1->direction != GST_PAD_SINK ||
7652                                 temp1->presence != GST_PAD_ALWAYS)
7653                                 continue;
7654
7655
7656                         if ( GST_IS_CAPS( &temp1->static_caps.caps) )
7657                         {
7658                                 /* using existing caps */
7659                                 static_caps = gst_caps_ref( &temp1->static_caps.caps );
7660                         }
7661                         else
7662                         {
7663                                 /* create one */
7664                                 static_caps = gst_caps_from_string ( temp1->static_caps.string );
7665                         }
7666
7667                         res = gst_caps_intersect(caps, static_caps);
7668
7669                         gst_caps_unref( static_caps );
7670                         static_caps = NULL;
7671
7672                         if( res && !gst_caps_is_empty(res) )
7673                         {
7674                                 GstElement *new_element;
7675                                 GList *elements = player->parsers;
7676                                 char *name_template = g_strdup(temp1->name_template);
7677                                 gchar *name_to_plug = GST_PLUGIN_FEATURE_NAME(factory);
7678
7679                                 gst_caps_unref(res);
7680
7681                                 debug_log("found %s to plug\n", name_to_plug);
7682
7683                                 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
7684                                 if ( ! new_element )
7685                                 {
7686                                         debug_error("failed to create element [%s]. continue with next.\n",
7687                                                 GST_PLUGIN_FEATURE_NAME (factory));
7688
7689                                         MMPLAYER_FREEIF(name_template);
7690
7691                                         continue;
7692                                 }
7693
7694                                 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
7695                                  * because parser can accept its own output as input.
7696                                  */
7697                                 if (g_strrstr(klass, "Parser"))
7698                                 {
7699                                         gchar *selected = NULL;
7700
7701                                         for ( ; elements; elements = g_list_next(elements))
7702                                         {
7703                                                 gchar *element_name = elements->data;
7704
7705                                                 if (g_strrstr(element_name, name_to_plug))
7706                                                 {
7707                                                         debug_log("but, %s already linked, so skipping it\n", name_to_plug);
7708                                                         skip = TRUE;
7709                                                 }
7710                                         }
7711
7712                                         if (skip) continue;
7713
7714                                         selected = g_strdup(name_to_plug);
7715
7716                                         player->parsers = g_list_append(player->parsers, selected);
7717                                 }
7718
7719                                 /* store specific handles for futher control */
7720                                 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
7721                         {
7722                                         /* FIXIT : first value will be overwritten if there's more
7723                                          * than 1 demuxer/parser
7724                                          */
7725                                         debug_log("plugged element is demuxer. take it\n");
7726                                         mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
7727                                         mainbin[MMPLAYER_M_DEMUX].gst = new_element;
7728                                 }
7729                                 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
7730                                 {                                                                       
7731                                     if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
7732                                     {
7733                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
7734                                                 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
7735                                                 mainbin[MMPLAYER_M_DEC1].gst = new_element;
7736                                     }
7737                                     else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
7738                                     {
7739                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
7740                                                 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
7741                                                 mainbin[MMPLAYER_M_DEC2].gst = new_element;
7742                                     }
7743
7744                                         /* NOTE : IF one codec is found, add it to supported_codec and remove from
7745                                          * missing plugin. Both of them are used to check what's supported codec
7746                                          * before returning result of play start. And, missing plugin should be
7747                                          * updated here for multi track files.
7748                                          */
7749                                         if(g_str_has_prefix(mime, "video"))
7750                                         {
7751                                                 GstPad *src_pad = NULL;
7752                                                 GstPadTemplate *pad_templ = NULL;
7753                                                 GstCaps *caps = NULL;
7754                                                 gchar *caps_type = NULL;
7755                                                         
7756                                                 debug_log("found VIDEO decoder\n");
7757                                                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
7758                                                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
7759
7760                                                 src_pad = gst_element_get_static_pad (new_element, "src");
7761                                                 pad_templ = gst_pad_get_pad_template (src_pad);
7762                                                 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
7763
7764                                                 caps_type = gst_caps_to_string(caps);
7765
7766                                                 if ( g_strrstr( caps_type, "ST12") )
7767                                                         player->is_nv12_tiled = TRUE;
7768
7769                                                 /* clean */
7770                                                 MMPLAYER_FREEIF( caps_type );
7771                                                 gst_object_unref (src_pad);
7772                                         }
7773                                         else if (g_str_has_prefix(mime, "audio"))
7774                                         {
7775                                                 debug_log("found AUDIO decoder\n");
7776                                                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
7777                                                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
7778                                         }
7779                                 }
7780                                 if ( ! __mmplayer_close_link(player, pad, new_element,
7781                                             name_template,gst_element_factory_get_static_pad_templates(factory)) )
7782                                 {
7783                                         if (player->keep_detecting_vcodec)
7784                                                 continue;
7785
7786                                         /* Link is failed even though a supportable codec is found. */
7787                                         __mmplayer_check_not_supported_codec(player, (gchar *)mime);
7788
7789                                         MMPLAYER_FREEIF(name_template);
7790                                         debug_error("failed to call _close_link\n");
7791                                         return FALSE;
7792                                 }
7793
7794                                 MMPLAYER_FREEIF(name_template);
7795                                 return TRUE;
7796                         }
7797
7798                         gst_caps_unref(res);
7799
7800                         break;
7801                 }
7802         }
7803
7804         /* There is no any found codec. */
7805         __mmplayer_check_not_supported_codec(player,(gchar *)mime);
7806
7807         debug_error("failed to autoplug\n");
7808
7809         debug_fleave();
7810         
7811         return FALSE;
7812
7813
7814 ERROR:
7815
7816         /* release */
7817         if ( queue )
7818                 gst_object_unref( queue );
7819
7820
7821         if ( queue_pad )
7822                 gst_object_unref( queue_pad );
7823
7824         if ( element )
7825                 gst_object_unref ( element );
7826
7827         return FALSE;
7828 }
7829
7830
7831 static
7832 int __mmplayer_check_not_supported_codec(mm_player_t* player, gchar* mime)
7833 {
7834         debug_fenter();
7835
7836         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7837         return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
7838
7839         debug_log("mimetype to check: %s\n", mime );
7840
7841         /* add missing plugin */
7842         /* NOTE : msl should check missing plugin for image mime type.
7843          * Some motion jpeg clips can have playable audio track.
7844          * So, msl have to play audio after displaying popup written video format not supported.
7845          */
7846         if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
7847         {
7848                 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
7849                 {
7850                         debug_log("not found demuxer\n");
7851                         player->not_found_demuxer = TRUE;
7852                         player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
7853
7854                         goto DONE;
7855                 }
7856         }
7857
7858         if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
7859         {
7860                 debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
7861                         player->can_support_codec, player->videodec_linked, player->audiodec_linked);
7862
7863                 /* check that clip have multi tracks or not */
7864                 if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
7865                 {
7866                         debug_log("video plugin is already linked\n");
7867                 }
7868                 else
7869                 {
7870                         debug_warning("add VIDEO to missing plugin\n");
7871                         player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
7872                 }
7873         }
7874         else if ( g_str_has_prefix(mime, "audio") )
7875         {
7876                 if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
7877                 {
7878                         debug_log("audio plugin is already linked\n");
7879                 }
7880                 else
7881                 {
7882                         debug_warning("add AUDIO to missing plugin\n");
7883                         player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
7884                 }
7885         }
7886
7887 DONE:
7888         debug_fleave(); 
7889
7890         return MM_ERROR_NONE;
7891 }
7892
7893
7894 static void __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data) // @
7895 {
7896     mm_player_t* player = (mm_player_t*)data;
7897
7898         debug_fenter();
7899
7900         return_if_fail( player );
7901
7902         /* remove fakesink */
7903         if ( ! __mmplayer_gst_remove_fakesink( player,
7904                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
7905         {
7906                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
7907                  * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
7908                  * source element are not same. To overcome this situation, this function will called
7909                  * several places and several times. Therefore, this is not an error case.
7910                  */
7911                 return;
7912         }
7913         debug_log("pipeline has completely constructed\n");
7914
7915         player->pipeline_is_constructed = TRUE;
7916         
7917         if ( ( PLAYER_INI()->async_start ) &&
7918                 ( player->posted_msg == FALSE ) )
7919         {
7920                 __mmplayer_post_missed_plugin( player );
7921         }
7922         
7923         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complate" );
7924 }
7925
7926 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
7927 {
7928         debug_fenter();
7929
7930         return_val_if_fail ( player, FALSE );
7931
7932
7933         if ( MMPLAYER_IS_STREAMING(player) )
7934                 return FALSE;
7935
7936         /* This callback can be set to music player only. */
7937         if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
7938         {
7939                 debug_warning("audio callback is not supported for video");
7940                 return FALSE;
7941         }
7942
7943         if (player->audio_stream_cb)
7944         {
7945                 {
7946                         GstPad *pad = NULL;
7947
7948                         pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
7949
7950                         if ( !pad )
7951                         {
7952                                 debug_error("failed to get sink pad from audiosink to probe data\n");
7953                                 return FALSE;
7954                         }
7955
7956                         player->audio_cb_probe_id = gst_pad_add_buffer_probe (pad,
7957                                 G_CALLBACK (__mmplayer_audio_stream_probe), player);
7958
7959                         gst_object_unref (pad);
7960
7961                         pad = NULL;
7962                }
7963         }
7964         else
7965         {
7966                 debug_error("There is no audio callback to configure.\n");
7967                 return FALSE;
7968         }
7969
7970         debug_fleave(); 
7971
7972         return TRUE;
7973 }
7974
7975 static void
7976 __mmplayer_init_factories(mm_player_t* player) // @
7977 {
7978         debug_fenter();
7979
7980         return_if_fail ( player );
7981
7982         player->factories = gst_registry_feature_filter(gst_registry_get_default(),
7983                                         (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
7984
7985         player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
7986
7987         debug_fleave(); 
7988 }
7989
7990 static void
7991 __mmplayer_release_factories(mm_player_t* player) // @
7992 {
7993         debug_fenter();
7994
7995         return_if_fail ( player );
7996
7997         if (player->factories)
7998         {
7999                 gst_plugin_feature_list_free (player->factories);
8000                 player->factories = NULL;
8001         }
8002
8003         debug_fleave();
8004 }
8005
8006 static void
8007 __mmplayer_release_misc(mm_player_t* player)
8008 {
8009         debug_fenter();
8010
8011         return_if_fail ( player );
8012
8013         /* free memory related to sound effect */
8014         if(player->audio_filter_info.custom_ext_level_for_plugin)
8015         {
8016                 free(player->audio_filter_info.custom_ext_level_for_plugin);
8017         }
8018
8019         debug_fleave();
8020 }
8021
8022 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
8023 {
8024         GstElement *element = NULL;
8025         GstPad *sinkpad;
8026
8027         debug_log("creating %s to plug\n", name);
8028         
8029         element = gst_element_factory_make(name, NULL);
8030         if ( ! element )
8031         {
8032                 debug_error("failed to create queue\n");
8033                 return NULL;
8034         }
8035
8036         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
8037         {
8038                 debug_error("failed to set state READY to %s\n", name);
8039                 return NULL;
8040         }
8041
8042         if ( ! gst_bin_add(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, element) )
8043         {
8044                 debug_error("failed to add %s\n", name);
8045                 return NULL;
8046         }
8047
8048         sinkpad = gst_element_get_static_pad(element, "sink");
8049
8050         if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
8051         {
8052                 debug_error("failed to link %s\n", name);
8053                 gst_object_unref (sinkpad);
8054                 
8055                 return NULL;
8056         }
8057
8058         debug_log("linked %s to pipeline successfully\n", name);
8059
8060         gst_object_unref (sinkpad);
8061
8062         return element; 
8063 }
8064
8065 static gboolean
8066 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
8067 const char *padname, const GList *templlist)
8068 {
8069         GstPad *pad = NULL;
8070         gboolean has_dynamic_pads = FALSE;
8071         gboolean has_many_types = FALSE;        
8072         const char *klass = NULL;
8073         GstStaticPadTemplate *padtemplate = NULL;
8074         GstElementFactory *factory = NULL;
8075         GstElement* queue = NULL;
8076         GstElement* parser = NULL;      
8077         GstPad *pssrcpad = NULL;
8078         GstPad *qsrcpad = NULL, *qsinkpad = NULL;
8079         MMPlayerGstElement *mainbin = NULL;
8080         GstStructure* str = NULL;
8081         GstCaps* srccaps = NULL;
8082         GstState warmup = GST_STATE_READY;
8083         gboolean isvideo_decoder = FALSE;
8084         guint q_max_size_time = 0;
8085
8086         debug_fenter();
8087
8088         return_val_if_fail ( player && 
8089                 player->pipeline && 
8090                 player->pipeline->mainbin, 
8091                 FALSE );
8092
8093         mainbin = player->pipeline->mainbin;
8094
8095         debug_log("plugging pad %s:%s to newly create %s:%s\n",
8096                                         GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
8097                         GST_PAD_NAME( srcpad ),
8098                         GST_ELEMENT_NAME( sinkelement ),
8099                         padname);
8100
8101
8102         factory = gst_element_get_factory(sinkelement);
8103         klass = gst_element_factory_get_klass(factory);
8104
8105         /* check if player can do start continually */
8106         MMPLAYER_CHECK_CMD_IF_EXIT(player);
8107
8108         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, warmup) )
8109         {
8110                 if (isvideo_decoder)
8111                         player->keep_detecting_vcodec = TRUE;
8112
8113                 debug_error("failed to set %d state to %s\n", warmup, GST_ELEMENT_NAME( sinkelement ));
8114                 goto ERROR;
8115         }
8116
8117         /* add to pipeline */
8118         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
8119         {
8120                 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
8121                 goto ERROR;
8122         }
8123
8124         debug_log("element klass : %s\n", klass);
8125
8126         /* added to support multi track files */
8127         /* only decoder case and any of the video/audio still need to link*/
8128         if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
8129         {
8130                 gchar *name = NULL;
8131
8132                 name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
8133                 
8134                 if (g_strrstr(name, "mpegtsdemux"))
8135                 {
8136                         gchar *demux_caps = NULL;
8137                         gchar *parser_name = NULL;
8138                         GstCaps *dcaps = NULL;
8139
8140                         dcaps = gst_pad_get_caps(srcpad);
8141                         demux_caps = gst_caps_to_string(dcaps);
8142                         
8143                         if (g_strrstr(demux_caps, "video/x-h264"))
8144                         {
8145                                 parser_name = g_strdup("h264parse");
8146                         }
8147                         else if (g_strrstr(demux_caps, "video/mpeg"))
8148                         {
8149                                 parser_name = g_strdup("mpeg4videoparse");
8150                         }
8151                         
8152                         gst_caps_unref(dcaps);
8153                         MMPLAYER_FREEIF( demux_caps );
8154
8155                         if (parser_name)
8156                         {
8157                                 parser = __mmplayer_element_create_and_link(player, srcpad, parser_name);
8158
8159                                 MMPLAYER_FREEIF(parser_name);
8160                                 
8161                                 if ( ! parser )
8162                                 {
8163                                         debug_error("failed to create parser\n");
8164                                 }
8165                                 else
8166                                 {
8167                                         /* update srcpad if parser is created */
8168                                         pssrcpad = gst_element_get_static_pad(parser, "src");
8169                                         srcpad = pssrcpad;
8170                                 }
8171                         }
8172                 }
8173                 MMPLAYER_FREEIF(name);
8174
8175                 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
8176                 if ( ! queue )
8177                 {
8178                         debug_error("failed to create queue\n");
8179                         goto ERROR;
8180                 }
8181
8182                 /* update srcpad to link with decoder */
8183                 qsrcpad = gst_element_get_static_pad(queue, "src");
8184                 srcpad = qsrcpad;
8185
8186                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
8187                         q_max_size_time = GST_QUEUE_HLS_TIME;
8188                 else
8189                         q_max_size_time = GST_QUEUE_DEFAULT_TIME;
8190
8191                 /* assigning queue handle for futher manipulation purpose */
8192                 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
8193                 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
8194                 {
8195                         mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
8196                         mainbin[MMPLAYER_M_Q1].gst = queue;
8197
8198                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
8199                 }
8200                 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
8201                 {
8202                         mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
8203                         mainbin[MMPLAYER_M_Q2].gst = queue;
8204
8205                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
8206                 }
8207                 else
8208                 {
8209                         debug_critical("Not supporting more then two elementary stream\n");
8210                         g_assert(1);
8211                 }
8212
8213                 pad = gst_element_get_static_pad(sinkelement, padname);
8214
8215                 if ( ! pad )
8216                 {
8217                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
8218                                 padname, GST_ELEMENT_NAME(sinkelement) );
8219
8220                         pad = gst_element_get_static_pad(sinkelement, "sink");
8221                         if ( ! pad )
8222                         {
8223                                 debug_error("failed to get pad(sink) from %s. \n",
8224                                 GST_ELEMENT_NAME(sinkelement) );
8225                                 goto ERROR;
8226                         }
8227                 }
8228
8229                 /*  to check the video/audio type set the proper flag*/
8230                 {
8231                         srccaps = gst_pad_get_caps( srcpad );
8232                         if ( !srccaps )
8233                                 goto ERROR;
8234
8235                         str = gst_caps_get_structure( srccaps, 0 );
8236                         if ( ! str )
8237                                 goto ERROR;
8238
8239                         name = gst_structure_get_name(str);
8240                         if ( ! name )
8241                                 goto ERROR;
8242                 }
8243
8244                 /* link queue and decoder. so, it will be queue - decoder. */
8245                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
8246                 {
8247                         gst_object_unref(GST_OBJECT(pad));
8248                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
8249
8250                         /* reconstitute supportable codec */
8251                         {
8252                                 if (strstr(name, "video"))
8253                                 {
8254                                         player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
8255                                 }
8256
8257                                 if (strstr(name, "audio"))
8258                                 {
8259                                         player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
8260                                 }
8261                         }
8262                         goto ERROR;
8263                 }
8264
8265                 gst_object_unref(GST_OBJECT(pad));
8266
8267                 {
8268                         if (strstr(name, "video"))
8269                         {
8270                                 player->videodec_linked = 1;
8271                                 debug_msg("player->videodec_linked set to 1\n");
8272
8273                         }
8274                         if (strstr(name, "audio"))
8275                         {
8276                                 player->audiodec_linked = 1;
8277                                 debug_msg("player->auddiodec_linked set to 1\n");
8278                         }
8279
8280                         gst_caps_unref(GST_CAPS(srccaps));
8281                         srccaps = NULL;
8282                 }
8283         }
8284
8285         if ( !MMPLAYER_IS_HTTP_PD(player) )
8286         {
8287                 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
8288                 {
8289                         if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
8290                         {
8291                                 GstFormat fmt  = GST_FORMAT_BYTES;
8292                                 gint64 dur_bytes = 0L;
8293                                 gchar *file_buffering_path = NULL;
8294                                 gboolean use_file_buffer = FALSE;
8295
8296                                 if ( !mainbin[MMPLAYER_M_S_BUFFER].gst)
8297                                 {
8298                                         debug_log("creating http streaming buffering queue\n");
8299
8300                                         queue = gst_element_factory_make("queue2", "http_streaming_buffer");
8301                                         if ( ! queue )
8302                                         {
8303                                                 debug_critical ( "failed to create buffering queue element\n" );
8304                                                 goto ERROR;
8305                                         }
8306
8307                                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
8308                                         {
8309                                                 debug_error("failed to set state READY to buffering queue\n");
8310                                                 goto ERROR;
8311                                         }
8312
8313                                         if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
8314                                         {
8315                                                 debug_error("failed to add buffering queue\n");
8316                                                 goto ERROR;
8317                                         }
8318
8319                                         qsinkpad = gst_element_get_static_pad(queue, "sink");
8320                                         qsrcpad = gst_element_get_static_pad(queue, "src");
8321
8322                                         if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
8323                                         {
8324                                                 debug_error("failed to link buffering queue\n");
8325                                                 goto ERROR;
8326                                         }
8327                                         srcpad = qsrcpad;
8328
8329
8330                                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_S_BUFFER;
8331                                         mainbin[MMPLAYER_M_S_BUFFER].gst = queue;
8332
8333                                         if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
8334                                          {
8335                                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
8336                                                         debug_error("fail to get duration.\n");
8337
8338                                                 if (dur_bytes>0)
8339                                                 {
8340                                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
8341                                                         file_buffering_path = g_strdup(PLAYER_INI()->http_file_buffer_path);
8342                                                 }
8343                                         }
8344
8345                                         __mm_player_streaming_set_buffer(player->streamer,
8346                                                 queue,
8347                                                 TRUE,
8348                                                 PLAYER_INI()->http_max_size_bytes,
8349                                                 1.0,
8350                                                 PLAYER_INI()->http_buffering_limit,
8351                                                 PLAYER_INI()->http_buffering_time,
8352                                                 use_file_buffer,
8353                                                 file_buffering_path,
8354                                                 dur_bytes);
8355
8356                                         MMPLAYER_FREEIF(file_buffering_path);
8357                                 }
8358                         }
8359                 }
8360         }
8361         /* if it is not decoder or */
8362         /* in decoder case any of the video/audio still need to link*/
8363         if(!g_strrstr(klass, "Decoder"))
8364         {
8365
8366                 pad = gst_element_get_static_pad(sinkelement, padname);
8367                 if ( ! pad )
8368                 {
8369                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
8370                                         padname, GST_ELEMENT_NAME(sinkelement) );
8371
8372                         pad = gst_element_get_static_pad(sinkelement, "sink");
8373
8374                         if ( ! pad )
8375                         {
8376                                 debug_error("failed to get pad(sink) from %s. \n",
8377                                         GST_ELEMENT_NAME(sinkelement) );
8378                                 goto ERROR;
8379                         }
8380                 }
8381
8382                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
8383                 {
8384                         gst_object_unref(GST_OBJECT(pad));
8385                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
8386                         goto ERROR;
8387                 }
8388
8389                 gst_object_unref(GST_OBJECT(pad));
8390         }
8391
8392         for(;templlist != NULL; templlist = templlist->next)
8393         {
8394                 padtemplate = templlist->data;
8395
8396                 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
8397
8398                 if(     padtemplate->direction != GST_PAD_SRC ||
8399                         padtemplate->presence == GST_PAD_REQUEST        )
8400                         continue;
8401
8402                 switch(padtemplate->presence)
8403                 {
8404                         case GST_PAD_ALWAYS:
8405                         {
8406                                 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
8407                                 GstCaps *caps = gst_pad_get_caps(srcpad);
8408
8409                                 /* Check whether caps has many types */
8410                                 if ( gst_caps_get_size (caps) > 1 && g_strrstr(klass, "Parser")) {
8411                                         debug_log ("has_many_types for this caps [%s]\n", gst_caps_to_string(caps));
8412                                         has_many_types = TRUE;
8413                                         break;
8414                                 }
8415
8416                                 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
8417                                 {
8418                                         gst_object_unref(GST_OBJECT(srcpad));
8419                                         gst_caps_unref(GST_CAPS(caps));
8420
8421                                         debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
8422                                         goto ERROR;
8423                                 }
8424
8425                                 gst_caps_unref(GST_CAPS(caps));
8426                                 gst_object_unref(GST_OBJECT(srcpad));
8427
8428                         }
8429                         break;
8430
8431
8432                         case GST_PAD_SOMETIMES:
8433                                 has_dynamic_pads = TRUE;
8434                         break;
8435
8436                         default:
8437                                 break;
8438                 }
8439         }
8440
8441         /* check if player can do start continually */
8442         MMPLAYER_CHECK_CMD_IF_EXIT(player);
8443
8444         if( has_dynamic_pads )
8445         {
8446                 player->have_dynamic_pad = TRUE;
8447                 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, "pad-added",
8448                         G_CALLBACK(__mmplayer_add_new_pad), player);
8449
8450                 /* for streaming, more then one typefind will used for each elementary stream
8451                  * so this doesn't mean the whole pipeline completion
8452                  */
8453                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
8454                 {
8455                         MMPLAYER_SIGNAL_CONNECT( player, sinkelement, "no-more-pads",
8456                                 G_CALLBACK(__mmplayer_pipeline_complete), player);
8457                 }
8458         }
8459
8460         if (has_many_types)
8461         {
8462                 GstPad *pad = NULL;
8463
8464                 player->has_many_types = has_many_types;
8465                 
8466                 pad = gst_element_get_static_pad(sinkelement, "src");
8467                 MMPLAYER_SIGNAL_CONNECT (player, pad, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
8468                 gst_object_unref (GST_OBJECT(pad));
8469         }
8470
8471
8472         /* check if player can do start continually */
8473         MMPLAYER_CHECK_CMD_IF_EXIT(player);
8474
8475         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
8476         {
8477                 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
8478                 goto ERROR;
8479         }
8480
8481         if ( queue )
8482         {
8483                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
8484                 {
8485                         debug_error("failed to set state PAUSED to queue\n");
8486                         goto ERROR;
8487                 }
8488
8489                 queue = NULL;
8490
8491                 gst_object_unref (GST_OBJECT(qsrcpad));
8492                 qsrcpad = NULL;
8493         }
8494
8495         if ( parser )
8496         {
8497                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
8498                 {
8499                         debug_error("failed to set state PAUSED to queue\n");
8500                         goto ERROR;
8501                 }
8502
8503                 parser = NULL;
8504
8505                 gst_object_unref (GST_OBJECT(pssrcpad));
8506                 pssrcpad = NULL;
8507         }
8508
8509         debug_fleave();
8510
8511         return TRUE;
8512
8513 ERROR:
8514
8515         if ( queue )
8516         {
8517                 gst_object_unref(GST_OBJECT(qsrcpad));
8518
8519                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
8520                  * You need to explicitly set elements to the NULL state before
8521                  * dropping the final reference, to allow them to clean up.
8522                  */
8523                 gst_element_set_state(queue, GST_STATE_NULL);
8524                 /* And, it still has a parent "player".
8525                  * You need to let the parent manage the object instead of unreffing the object directly.
8526                  */
8527
8528                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
8529                 //gst_object_unref( queue );
8530         }
8531
8532         if ( srccaps )
8533                 gst_caps_unref(GST_CAPS(srccaps));
8534
8535     return FALSE;
8536 }
8537
8538 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
8539 {
8540         const gchar *klass;
8541         //const gchar *name;
8542
8543         /* we only care about element factories */
8544         if (!GST_IS_ELEMENT_FACTORY(feature))
8545                 return FALSE;
8546
8547         /* only parsers, demuxers and decoders */
8548         klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
8549         //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
8550
8551         if( g_strrstr(klass, "Demux") == NULL &&
8552                 g_strrstr(klass, "Codec/Decoder") == NULL &&
8553                 g_strrstr(klass, "Depayloader") == NULL &&
8554                 g_strrstr(klass, "Parse") == NULL)
8555         {
8556                 return FALSE;
8557         }
8558     return TRUE;
8559 }
8560
8561
8562 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
8563 {
8564         mm_player_t* player = (mm_player_t*) data;
8565         GstCaps *caps = NULL;
8566         GstStructure *str = NULL;
8567         const char *name;
8568
8569         debug_fenter();
8570
8571         return_if_fail ( pad )
8572         return_if_fail ( unused )
8573         return_if_fail ( data )
8574
8575         caps = gst_pad_get_caps(pad);
8576         if ( !caps )
8577                 return;
8578         
8579         str = gst_caps_get_structure(caps, 0);
8580         if ( !str )
8581                 return;
8582
8583         name = gst_structure_get_name(str);
8584         if ( !name )
8585                 return;
8586         debug_log("name=%s\n", name);
8587
8588         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
8589         {
8590                 debug_error("failed to autoplug for type (%s)\n", name);
8591                 gst_caps_unref(caps);
8592                 return;
8593         }
8594
8595         gst_caps_unref(caps);
8596
8597         __mmplayer_pipeline_complete( NULL, (gpointer)player );
8598
8599         debug_fleave(); 
8600
8601         return;
8602 }
8603
8604 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
8605 {
8606         GstStructure *str;
8607         gint version = 0;
8608         const char *stream_type;
8609         gchar *version_field = NULL;
8610
8611         debug_fenter();
8612
8613         return_if_fail ( player );
8614         return_if_fail ( caps );
8615         
8616         str = gst_caps_get_structure(caps, 0);
8617         if ( !str )
8618                 return;
8619         
8620         stream_type = gst_structure_get_name(str);
8621         if ( !stream_type )
8622                 return;
8623
8624
8625         /* set unlinked mime type for downloadable codec */
8626         if (g_str_has_prefix(stream_type, "video/"))
8627         {       
8628                 if (g_str_has_prefix(stream_type, "video/mpeg")) 
8629                 {
8630                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
8631                         version_field = MM_PLAYER_MPEG_VNAME;
8632                 }
8633                 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
8634                 {
8635                         gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
8636                         version_field = MM_PLAYER_WMV_VNAME;
8637                         
8638                 }
8639                 else if (g_str_has_prefix(stream_type, "video/x-divx"))
8640                 {
8641                         gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
8642                         version_field = MM_PLAYER_DIVX_VNAME;
8643                 }
8644
8645                 if (version)
8646                 {
8647                         player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
8648                 }
8649                 else
8650                 {
8651                         player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
8652                 }
8653         }
8654         else if (g_str_has_prefix(stream_type, "audio/"))
8655         {
8656                 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
8657                 {
8658                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
8659                         version_field = MM_PLAYER_MPEG_VNAME;
8660                 }
8661                 else if (g_str_has_prefix(stream_type, "audio/x-wma")) 
8662                 {
8663                         gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
8664                         version_field = MM_PLAYER_WMA_VNAME;
8665                 }
8666
8667                 if (version)
8668                 {
8669                         player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
8670                 }
8671                 else
8672                 {
8673                         player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
8674                 }
8675         }
8676
8677         debug_fleave();
8678 }
8679
8680 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
8681 {
8682         mm_player_t* player = (mm_player_t*) data;
8683         GstCaps *caps = NULL;
8684         GstStructure *str = NULL;
8685         const char *name;
8686
8687         debug_fenter();
8688         return_if_fail ( player );
8689         return_if_fail ( pad );
8690
8691         GST_OBJECT_LOCK (pad);
8692         if ((caps = GST_PAD_CAPS(pad)))
8693                 gst_caps_ref(caps);
8694         GST_OBJECT_UNLOCK (pad);
8695
8696         if ( NULL == caps )
8697         {
8698                 caps = gst_pad_get_caps(pad);
8699                 if ( !caps ) return;
8700         }
8701
8702         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
8703         
8704         str = gst_caps_get_structure(caps, 0);
8705         if ( !str )
8706                 return;
8707
8708         name = gst_structure_get_name(str);
8709         if ( !name )
8710                 return;
8711
8712         player->num_dynamic_pad++;
8713         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
8714
8715         /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
8716           *     If want to play it, remove this code.
8717           */
8718         if (g_strrstr(name, "application"))
8719         {
8720                 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
8721                 {
8722                         /* If id3/ape tag comes, keep going */
8723                         debug_log("application mime exception : id3/ape tag");
8724                 }
8725                 else
8726                 {
8727                         /* Otherwise, we assume that this stream is subtile. */
8728                         debug_log(" application mime type pad is closed.");
8729                         return;
8730                 }
8731         }
8732         else if (g_strrstr(name, "audio"))
8733         {
8734                 gint samplerate = 0, channels = 0;
8735
8736                 /* set stream information */
8737                 /* if possible, set it here because the caps is not distrubed by resampler. */
8738                 gst_structure_get_int (str, "rate", &samplerate);
8739                 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
8740
8741                 gst_structure_get_int (str, "channels", &channels);
8742                 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
8743
8744                 debug_log("audio samplerate : %d        channels : %d", samplerate, channels);
8745
8746                 /* validate all */
8747                 if (  mmf_attrs_commit ( player->attrs ) )
8748                 {
8749                         debug_error("failed to update attributes");
8750                         return FALSE;
8751                 }
8752         }
8753         else if (g_strrstr(name, "video"))
8754         {
8755                 gint stype;
8756                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
8757
8758                 /* don't make video because of not required */
8759                 if (stype == MM_DISPLAY_SURFACE_NULL)
8760                 {
8761                         debug_log("no video because it's not required");
8762                         return;
8763                 }
8764
8765                 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
8766         }
8767
8768         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
8769         {
8770                 debug_error("failed to autoplug for type (%s)", name);
8771
8772                 __mmplayer_set_unlinked_mime_type(player, caps);
8773         }
8774
8775         gst_caps_unref(caps);
8776
8777         debug_fleave();
8778         return;
8779 }
8780
8781 /* test API for tuning audio gain. this API should be
8782  * deprecated before the day of final release
8783  */
8784 int
8785 _mmplayer_set_volume_tune(MMHandleType hplayer, MMPlayerVolumeType volume)
8786 {
8787         mm_player_t* player = (mm_player_t*) hplayer;
8788         gint error = MM_ERROR_NONE;
8789         gint vol_max = 0;
8790         gboolean isMidi = FALSE;
8791         gint i = 0;
8792
8793         debug_fenter();
8794
8795         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
8796         return_val_if_fail( player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED )
8797
8798         debug_log("clip type=%d(1-midi, 0-others), volume [L]=%d:[R]=%d\n",
8799                 player->profile.play_mode, volume.level[0], volume.level[1]);
8800
8801         isMidi = ( player->profile.play_mode == MM_PLAYER_MODE_MIDI ) ? TRUE : FALSE;
8802
8803         if ( isMidi )
8804                 vol_max = 1000;
8805         else
8806                 vol_max = 100;
8807
8808         /* is it proper volume level? */
8809         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; ++i)
8810         {
8811                 if (volume.level[i] < 0 || volume.level[i] > vol_max) {
8812                         debug_log("Invalid Volume level!!!! \n");
8813                         return MM_ERROR_INVALID_ARGUMENT;
8814                 }
8815         }
8816
8817         if ( isMidi )
8818         {
8819                 if ( player->pipeline->mainbin )
8820                 {
8821                         GstElement *midi_element = player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst;
8822
8823                         if ( midi_element && ( strstr(GST_ELEMENT_NAME(midi_element), "midiparse")) )
8824                         {
8825                                 debug_log("setting volume (%d) level to midi plugin\n", volume.level[0]);
8826
8827                                 g_object_set(midi_element, "volume", volume.level[0], NULL);
8828                         }
8829                 }
8830         }
8831         else
8832         {
8833                 if ( player->pipeline->audiobin )
8834                 {
8835                         GstElement *sink_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
8836
8837                         /* Set to Avsysaudiosink element */
8838                         if ( sink_element )
8839                         {
8840                                 gint vol_value = 0;
8841                                 gboolean mute = FALSE;
8842                                 vol_value = volume.level[0];
8843
8844                                 g_object_set(G_OBJECT(sink_element), "tuningvolume", vol_value, NULL);
8845
8846                                 mute = (vol_value == 0)? TRUE:FALSE;
8847
8848                                 g_object_set(G_OBJECT(sink_element), "mute", mute, NULL);
8849                         }
8850
8851                 }
8852         }
8853
8854         debug_fleave();
8855
8856         return error;
8857 }
8858
8859 gboolean
8860 __mmplayer_dump_pipeline_state( mm_player_t* player )
8861 {
8862         GstIterator*iter = NULL;
8863         gboolean done = FALSE;
8864
8865         GstElement *item = NULL;
8866         GstElementFactory *factory = NULL;
8867
8868         GstState state = GST_STATE_VOID_PENDING;
8869         GstState pending = GST_STATE_VOID_PENDING;
8870         GstClockTime time = 200*GST_MSECOND;
8871
8872         debug_fenter();
8873
8874         return_val_if_fail ( player &&
8875                 player->pipeline &&
8876                 player->pipeline->mainbin,
8877                 FALSE );
8878
8879
8880         iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) );
8881
8882         if ( iter != NULL )
8883         {
8884                 while (!done) {
8885                          switch ( gst_iterator_next (iter, (gpointer)&item) )
8886                          {
8887                            case GST_ITERATOR_OK:
8888                                 gst_element_get_state(GST_ELEMENT (item),&state, &pending,time);
8889
8890                                 factory = gst_element_get_factory (item) ;
8891                                  debug_log("%s:%s : From:%s To:%s   refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(item) ,
8892                                         gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(item));
8893
8894
8895                                  gst_object_unref (item);
8896                                  break;
8897                            case GST_ITERATOR_RESYNC:
8898                                  gst_iterator_resync (iter);
8899                                  break;
8900                            case GST_ITERATOR_ERROR:
8901                                  done = TRUE;
8902                                  break;
8903                            case GST_ITERATOR_DONE:
8904                                  done = TRUE;
8905                                  break;
8906                          }
8907                 }
8908         }
8909
8910         item = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
8911
8912         gst_element_get_state(GST_ELEMENT (item),&state, &pending,time);
8913
8914         factory = gst_element_get_factory (item) ;
8915
8916         debug_log("%s:%s : From:%s To:%s  refcount : %d\n",
8917                 GST_OBJECT_NAME(factory),
8918                 GST_ELEMENT_NAME(item),
8919                 gst_element_state_get_name(state),
8920                 gst_element_state_get_name(pending),
8921                 GST_OBJECT_REFCOUNT_VALUE(item) );
8922
8923         if ( iter )
8924                 gst_iterator_free (iter);
8925
8926         debug_fleave();
8927
8928         return FALSE;
8929 }
8930
8931
8932 gboolean
8933 __mmplayer_check_subtitle( mm_player_t* player )
8934 {
8935         MMHandleType attrs = 0;
8936         char *subtitle_uri = NULL;
8937
8938         debug_fenter();
8939
8940         return_val_if_fail( player, FALSE );
8941
8942         /* get subtitle attribute */
8943         attrs = MMPLAYER_GET_ATTRS(player);
8944         if ( !attrs )
8945                 return FALSE;
8946
8947         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
8948         if ( !subtitle_uri || !strlen(subtitle_uri))
8949                 return FALSE;
8950
8951         debug_log ("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
8952
8953         debug_fleave();
8954
8955         return TRUE;
8956 }
8957
8958 static gboolean
8959 __mmplayer_can_extract_pcm( mm_player_t* player )
8960 {
8961         MMHandleType attrs = 0;
8962         gboolean is_drm = FALSE;
8963         gboolean sound_extraction = FALSE;
8964
8965         debug_fenter();
8966
8967         return_val_if_fail ( player, FALSE );
8968
8969         attrs = MMPLAYER_GET_ATTRS(player);
8970         if ( !attrs )
8971         {
8972                 debug_error("fail to get attributes.");
8973                 return FALSE;
8974         }
8975         
8976         /* check file is drm or not */
8977         g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
8978
8979         /* get sound_extraction property */
8980         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
8981
8982         if ( ! sound_extraction || is_drm )
8983         {
8984                 debug_log("pcm extraction param.. is drm = %d, extraction mode = %d", is_drm, sound_extraction);
8985                 return FALSE;
8986         }
8987
8988         debug_fleave();
8989
8990         return TRUE;
8991 }
8992
8993 static gboolean
8994 __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error )
8995 {
8996         MMMessageParamType msg_param;
8997        gchar *msg_src_element;
8998
8999         debug_fenter();
9000
9001         return_val_if_fail( player, FALSE );
9002         return_val_if_fail( error, FALSE );
9003
9004         /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
9005
9006         memset (&msg_param, 0, sizeof(MMMessageParamType));
9007
9008         if ( error->domain == GST_CORE_ERROR )
9009         {
9010                 msg_param.code = __gst_handle_core_error( player, error->code );
9011         }
9012         else if ( error->domain == GST_LIBRARY_ERROR )
9013         {
9014                 msg_param.code = __gst_handle_library_error( player, error->code );
9015         }
9016         else if ( error->domain == GST_RESOURCE_ERROR )
9017         {
9018                 msg_param.code = __gst_handle_resource_error( player, error->code );
9019         }
9020         else if ( error->domain == GST_STREAM_ERROR )
9021         {
9022                 msg_param.code = __gst_handle_stream_error( player, error, message );
9023         }
9024         else
9025         {
9026                 debug_warning("This error domain is not defined.\n");
9027
9028                 /* we treat system error as an internal error */
9029                 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
9030         }
9031
9032         if ( message->src )
9033         {
9034                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
9035
9036                 msg_param.data = (void *) error->message;
9037
9038                 debug_error("-Msg src : [%s]    Domain : [%s]   Error : [%s]  Code : [%d] is tranlated to error code : [0x%x]\n",
9039                         msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg_param.code);
9040         }
9041
9042         if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
9043         {
9044                 __mm_player_ahs_stop (player->ahs_player);
9045         }
9046
9047         /* post error to application */
9048         if ( ! player->posted_msg )
9049         {
9050                 if (msg_param.code == MM_MESSAGE_DRM_NOT_AUTHORIZED)
9051                 {
9052                         MMPLAYER_POST_MSG( player, MM_MESSAGE_DRM_NOT_AUTHORIZED, NULL );
9053                 }
9054                 else
9055                 {
9056                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
9057                 }
9058
9059                 /* don't post more if one was sent already */
9060                 player->posted_msg = TRUE;
9061         }
9062         else
9063         {
9064                 debug_log("skip error post because it's sent already.\n");
9065         }
9066
9067         debug_fleave();
9068
9069         return TRUE;
9070 }
9071
9072 static gboolean
9073 __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message )
9074 {
9075         debug_log("\n");
9076         MMMessageParamType msg_param;
9077         gchar *msg_src_element = NULL;
9078         GstStructure *s = NULL;
9079         guint error_id = 0;
9080         gchar *error_string = NULL;
9081
9082         debug_fenter();
9083
9084         return_val_if_fail ( player, FALSE );
9085         return_val_if_fail ( message, FALSE );
9086
9087         s = malloc( sizeof(GstStructure) );
9088         memcpy ( s, gst_message_get_structure ( message ), sizeof(GstStructure));
9089
9090         if ( !gst_structure_get_uint (s, "error_id", &error_id) )
9091                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
9092
9093         switch ( error_id )
9094         {
9095                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
9096                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
9097                         break;
9098                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
9099                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
9100                         break;
9101                 case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
9102                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
9103                         break;
9104                 case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
9105                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
9106                         break;
9107                 case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
9108                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
9109                         break;
9110                 case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
9111                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
9112                         break;
9113                 case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
9114                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
9115                         break;
9116                 case MMPLAYER_STREAMING_ERROR_INVALID_URL:
9117                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
9118                         break;
9119                 case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
9120                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
9121                         break;
9122                 case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
9123                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
9124                         break;
9125                 case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
9126                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
9127                         break;
9128                 case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
9129                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
9130                         break;
9131                 case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
9132                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
9133                         break;
9134                 case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
9135                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
9136                         break;
9137                 case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
9138                         msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
9139                         break;
9140                 case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
9141                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
9142                         break;
9143                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
9144                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
9145                         break;
9146                 case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
9147                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
9148                         break;
9149                 case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
9150                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
9151                         break;
9152                 case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
9153                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
9154                         break;
9155                 case MMPLAYER_STREAMING_ERROR_GONE:
9156                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
9157                         break;
9158                 case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
9159                         msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
9160                         break;
9161                 case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
9162                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
9163                         break;
9164                 case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
9165                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
9166                         break;
9167                 case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
9168                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
9169                         break;
9170                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
9171                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
9172                         break;
9173                 case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
9174                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
9175                         break;
9176                 case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
9177                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
9178                         break;
9179                 case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
9180                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
9181                         break;
9182                 case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
9183                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
9184                         break;
9185                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
9186                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
9187                         break;
9188                 case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
9189                         msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
9190                         break;
9191                 case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
9192                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
9193                         break;
9194                 case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
9195                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
9196                         break;
9197                 case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
9198                         msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
9199                         break;
9200                 case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
9201                         msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
9202                         break;
9203                 case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
9204                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
9205                         break;
9206                 case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
9207                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
9208                         break;
9209                 case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
9210                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
9211                         break;
9212                 case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
9213                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
9214                         break;
9215                 case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
9216                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
9217                         break;
9218                 case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
9219                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
9220                         break;
9221                 case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
9222                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
9223                         break;
9224                 case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
9225                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
9226                         break;
9227                 case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
9228                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
9229                         break;
9230                 default:
9231                         return MM_ERROR_PLAYER_STREAMING_FAIL;
9232         }
9233
9234         error_string = g_strdup(gst_structure_get_string (s, "error_string"));
9235         if ( error_string )
9236                 msg_param.data = (void *) error_string;
9237
9238         if ( message->src )
9239         {
9240                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
9241
9242                 debug_error("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
9243                         msg_src_element, msg_param.code, (char*)msg_param.data );
9244         }
9245
9246         /* post error to application */
9247         if ( ! player->posted_msg )
9248         {
9249                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
9250
9251                 /* don't post more if one was sent already */
9252                 player->posted_msg = TRUE;
9253         }
9254         else
9255         {
9256                 debug_log("skip error post because it's sent already.\n");
9257         }
9258
9259         debug_fleave();
9260
9261         return TRUE;
9262
9263 }
9264
9265 static gint
9266 __gst_handle_core_error( mm_player_t* player, int code )
9267 {
9268         gint trans_err = MM_ERROR_NONE;
9269
9270         debug_fenter();
9271
9272         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9273
9274         switch ( code )
9275         {
9276                 case GST_CORE_ERROR_STATE_CHANGE:
9277                 case GST_CORE_ERROR_MISSING_PLUGIN:
9278                 case GST_CORE_ERROR_SEEK:
9279                 case GST_CORE_ERROR_NOT_IMPLEMENTED:
9280                 case GST_CORE_ERROR_FAILED:
9281                 case GST_CORE_ERROR_TOO_LAZY:
9282                 case GST_CORE_ERROR_PAD:
9283                 case GST_CORE_ERROR_THREAD:
9284                 case GST_CORE_ERROR_NEGOTIATION:
9285                 case GST_CORE_ERROR_EVENT:
9286                 case GST_CORE_ERROR_CAPS:
9287                 case GST_CORE_ERROR_TAG:
9288                 case GST_CORE_ERROR_CLOCK:
9289                 case GST_CORE_ERROR_DISABLED:
9290                 default:
9291                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
9292                 break;
9293         }
9294
9295         debug_fleave();
9296
9297         return trans_err;
9298 }
9299
9300 static gint
9301 __gst_handle_library_error( mm_player_t* player, int code )
9302 {
9303         gint trans_err = MM_ERROR_NONE;
9304
9305         debug_fenter();
9306
9307         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9308
9309         switch ( code )
9310         {
9311                 case GST_LIBRARY_ERROR_FAILED:
9312                 case GST_LIBRARY_ERROR_TOO_LAZY:
9313                 case GST_LIBRARY_ERROR_INIT:
9314                 case GST_LIBRARY_ERROR_SHUTDOWN:
9315                 case GST_LIBRARY_ERROR_SETTINGS:
9316                 case GST_LIBRARY_ERROR_ENCODE:
9317                 default:
9318                         trans_err =  MM_ERROR_PLAYER_INVALID_STREAM;
9319                 break;
9320         }
9321         
9322         debug_fleave();
9323
9324         return trans_err;
9325 }
9326
9327
9328 static gint
9329 __gst_handle_resource_error( mm_player_t* player, int code )
9330 {
9331         gint trans_err = MM_ERROR_NONE;
9332
9333         debug_fenter();
9334
9335         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9336
9337         switch ( code )
9338         {
9339                 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
9340                         trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
9341                         break;
9342                 case GST_RESOURCE_ERROR_NOT_FOUND:
9343                 case GST_RESOURCE_ERROR_OPEN_READ:
9344                         if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player ) )
9345                         {
9346                                 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
9347                                 break;
9348                         }
9349                 case GST_RESOURCE_ERROR_READ:
9350                         if ( MMPLAYER_IS_HTTP_STREAMING(player) ||  MMPLAYER_IS_HTTP_LIVE_STREAMING ( player ))
9351                         {
9352                                 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
9353                                 break;
9354                         }
9355                 case GST_RESOURCE_ERROR_SEEK:
9356                 case GST_RESOURCE_ERROR_FAILED:
9357                 case GST_RESOURCE_ERROR_TOO_LAZY:
9358                 case GST_RESOURCE_ERROR_BUSY:
9359                 case GST_RESOURCE_ERROR_OPEN_WRITE:
9360                 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
9361                 case GST_RESOURCE_ERROR_CLOSE:
9362                 case GST_RESOURCE_ERROR_WRITE:
9363                 case GST_RESOURCE_ERROR_SYNC:
9364                 case GST_RESOURCE_ERROR_SETTINGS:
9365                 default:
9366                         trans_err = MM_ERROR_PLAYER_FILE_NOT_FOUND;
9367                 break;
9368         }
9369
9370         debug_fleave();
9371
9372         return trans_err;
9373 }
9374
9375
9376 static gint
9377 __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message )
9378 {
9379         gint trans_err = MM_ERROR_NONE;
9380
9381         debug_fenter();
9382
9383         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9384         return_val_if_fail( error, MM_ERROR_INVALID_ARGUMENT );
9385         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
9386
9387         switch ( error->code )
9388         {
9389                 case GST_STREAM_ERROR_FAILED:
9390                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
9391                 case GST_STREAM_ERROR_DECODE:
9392                 case GST_STREAM_ERROR_WRONG_TYPE:
9393                 case GST_STREAM_ERROR_DECRYPT:
9394                          trans_err = __gst_transform_gsterror( player, message, error );
9395                 break;
9396
9397                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
9398                 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
9399                 case GST_STREAM_ERROR_TOO_LAZY:
9400                 case GST_STREAM_ERROR_ENCODE:
9401                 case GST_STREAM_ERROR_DEMUX:
9402                 case GST_STREAM_ERROR_MUX:
9403                 case GST_STREAM_ERROR_FORMAT:
9404                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
9405                 default:
9406                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
9407                 break;
9408         }
9409
9410         debug_fleave();
9411
9412         return trans_err;
9413 }
9414
9415
9416 /* NOTE : decide gstreamer state whether there is some playable track or not. */
9417 static gint
9418 __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error )
9419 {
9420         gchar *src_element_name = NULL;
9421         GstElement *src_element = NULL;
9422         GstElementFactory *factory = NULL;
9423         const gchar* klass = NULL;
9424         
9425         debug_fenter();
9426
9427         /* FIXIT */
9428         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
9429         return_val_if_fail ( message->src, MM_ERROR_INVALID_ARGUMENT );
9430         return_val_if_fail ( error, MM_ERROR_INVALID_ARGUMENT );
9431
9432         src_element = GST_ELEMENT_CAST(message->src);
9433         if ( !src_element )
9434                 goto INTERNAL_ERROR;
9435         
9436         src_element_name = GST_ELEMENT_NAME(src_element);
9437         if ( !src_element_name )
9438                 goto INTERNAL_ERROR;
9439
9440         factory = gst_element_get_factory(src_element);
9441         if ( !factory )
9442                 goto INTERNAL_ERROR;
9443         
9444         klass = gst_element_factory_get_klass(factory);
9445         if ( !klass )
9446                 goto INTERNAL_ERROR;
9447
9448         debug_log("error code=%d, msg=%s, src element=%s, class=%s\n", 
9449                         error->code, error->message, src_element_name, klass);
9450
9451
9452         switch ( error->code )
9453         {
9454                 case GST_STREAM_ERROR_DECODE:
9455                 {
9456                         /* NOTE : Delay is needed because gst callback is sometime sent
9457                          * before completing autoplugging.
9458                          * Timer is more better than usleep.
9459                          * But, transformed msg value should be stored in player handle
9460                          * for function to call by timer.
9461                          */
9462                         if ( PLAYER_INI()->async_start )
9463                                 usleep(500000);
9464
9465                         /* Demuxer can't parse one track because it's corrupted.
9466                          * So, the decoder for it is not linked.
9467                          * But, it has one playable track.
9468                          */
9469                         if ( g_strrstr(klass, "Demux") )
9470                         {
9471                                 if ( player->can_support_codec == FOUND_PLUGIN_VIDEO )
9472                                 {
9473                                         return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9474                                 }
9475                                 else if ( player->can_support_codec == FOUND_PLUGIN_AUDIO )
9476                                 {
9477                                         return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9478                                 }
9479                                 else
9480                                 {
9481                                         if ( player->pipeline->audiobin ) // PCM
9482                                         {
9483                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9484                                         }
9485                                         else
9486                                         {
9487                                                 goto CODEC_NOT_FOUND;
9488                                         }
9489                                 }
9490                         }
9491                         return MM_ERROR_PLAYER_INVALID_STREAM;
9492                 }
9493                 break;
9494
9495                 case GST_STREAM_ERROR_WRONG_TYPE:
9496                 {
9497                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
9498                 }
9499                 break;
9500
9501                 case GST_STREAM_ERROR_FAILED:
9502                 {
9503                         /* Decoder Custom Message */
9504                         if ( strstr(error->message, "ongoing") )
9505                         {
9506                                 if ( strcasestr(klass, "audio") )
9507                                 {
9508                                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) )
9509                                         {
9510                                                 debug_log("Video can keep playing.\n");
9511                                                 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9512                                         }
9513                                         else
9514                                         {
9515                                                 goto CODEC_NOT_FOUND;
9516                                         }
9517
9518                                 }
9519                                 else if ( strcasestr(klass, "video") )
9520                                 {
9521                                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) )
9522                                         {
9523                                                 debug_log("Audio can keep playing.\n");
9524                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9525                                         }
9526                                         else
9527                                         {
9528                                                 goto CODEC_NOT_FOUND;
9529                                         }
9530                                 }
9531                         }
9532         return MM_ERROR_PLAYER_INVALID_STREAM;
9533                 }
9534                 break;
9535
9536                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
9537                 {                               
9538                         goto CODEC_NOT_FOUND;
9539                 }
9540                 break;
9541
9542                 case GST_STREAM_ERROR_DECRYPT:
9543                 {                               
9544                         debug_log("%s failed reason : %s\n", src_element_name, error->message);
9545                         return MM_MESSAGE_DRM_NOT_AUTHORIZED;
9546                 }
9547                 break;
9548
9549                 default:
9550                 break;
9551         }
9552
9553         debug_fleave();
9554
9555         return MM_ERROR_PLAYER_INVALID_STREAM;
9556
9557 INTERNAL_ERROR:
9558         return MM_ERROR_PLAYER_INTERNAL;
9559
9560 CODEC_NOT_FOUND:
9561         debug_log("not found any available codec. Player should be destroyed.\n");
9562         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9563 }
9564
9565 static void
9566 __mmplayer_post_delayed_eos( mm_player_t* player, int delay_in_ms )
9567 {
9568         debug_fenter();
9569
9570         return_if_fail( player );
9571
9572         /* cancel if existing */
9573         __mmplayer_cancel_delayed_eos( player );
9574
9575
9576         /* post now if delay is zero */
9577         if ( delay_in_ms == 0 || player->is_sound_extraction)
9578         {
9579                 debug_log("eos delay is zero. posting EOS now\n");
9580                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
9581
9582                 if ( player->is_sound_extraction )
9583                         __mmplayer_cancel_delayed_eos(player);
9584
9585                 return;
9586         }
9587
9588         /* init new timeout */
9589         /* NOTE : consider give high priority to this timer */
9590
9591         debug_log("posting EOS message after [%d] msec\n", delay_in_ms);
9592         player->eos_timer = g_timeout_add( delay_in_ms,
9593                 __mmplayer_eos_timer_cb, player );
9594
9595
9596         /* check timer is valid. if not, send EOS now */
9597         if ( player->eos_timer == 0 )
9598         {
9599                 debug_warning("creating timer for delayed EOS has failed. sending EOS now\n");
9600                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
9601         }
9602
9603         debug_fleave();
9604 }
9605
9606 static void
9607 __mmplayer_cancel_delayed_eos( mm_player_t* player )
9608 {
9609         debug_fenter();
9610
9611         return_if_fail( player );
9612
9613         if ( player->eos_timer )
9614         {
9615                 g_source_remove( player->eos_timer );
9616         }
9617
9618         player->eos_timer = 0;
9619
9620         debug_fleave();
9621
9622         return;
9623 }
9624
9625 static gboolean
9626 __mmplayer_eos_timer_cb(gpointer u_data)
9627 {
9628         mm_player_t* player = NULL;
9629         player = (mm_player_t*) u_data;
9630
9631         debug_fenter();
9632
9633         return_val_if_fail( player, FALSE );
9634
9635         /* posting eos */
9636         MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
9637
9638         /* cleare timer id */
9639         player->eos_timer = 0;
9640
9641         debug_fleave();
9642
9643         /* we are returning FALSE as we need only one posting */
9644         return FALSE;
9645 }
9646
9647 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force)
9648 {
9649         gint antishock = FALSE;
9650         MMHandleType attrs = 0;
9651
9652         debug_fenter();
9653
9654         return_if_fail ( player && player->pipeline );
9655
9656         /* It should be passed for video only clip */
9657         if ( ! player->pipeline->audiobin )
9658                 return;
9659
9660         if ( ( g_strrstr(PLAYER_INI()->name_of_audiosink, "avsysaudiosink")) )
9661         {
9662                 attrs = MMPLAYER_GET_ATTRS(player);
9663                 if ( ! attrs )
9664                 {
9665                         debug_error("fail to get attributes.\n");
9666                         return;
9667                 }
9668
9669                 mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock);
9670
9671                 debug_log("setting antishock as (%d)\n", antishock);
9672
9673                 if ( disable_by_force )
9674                 {
9675                         debug_log("but, antishock is disabled by force when is seeked\n");
9676
9677                         antishock = FALSE;
9678                 }
9679
9680                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "fadeup", antishock, NULL);
9681         }
9682
9683         debug_fleave();
9684
9685         return;
9686 }
9687
9688
9689 static gboolean
9690 __mmplayer_link_decoder( mm_player_t* player, GstPad *srcpad)
9691 {
9692         const gchar* name = NULL;
9693         GstStructure* str = NULL;
9694         GstCaps* srccaps = NULL;
9695
9696         debug_fenter();
9697
9698         return_val_if_fail( player, FALSE );
9699         return_val_if_fail ( srcpad, FALSE );
9700
9701         /* to check any of the decoder (video/audio) need to be linked  to parser*/
9702         srccaps = gst_pad_get_caps( srcpad );
9703         if ( !srccaps )
9704                 goto ERROR;
9705
9706         str = gst_caps_get_structure( srccaps, 0 );
9707         if ( ! str )
9708                 goto ERROR;
9709
9710         name = gst_structure_get_name(str);
9711         if ( ! name )
9712                 goto ERROR;
9713
9714         if (strstr(name, "video"))
9715         {
9716                 if(player->videodec_linked)
9717                 {
9718                     debug_msg("Video decoder already linked\n");
9719                         return FALSE;
9720                 }
9721         }
9722         if (strstr(name, "audio"))
9723         {
9724                 if(player->audiodec_linked)
9725                 {
9726                     debug_msg("Audio decoder already linked\n");
9727                         return FALSE;
9728                 }
9729         }
9730
9731         gst_caps_unref( srccaps );
9732
9733         debug_fleave();
9734
9735         return TRUE;
9736
9737 ERROR:
9738         if ( srccaps )
9739                 gst_caps_unref( srccaps );
9740
9741         return FALSE;
9742 }
9743
9744 static gboolean
9745 __mmplayer_link_sink( mm_player_t* player , GstPad *srcpad)
9746 {
9747         const gchar* name = NULL;
9748         GstStructure* str = NULL;
9749         GstCaps* srccaps = NULL;
9750
9751         debug_fenter();
9752
9753         return_val_if_fail ( player, FALSE );
9754         return_val_if_fail ( srcpad, FALSE );
9755
9756         /* to check any of the decoder (video/audio) need to be linked  to parser*/
9757         srccaps = gst_pad_get_caps( srcpad );
9758         if ( !srccaps )
9759                 goto ERROR;
9760
9761         str = gst_caps_get_structure( srccaps, 0 );
9762         if ( ! str )
9763                 goto ERROR;
9764
9765         name = gst_structure_get_name(str);
9766         if ( ! name )
9767                 goto ERROR;
9768
9769         if (strstr(name, "video"))
9770         {
9771                 if(player->videosink_linked)
9772                 {
9773                         debug_msg("Video Sink already linked\n");
9774                         return FALSE;
9775                 }
9776         }
9777         if (strstr(name, "audio"))
9778         {
9779                 if(player->audiosink_linked)
9780                 {
9781                         debug_msg("Audio Sink already linked\n");
9782                         return FALSE;
9783                 }
9784         }
9785         if (strstr(name, "text"))
9786         {
9787                 if(player->textsink_linked)
9788                 {
9789                         debug_msg("Text Sink already linked\n");
9790                         return FALSE;
9791                 }
9792         }
9793
9794         gst_caps_unref( srccaps );
9795
9796         debug_fleave();
9797
9798         return TRUE;
9799         //return (!player->videosink_linked || !player->audiosink_linked);
9800
9801 ERROR:
9802         if ( srccaps )
9803                 gst_caps_unref( srccaps );
9804
9805         return FALSE;
9806 }
9807
9808
9809 /* sending event to one of sinkelements */
9810 static gboolean
9811 __gst_send_event_to_sink( mm_player_t* player, GstEvent* event )
9812 {
9813         GList *sinks = NULL;
9814         gboolean res = FALSE;
9815
9816         debug_fenter();
9817         
9818         return_val_if_fail( player, FALSE );
9819         return_val_if_fail ( event, FALSE );
9820
9821         sinks = player->sink_elements;
9822         while (sinks)
9823         {
9824                 GstElement *sink = GST_ELEMENT_CAST (sinks->data);
9825
9826                 if (GST_IS_ELEMENT(sink))
9827                 {
9828                         /* keep ref to the event */
9829                         gst_event_ref (event);
9830
9831                         if ( (res = gst_element_send_event (sink, event)) )
9832                         {
9833                                 debug_log("sending event[%s] to sink element [%s] success!\n",
9834                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
9835                                 break;
9836                         }
9837
9838                         debug_log("sending event[%s] to sink element [%s] failed. try with next one.\n",
9839                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
9840                 }
9841
9842                 sinks = g_list_next (sinks);
9843         }
9844
9845         /* Note : Textbin is not linked to the video or audio bin.
9846          *              It needs to send the event to the text sink seperatelly.
9847          */
9848          if ( MMPLAYER_PLAY_SUBTITLE(player) )
9849          {
9850                 GstElement *subtitle_sink = GST_ELEMENT_CAST (player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst);
9851
9852                 if ( (res != gst_element_send_event (subtitle_sink, event)) )
9853                 {
9854                         debug_error("sending event[%s] to subtitle sink element [%s] failed!\n",
9855                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(subtitle_sink) );
9856                 }
9857                 else
9858                 {
9859                         debug_log("sending event[%s] to subtitle sink element [%s] success!\n",
9860                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(subtitle_sink) );
9861                 }
9862          }
9863
9864         gst_event_unref (event);
9865
9866         debug_fleave();
9867
9868         return res;
9869 }
9870
9871 static void
9872 __mmplayer_add_sink( mm_player_t* player, GstElement* sink )
9873 {
9874         debug_fenter();
9875
9876         return_if_fail ( player );
9877         return_if_fail ( sink );
9878
9879         player->sink_elements =
9880                 g_list_append(player->sink_elements, sink);
9881
9882         debug_fleave();
9883 }
9884
9885 static void
9886 __mmplayer_del_sink( mm_player_t* player, GstElement* sink )
9887 {
9888         debug_fenter();
9889
9890         return_if_fail ( player );
9891         return_if_fail ( sink );
9892
9893         player->sink_elements =
9894                         g_list_remove(player->sink_elements, sink);
9895
9896         debug_fleave();
9897 }
9898
9899 static gboolean
9900 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
9901                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
9902                         gint64 cur, GstSeekType stop_type, gint64 stop )
9903 {
9904         GstEvent* event = NULL;
9905         gboolean result = FALSE;
9906
9907         debug_fenter();
9908         
9909         return_val_if_fail( player, FALSE );
9910
9911         event = gst_event_new_seek (rate, format, flags, cur_type,
9912                 cur, stop_type, stop);
9913
9914         result = __gst_send_event_to_sink( player, event );
9915
9916         debug_fleave();
9917
9918         return result;
9919 }
9920
9921 /* NOTE : be careful with calling this api. please refer to below glib comment
9922  * glib comment : Note that there is a bug in GObject that makes this function much
9923  * less useful than it might seem otherwise. Once gobject is disposed, the callback
9924  * will no longer be called, but, the signal handler is not currently disconnected.
9925  * If the instance is itself being freed at the same time than this doesn't matter,
9926  * since the signal will automatically be removed, but if instance persists,
9927  * then the signal handler will leak. You should not remove the signal yourself
9928  * because in a future versions of GObject, the handler will automatically be
9929  * disconnected.
9930  *
9931  * It's possible to work around this problem in a way that will continue to work
9932  * with future versions of GObject by checking that the signal handler is still
9933  * connected before disconnected it:
9934  *
9935  *  if (g_signal_handler_is_connected (instance, id))
9936  *    g_signal_handler_disconnect (instance, id);
9937  */
9938 static void
9939 __mmplayer_release_signal_connection(mm_player_t* player)
9940 {
9941         GList* sig_list = player->signals;
9942         MMPlayerSignalItem* item = NULL;
9943
9944         debug_fenter();
9945         
9946         return_if_fail( player );
9947
9948         for ( ; sig_list; sig_list = sig_list->next )
9949         {
9950                 item = sig_list->data;
9951
9952                 if ( item && item->obj && GST_IS_ELEMENT(item->obj) )
9953                 {
9954                         debug_log("checking signal connection : [%lud] from [%s]\n", item->sig, GST_OBJECT_NAME( item->obj ));
9955
9956                         if ( g_signal_handler_is_connected ( item->obj, item->sig ) )
9957                         {
9958                                 debug_log("signal disconnecting : [%lud] from [%s]\n", item->sig, GST_OBJECT_NAME( item->obj ));
9959                                 g_signal_handler_disconnect ( item->obj, item->sig );
9960                         }
9961                 }
9962
9963                 MMPLAYER_FREEIF( item );
9964
9965         }
9966         g_list_free ( player->signals );
9967         player->signals = NULL;
9968
9969         debug_fleave();
9970
9971         return;
9972 }
9973
9974
9975 /* Note : if silent is true, then subtitle would not be displayed. :*/
9976 int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent)
9977 {
9978         mm_player_t* player = (mm_player_t*) hplayer;
9979
9980         debug_fenter();
9981
9982         /* check player handle */
9983         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9984         return_val_if_fail ( MMPLAYER_PLAY_SUBTITLE(player),    MM_ERROR_PLAYER_NOT_INITIALIZED );
9985
9986         player->is_subtitle_off = silent;
9987
9988         debug_log("subtitle is %s.\n", player->is_subtitle_off ? "ON" : "OFF");
9989
9990         debug_fleave();
9991
9992         return MM_ERROR_NONE;
9993 }
9994
9995
9996 int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent)
9997 {
9998         mm_player_t* player = (mm_player_t*) hplayer;
9999
10000         debug_fenter();
10001
10002         /* check player handle */
10003         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10004         return_val_if_fail ( MMPLAYER_PLAY_SUBTITLE(player),    MM_ERROR_PLAYER_NOT_INITIALIZED );
10005
10006         *silent = player->is_subtitle_off;
10007
10008         debug_log("subtitle is %s.\n", silent ? "ON" : "OFF");
10009
10010         debug_fleave();
10011
10012         return MM_ERROR_NONE;
10013 }
10014
10015 int _mmplayer_get_track_count(MMHandleType hplayer,  MMPlayerTrackType track_type, int *count)
10016 {
10017         mm_player_t* player = (mm_player_t*) hplayer;
10018         MMHandleType attrs = 0;
10019         int ret = MM_ERROR_NONE;
10020
10021         debug_fenter();
10022
10023         /* check player handle */
10024         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10025         return_val_if_fail(count, MM_ERROR_COMMON_INVALID_ARGUMENT);
10026         return_val_if_fail((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
10027                  ||(MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING),
10028                 MM_ERROR_PLAYER_INVALID_STATE);
10029
10030         attrs = MMPLAYER_GET_ATTRS(player);
10031         if ( !attrs )
10032         {
10033                 debug_error("cannot get content attribute");
10034                 return MM_ERROR_PLAYER_INTERNAL;
10035         }
10036
10037         switch (track_type)
10038         {
10039                 case MM_PLAYER_TRACK_TYPE_AUDIO:
10040                         ret = mm_attrs_get_int_by_name(attrs, "content_audio_track_num", count);
10041                         break;
10042                 case MM_PLAYER_TRACK_TYPE_VIDEO:
10043                         ret = mm_attrs_get_int_by_name(attrs, "content_video_track_num", count);
10044                         break;
10045                 case MM_PLAYER_TRACK_TYPE_TEXT:
10046                         ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
10047                         break;
10048                 default:
10049                         ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
10050                         break;
10051         }
10052
10053         debug_log ("%d track num is %d\n", track_type, *count);
10054
10055         debug_fleave();
10056
10057         return ret;
10058 }
10059
10060
10061
10062 const gchar * 
10063 __get_state_name ( int state )
10064 {
10065         switch ( state )
10066         {
10067                 case MM_PLAYER_STATE_NULL:
10068                         return "NULL";
10069                 case MM_PLAYER_STATE_READY:
10070                         return "READY";
10071                 case MM_PLAYER_STATE_PAUSED:
10072                         return "PAUSED";
10073                 case MM_PLAYER_STATE_PLAYING:
10074                         return "PLAYING";
10075                 case MM_PLAYER_STATE_NONE:
10076                         return "NONE";
10077                 default:
10078                         return "INVAID";
10079         }
10080 }
10081 gboolean
10082 __is_rtsp_streaming ( mm_player_t* player )
10083 {
10084         return_val_if_fail ( player, FALSE );
10085
10086         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP ) ? TRUE : FALSE;
10087 }
10088
10089 static gboolean
10090 __is_http_streaming ( mm_player_t* player )
10091 {
10092         return_val_if_fail ( player, FALSE );
10093
10094         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP ) ? TRUE : FALSE;
10095 }
10096
10097 static gboolean
10098 __is_streaming ( mm_player_t* player )
10099 {
10100         return_val_if_fail ( player, FALSE );
10101
10102         return ( __is_rtsp_streaming ( player ) || __is_http_streaming ( player ) || __is_http_live_streaming ( player )) ? TRUE : FALSE;
10103 }
10104
10105 gboolean
10106 __is_live_streaming ( mm_player_t* player )
10107 {
10108         return_val_if_fail ( player, FALSE );
10109
10110         return ( __is_rtsp_streaming ( player ) && player->streaming_type == STREAMING_SERVICE_LIVE ) ? TRUE : FALSE;
10111 }
10112
10113 static gboolean
10114 __is_http_live_streaming( mm_player_t* player )
10115 {
10116         return_val_if_fail( player, FALSE );
10117
10118         return ( (player->ahs_player) && (player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS) ) ? TRUE : FALSE;
10119 }
10120
10121 static gboolean
10122 __is_http_progressive_down(mm_player_t* player)
10123 {
10124         return_val_if_fail( player, FALSE );
10125
10126         return ((player->pd_mode) ? TRUE:FALSE);
10127 }