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