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