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