ede7896785bee48c563f08e5d1ec4526f99d1dd8
[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 #include "mm_player_priv_internal.h"
51 #include "mm_player_priv_locl_func.h"
52
53 /*===========================================================================================
54 |                                                                                                                                                                                       |
55 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
56 |                                                                                                                                                                                       |
57 ========================================================================================== */
58
59 /*---------------------------------------------------------------------------
60 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
61 ---------------------------------------------------------------------------*/
62
63 /*---------------------------------------------------------------------------
64 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
65 ---------------------------------------------------------------------------*/
66
67 /*---------------------------------------------------------------------------
68 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
69 ---------------------------------------------------------------------------*/
70
71 /*---------------------------------------------------------------------------
72 |    LOCAL #defines:                                                                                                            |
73 ---------------------------------------------------------------------------*/
74 #define TRICK_PLAY_MUTE_THRESHOLD_MAX   2.0
75 #define TRICK_PLAY_MUTE_THRESHOLD_MIN   0.0
76
77 #define MM_VOLUME_FACTOR_DEFAULT                1.0
78 #define MM_VOLUME_FACTOR_MIN                            0
79 #define MM_VOLUME_FACTOR_MAX                            1.0
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 #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) )
92
93 #define LAZY_PAUSE_TIMEOUT_MSEC 700
94
95 /*---------------------------------------------------------------------------
96 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
97 ---------------------------------------------------------------------------*/
98
99 /*---------------------------------------------------------------------------
100 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
101 ---------------------------------------------------------------------------*/
102
103 /*---------------------------------------------------------------------------
104 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
105 ---------------------------------------------------------------------------*/
106
107 /*---------------------------------------------------------------------------
108 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
109 ---------------------------------------------------------------------------*/
110
111 /*---------------------------------------------------------------------------
112 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
113 ---------------------------------------------------------------------------*/
114 static gboolean __mmplayer_set_state(mm_player_t* player, int state);
115 static int              __mmplayer_get_state(mm_player_t* player);
116 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
117 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
118 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
119 static gboolean __mmplayer_is_amr_type (gchar *str_caps);
120 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
121
122 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
123 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
124 static void     __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
125
126 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player );
127 static void     __mmplayer_init_factories(mm_player_t* player);
128 static void     __mmplayer_release_factories(mm_player_t* player);
129 static void     __mmplayer_release_misc(mm_player_t* player);
130 static gboolean __mmplayer_gstreamer_init(void);
131
132 gboolean __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param);
133
134 int             __mmplayer_switch_audio_sink (mm_player_t* player);
135 static int              __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
136 static gboolean __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data);
137 static void             __mmplayer_post_delayed_eos( mm_player_t* player, int delay_in_ms );
138 static void     __mmplayer_cancel_delayed_eos( mm_player_t* player );
139 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, gchar* mime);
140 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
141 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force);
142 static gpointer __mmplayer_repeat_thread(gpointer data);
143 int _mmplayer_get_track_count(MMHandleType hplayer,  MMPlayerTrackType track_type, int *count);
144 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
145 static void     __gst_set_async_state_change(mm_player_t* player, gboolean async);
146 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
147 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
148
149 /*fadeout */
150 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
151 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
152
153 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
154 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
155
156 /* util */
157 const gchar * __get_state_name ( int state );
158
159 static gboolean __mmplayer_warm_up_video_codec( mm_player_t* player,  GstElementFactory *factory);
160
161 static int  __mmplayer_realize_streaming_ext(mm_player_t* player);
162 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
163 static int __mmplayer_start_streaming_ext(mm_player_t *player);
164 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
165
166
167 /*===========================================================================================
168 |                                                                                                                                                                                       |
169 |  FUNCTION DEFINITIONS                                                                                                                                         |
170 |                                                                                                                                                                                       |
171 ========================================================================================== */
172
173 /* implementing player FSM */
174 /* FIXIT : We need to handle state transition also at here since start api is no more sync */
175 static int
176 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
177 {
178         MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
179         MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
180         MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
181         MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
182
183         debug_fenter();
184
185         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
186
187         //debug_log("incomming command : %d \n", command );
188
189         current_state = MMPLAYER_CURRENT_STATE(player);
190         pending_state = MMPLAYER_PENDING_STATE(player);
191         target_state = MMPLAYER_TARGET_STATE(player);
192         prev_state = MMPLAYER_PREV_STATE(player);
193
194         MMPLAYER_PRINT_STATE(player);
195
196         switch( command )
197         {
198                 case MMPLAYER_COMMAND_CREATE:
199                 {
200                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
201
202                         if ( current_state == MM_PLAYER_STATE_NULL ||
203                                 current_state == MM_PLAYER_STATE_READY ||
204                                 current_state == MM_PLAYER_STATE_PAUSED ||
205                                 current_state == MM_PLAYER_STATE_PLAYING )
206                                 goto NO_OP;
207                 }
208                 break;
209
210                 case MMPLAYER_COMMAND_DESTROY:
211                 {
212                         /* destroy can called anytime */
213
214                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
215                 }
216                 break;
217
218                 case MMPLAYER_COMMAND_REALIZE:
219                 {
220                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
221
222                         if ( pending_state != MM_PLAYER_STATE_NONE )
223                         {
224                                 goto INVALID_STATE;
225                         }
226                         else
227                         {
228                                 /* need ready state to realize */
229                                 if ( current_state == MM_PLAYER_STATE_READY )
230                                         goto NO_OP;
231
232                                 if ( current_state != MM_PLAYER_STATE_NULL )
233                                         goto INVALID_STATE;
234                         }
235                 }
236                 break;
237
238                 case MMPLAYER_COMMAND_UNREALIZE:
239                 {
240                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
241
242                         if ( current_state == MM_PLAYER_STATE_NULL )
243                                 goto NO_OP;
244                 }
245                 break;
246
247                 case MMPLAYER_COMMAND_START:
248                 {
249                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
250
251                         if ( pending_state == MM_PLAYER_STATE_NONE )
252                         {
253                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
254                                         goto NO_OP;
255                                 else if ( current_state  != MM_PLAYER_STATE_READY &&
256                                         current_state != MM_PLAYER_STATE_PAUSED )
257                                         goto INVALID_STATE;
258                         }
259                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
260                         {
261                                 goto ALREADY_GOING;
262                         }
263                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
264                         {
265                                 debug_log("player is going to paused state, just change the pending state as playing");
266                         }
267                         else
268                         {
269                                 goto INVALID_STATE;
270                         }
271                 }
272                 break;
273
274                 case MMPLAYER_COMMAND_STOP:
275                 {
276                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
277
278                         if ( current_state == MM_PLAYER_STATE_READY )
279                                 goto NO_OP;
280
281                         /* need playing/paused state to stop */
282                         if ( current_state != MM_PLAYER_STATE_PLAYING &&
283                                  current_state != MM_PLAYER_STATE_PAUSED )
284                                 goto INVALID_STATE;
285                 }
286                 break;
287
288                 case MMPLAYER_COMMAND_PAUSE:
289                 {
290                         if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
291                                 goto NO_OP;
292
293                         if (player->doing_seek)
294                                 goto NOT_COMPLETED_SEEK;
295
296                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
297
298                         if ( pending_state == MM_PLAYER_STATE_NONE )
299                         {
300                                 if ( current_state == MM_PLAYER_STATE_PAUSED )
301                                         goto NO_OP;
302                                 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
303                                         goto INVALID_STATE;
304                         }
305                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
306                         {
307                                 goto ALREADY_GOING;
308                         }
309                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
310                         {
311                                 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
312                                         debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
313                                 } else {
314                                         goto INVALID_STATE;
315                                 }
316                         }
317                 }
318                 break;
319
320                 case MMPLAYER_COMMAND_RESUME:
321                 {
322                         if ( MMPLAYER_IS_LIVE_STREAMING(player) )
323                                 goto NO_OP;
324
325                         if (player->doing_seek)
326                                 goto NOT_COMPLETED_SEEK;
327
328                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
329
330                         if ( pending_state == MM_PLAYER_STATE_NONE )
331                         {
332                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
333                                         goto NO_OP;
334                                 else if (  current_state != MM_PLAYER_STATE_PAUSED )
335                                         goto INVALID_STATE;
336                         }
337                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
338                         {
339                                 goto ALREADY_GOING;
340                         }
341                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
342                         {
343                                 debug_log("player is going to paused state, just change the pending state as playing");
344                         }
345                         else
346                         {
347                                 goto INVALID_STATE;
348                         }
349                 }
350                 break;
351
352                 default:
353                 break;
354         }
355         player->cmd = command;
356
357         debug_fleave();
358         return MM_ERROR_NONE;
359
360 INVALID_STATE:
361         debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
362                 MMPLAYER_STATE_GET_NAME(current_state), command);
363         return MM_ERROR_PLAYER_INVALID_STATE;
364
365 NOT_COMPLETED_SEEK:
366         debug_warning("not completed seek");
367         return MM_ERROR_PLAYER_DOING_SEEK;
368
369 NO_OP:
370         debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
371         return MM_ERROR_PLAYER_NO_OP;
372
373 ALREADY_GOING:
374         debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
375         return MM_ERROR_PLAYER_NO_OP;
376 }
377
378 void
379 __mmplayer_videostream_cb(GstElement *element, void *stream,
380 int width, int height, gpointer data) // @
381 {
382         mm_player_t* player = (mm_player_t*)data;
383         int length = 0;
384
385         return_if_fail ( player );
386
387         debug_fenter();
388
389         if (player->video_stream_cb )
390         {
391                 length = width * height * 4; // for rgb 32bit
392                 player->video_stream_cb(stream, length, player->video_stream_cb_user_param, width, height);
393         }
394
395         debug_fleave();
396 }
397
398 void
399 __mmplayer_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer data)
400 {
401         mm_player_t* player = (mm_player_t*)data;
402
403         return_if_fail ( player );
404
405         debug_fenter();
406
407         if (player->video_frame_render_error_cb )
408         {
409                 if (player->attrs)
410                 {
411                         int surface_type = 0;
412                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
413                         switch (surface_type)
414                         {
415                         case MM_DISPLAY_SURFACE_X_EXT:
416                                 player->video_frame_render_error_cb((unsigned int*)error_id, player->video_frame_render_error_cb_user_param);
417                                 debug_log("display surface type(X_EXT) : render error callback(%p) is finished", player->video_frame_render_error_cb);
418                                 break;
419                         default:
420                                 debug_error("video_frame_render_error_cb was set, but this surface type(%d) is not supported", surface_type);
421                                 break;
422                         }
423                 }
424                 else
425                 {
426                         debug_error("could not get surface type");
427                 }
428         }
429         else
430         {
431                 debug_warning("video_frame_render_error_cb was not set");
432         }
433
434         debug_fleave();
435 }
436
437 /* This function should be called after the pipeline goes PAUSED or higher
438 state. */
439 gboolean
440 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
441 {
442         static gboolean has_duration = FALSE;
443         static gboolean has_video_attrs = FALSE;
444         static gboolean has_audio_attrs = FALSE;
445         static gboolean has_bitrate = FALSE;
446         gboolean missing_only = FALSE;
447         gboolean all = FALSE;
448
449 #ifndef GST_API_VERSION_1
450         GstFormat fmt  = GST_FORMAT_TIME;
451 #endif
452         gint64 dur_nsec = 0;
453         GstStructure* p = NULL;
454         MMHandleType attrs = 0;
455         gchar *path = NULL;
456         gint stream_service_type = STREAMING_SERVICE_NONE;
457         struct stat sb;
458
459         debug_fenter();
460
461         return_val_if_fail ( player, FALSE );
462
463         /* check player state here */
464         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
465                 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING )
466         {
467                 /* give warning now only */
468                 debug_warning("be careful. content attributes may not available in this state ");
469         }
470
471         /* get content attribute first */
472         attrs = MMPLAYER_GET_ATTRS(player);
473         if ( !attrs )
474         {
475                 debug_error("cannot get content attribute");
476                 return FALSE;
477         }
478
479         /* get update flag */
480
481         if ( flag & ATTR_MISSING_ONLY )
482         {
483                 missing_only = TRUE;
484                 debug_log("updating missed attr only");
485         }
486
487         if ( flag & ATTR_ALL )
488         {
489                 all = TRUE;
490                 has_duration = FALSE;
491                 has_video_attrs = FALSE;
492                 has_audio_attrs = FALSE;
493                 has_bitrate = FALSE;
494
495                 debug_log("updating all attrs");
496         }
497
498         if ( missing_only && all )
499         {
500                 debug_warning("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
501                 missing_only = FALSE;
502         }
503
504         if (  (flag & ATTR_DURATION) || (!has_duration && missing_only) || all )
505         {
506                 debug_log("try to update duration");
507                 has_duration = FALSE;
508
509 #ifdef GST_API_VERSION_1
510                 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
511                 {
512                         player->duration = dur_nsec;
513                         debug_log("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
514                 }
515 #else
516                 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec ))
517                 {
518                         player->duration = dur_nsec;
519                         debug_log("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
520                 }
521 #endif
522
523                 /* try to get streaming service type */
524                 stream_service_type = __mmplayer_get_stream_service_type( player );
525                 mm_attrs_set_int_by_name ( attrs, "streaming_type", stream_service_type );
526
527                 /* check duration is OK */
528                 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
529                 {
530                         debug_error("not ready to get duration");
531                 }
532                 else
533                 {
534                         /*update duration */
535                         mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
536                         has_duration = TRUE;
537                         debug_log("duration updated");
538                 }
539         }
540
541         if (  (flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all )
542         {
543                 /* update audio params
544                 NOTE : We need original audio params and it can be only obtained from src pad of audio
545                 decoder. Below code only valid when we are not using 'resampler' just before
546                 'audioconverter'. */
547
548                 debug_log("try to update audio attrs");
549                 has_audio_attrs = FALSE;
550
551                 if ( player->pipeline->audiobin &&
552                          player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
553                 {
554                         GstCaps *caps_a = NULL;
555                         GstPad* pad = NULL;
556                         gint samplerate = 0, channels = 0;
557
558                         pad = gst_element_get_static_pad(
559                                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
560
561                         if ( pad )
562                         {
563 #ifdef GST_API_VERSION_1
564                                 caps_a = gst_pad_get_current_caps( pad );
565 #else
566                                 caps_a = gst_pad_get_negotiated_caps( pad );
567 #endif
568
569                                 if ( caps_a )
570                                 {
571                                         p = gst_caps_get_structure (caps_a, 0);
572
573                                         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
574
575                                         gst_structure_get_int (p, "rate", &samplerate);
576                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
577
578                                         gst_structure_get_int (p, "channels", &channels);
579                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
580
581                                         debug_log("samplerate : %d      channels : %d", samplerate, channels);
582
583                                         gst_caps_unref( caps_a );
584                                         caps_a = NULL;
585
586                                         has_audio_attrs = TRUE;
587                                 }
588                                 else
589                                 {
590                                         debug_warning("not ready to get audio caps");
591                                 }
592
593                                 gst_object_unref( pad );
594                         }
595                         else
596                         {
597                                 debug_warning("failed to get pad from audiosink");
598                         }
599                 }
600         }
601
602         if ( (flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all )
603         {
604                 debug_log("try to update video attrs");
605                 has_video_attrs = FALSE;
606
607                 if ( player->pipeline->videobin &&
608                          player->pipeline->videobin[MMPLAYER_V_SINK].gst )
609                 {
610                         GstCaps *caps_v = NULL;
611                         GstPad* pad = NULL;
612                         gint tmpNu, tmpDe;
613                         gint width, height;
614
615                         pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
616                         if ( pad )
617                         {
618 #ifdef GST_API_VERSION_1
619                                 caps_v = gst_pad_get_current_caps( pad );
620 #else
621                                 caps_v = gst_pad_get_negotiated_caps( pad );
622 #endif
623                                 if (caps_v)
624                                 {
625                                         p = gst_caps_get_structure (caps_v, 0);
626                                         gst_structure_get_int (p, "width", &width);
627                                         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
628
629                                         gst_structure_get_int (p, "height", &height);
630                                         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
631
632                                         gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
633
634                                         debug_log("width : %d     height : %d", width, height );
635
636                                         gst_caps_unref( caps_v );
637                                         caps_v = NULL;
638
639                                         if (tmpDe > 0)
640                                         {
641                                                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
642                                                 debug_log("fps : %d", tmpNu / tmpDe);
643                                         }
644
645                                         has_video_attrs = TRUE;
646                                 }
647                                 else
648                                 {
649                                         debug_log("no negitiated caps from videosink");
650                                 }
651                                 gst_object_unref( pad );
652                                 pad = NULL;
653                         }
654                         else
655                         {
656                                 debug_log("no videosink sink pad");
657                         }
658                 }
659         }
660
661
662         if ( (flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all )
663         {
664                 debug_log("try to update bitrate");
665                 has_bitrate = FALSE;
666
667                 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
668                 if (player->duration)
669                 {
670                         guint64 data_size = 0;
671
672                         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
673                         {
674                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
675
676                                 if (stat(path, &sb) == 0)
677                                 {
678                                         data_size = (guint64)sb.st_size;
679                                 }
680                         }
681                         else if (MMPLAYER_IS_HTTP_STREAMING(player))
682                         {
683                                 data_size = player->http_content_size;
684                         }
685
686                         if (data_size)
687                         {
688                                 guint64 bitrate = 0;
689                                 guint64 msec_dur = 0;
690
691                                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
692                                 bitrate = data_size * 8 * 1000 / msec_dur;
693                                 debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
694                                 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
695
696                                 has_bitrate = TRUE;
697                         }
698                 }
699         }
700
701         /* validate all */
702         if (  mmf_attrs_commit ( attrs ) )
703         {
704                 debug_error("failed to update attributes\n");
705                 return FALSE;
706         }
707
708         debug_fleave();
709         return TRUE;
710 }
711
712 gint __mmplayer_get_stream_service_type( mm_player_t* player )
713 {
714         gint streaming_type = STREAMING_SERVICE_NONE;
715
716         debug_fenter();
717
718         return_val_if_fail ( player &&
719                         player->pipeline &&
720                         player->pipeline->mainbin &&
721                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
722                         FALSE );
723
724         /* streaming service type if streaming */
725         if ( ! MMPLAYER_IS_STREAMING(player) )
726         {
727                 debug_log("not a streamming");
728                 return STREAMING_SERVICE_NONE;
729         }
730
731         if (MMPLAYER_IS_RTSP_STREAMING(player))
732         {
733                 /* get property from rtspsrc element */
734                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst),
735                         "service_type", &streaming_type, NULL);
736         }
737         else if (MMPLAYER_IS_HTTP_STREAMING(player))
738         {
739                 streaming_type = player->duration == 0 ?
740                         STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
741         }
742
743         switch ( streaming_type )
744         {
745                 case STREAMING_SERVICE_LIVE:
746                         debug_log("it's live streaming");
747                 break;
748                 case STREAMING_SERVICE_VOD:
749                         debug_log("it's vod streaming");
750                 break;
751                 case STREAMING_SERVICE_NONE:
752                         debug_error("should not get here");
753                 break;
754                 default:
755                         debug_error("should not get here");
756         }
757
758         player->streaming_type = streaming_type;
759         debug_fleave();
760
761         return streaming_type;
762 }
763
764
765 /* this function sets the player state and also report
766  * it to applicaton by calling callback function
767  */
768 static gboolean
769 __mmplayer_set_state(mm_player_t* player, int state) // @
770 {
771         MMMessageParamType msg = {0, };
772         int asm_result = MM_ERROR_NONE;
773         gboolean post_bos = FALSE;
774         gboolean interrupted_by_asm = FALSE;
775
776         debug_fenter();
777         return_val_if_fail ( player, FALSE );
778
779         if ( MMPLAYER_CURRENT_STATE(player) == state )
780         {
781                 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
782                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
783                 return TRUE;
784         }
785
786         /* update player states */
787         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
788         MMPLAYER_CURRENT_STATE(player) = state;
789
790         /* FIXIT : it's better to do like below code
791         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player) )
792                         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
793         and add more code to handling PENDING_STATE.
794         */
795         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
796                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
797
798         /* print state */
799         MMPLAYER_PRINT_STATE(player);
800
801         /* do some FSM stuffs before posting new state to application  */
802         interrupted_by_asm = player->sm.by_asm_cb;
803
804         switch ( MMPLAYER_CURRENT_STATE(player) )
805         {
806                 case MM_PLAYER_STATE_NULL:
807                 case MM_PLAYER_STATE_READY:
808                 {
809                         if (player->cmd == MMPLAYER_COMMAND_STOP)
810                         {
811                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP);
812                                 if ( asm_result != MM_ERROR_NONE )
813                                 {
814                                         debug_error("failed to set asm state to stop\n");
815                                         return FALSE;
816                                 }
817                         }
818                 }
819                 break;
820
821                 case MM_PLAYER_STATE_PAUSED:
822                 {
823                          if ( ! player->sent_bos )
824                          {
825                                 /* it's first time to update all content attrs. */
826                                 _mmplayer_update_content_attrs( player, ATTR_ALL );
827                          }
828
829                         /* add audio callback probe if condition is satisfied */
830                         if ( ! player->audio_cb_probe_id && player->is_sound_extraction )
831                         {
832                                 __mmplayer_configure_audio_callback(player);
833                         }
834
835                         asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE);
836                         if ( asm_result )
837                         {
838                                 debug_error("failed to set asm state to PAUSE\n");
839                                 return FALSE;
840                         }
841                 }
842                 break;
843
844                 case MM_PLAYER_STATE_PLAYING:
845                 {
846                         /* try to get content metadata */
847                         if ( ! player->sent_bos )
848                         {
849                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
850                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
851                                  * legacy mmfw-player api */
852                                 _mmplayer_update_content_attrs( player, ATTR_MISSING_ONLY);
853                         }
854
855                         if ( player->cmd == MMPLAYER_COMMAND_START  && !player->sent_bos )
856                         {
857                                 __mmplayer_handle_missed_plugin ( player );
858
859                                 /* update video resource status */
860                                 if ( ( player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO )
861                                 {
862                                         asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING);
863                                         if ( asm_result )
864                                         {
865                                                 MMMessageParamType msg = {0, };
866
867                                                 debug_error("failed to go ahead because of video conflict\n");
868
869                                                 msg.union_type = MM_MSG_UNION_CODE;
870                                                 msg.code = MM_ERROR_POLICY_INTERRUPTED;
871                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
872
873                                                 _mmplayer_unrealize((MMHandleType)player);
874
875                                                 return FALSE;
876                                         }
877                                 }
878                         }
879
880                         if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
881                         {
882                                 /* initialize because auto resume is done well. */
883                                 player->resumed_by_rewind = FALSE;
884                                 player->playback_rate = 1.0;
885                         }
886
887                         if ( !player->sent_bos )
888                         {
889                                 /* check audio codec field is set or not
890                                  * we can get it from typefinder or codec's caps.
891                                  */
892                                 gchar *audio_codec = NULL;
893                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
894
895                                 /* The codec format can't be sent for audio only case like amr, mid etc.
896                                  * Because, parser don't make related TAG.
897                                  * So, if it's not set yet, fill it with found data.
898                                  */
899                                 if ( ! audio_codec )
900                                 {
901                                         if ( g_strrstr(player->type, "audio/midi"))
902                                         {
903                                                 audio_codec = g_strdup("MIDI");
904
905                                         }
906                                         else if ( g_strrstr(player->type, "audio/x-amr"))
907                                         {
908                                                 audio_codec = g_strdup("AMR");
909                                         }
910                                         else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
911                                         {
912                                                 audio_codec = g_strdup("AAC");
913                                         }
914                                         else
915                                         {
916                                                 audio_codec = g_strdup("unknown");
917                                         }
918                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
919
920                                         MMPLAYER_FREEIF(audio_codec);
921                                         mmf_attrs_commit(player->attrs);
922                                         debug_log("set audio codec type with caps\n");
923                                 }
924
925                                 post_bos = TRUE;
926                         }
927                 }
928                 break;
929
930                 case MM_PLAYER_STATE_NONE:
931                 default:
932                         debug_warning("invalid target state, there is nothing to do.\n");
933                         break;
934         }
935
936
937         /* post message to application */
938         if (MMPLAYER_TARGET_STATE(player) == state)
939         {
940                 /* fill the message with state of player */
941                 msg.state.previous = MMPLAYER_PREV_STATE(player);
942                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
943
944                 /* state changed by asm callback */
945                 if ( interrupted_by_asm )
946                 {
947                         msg.union_type = MM_MSG_UNION_CODE;
948                         msg.code = player->sm.event_src;
949                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
950                 }
951                 /* state changed by usecase */
952                 else
953                 {
954                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
955                 }
956
957                 debug_log ("player reach the target state, then do something in each state(%s).\n",
958                         MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
959         }
960         else
961         {
962                 debug_log ("intermediate state, do nothing.\n");
963                 MMPLAYER_PRINT_STATE(player);
964                 return TRUE;
965         }
966
967         if ( post_bos )
968         {
969                 MMTA_ACUM_ITEM_END("[KPI] start media player service", FALSE);
970                 MMTA_ACUM_ITEM_END("[KPI] media player service create->playing", FALSE);
971
972                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
973                 player->sent_bos = TRUE;
974         }
975
976         debug_fleave();
977         return TRUE;
978 }
979
980
981 gboolean
982 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
983 {
984         return_val_if_fail( player, FALSE );
985
986         debug_fenter();
987
988         if ( !player->msg_cb )
989         {
990                 debug_warning("no msg callback. can't post msg now\n");
991                 return FALSE;
992         }
993
994         //debug_log("Message (type : %d)  will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
995
996         player->msg_cb(msgtype, param, player->msg_cb_param);
997
998         debug_fleave();
999
1000         return TRUE;
1001 }
1002
1003
1004 static int
1005 __mmplayer_get_state(mm_player_t* player) // @
1006 {
1007         int state = MM_PLAYER_STATE_NONE;
1008
1009         debug_fenter();
1010
1011         return_val_if_fail ( player, MM_PLAYER_STATE_NONE );
1012
1013         state = MMPLAYER_CURRENT_STATE(player);
1014
1015         debug_log("player state is %s.\n", MMPLAYER_STATE_GET_NAME(state));
1016
1017         debug_fleave();
1018
1019         return state;
1020 }
1021
1022 static void
1023 __gst_set_async_state_change(mm_player_t* player, gboolean async)
1024 {
1025         //debug_fenter();
1026         return_if_fail( player && player->pipeline && player->pipeline->mainbin );
1027
1028         /* need only when we are using decodebin */
1029         if ( ! PLAYER_INI()->use_decodebin )
1030                 return;
1031
1032         /* audio sink */
1033         if ( player->pipeline->audiobin &&
1034                  player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
1035         {
1036                 debug_log("audiosink async : %d\n", async);
1037                 g_object_set (G_OBJECT (player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "async", async, NULL);
1038         }
1039
1040         /* video sink */
1041         if ( player->pipeline->videobin &&
1042                  player->pipeline->videobin[MMPLAYER_V_SINK].gst )
1043         {
1044                 debug_log("videosink async : %d\n", async);
1045                 g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "async", async, NULL);
1046         }
1047
1048         /* decodebin if enabled */
1049         if ( PLAYER_INI()->use_decodebin )
1050         {
1051                 debug_log("decodebin async : %d\n", async);
1052                 g_object_set (G_OBJECT (player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst), "async-handling", async, NULL);
1053         }
1054
1055         //debug_fleave();
1056 }
1057
1058 static gpointer __mmplayer_repeat_thread(gpointer data)
1059 {
1060         mm_player_t* player = (mm_player_t*) data;
1061         gboolean ret_value = FALSE;
1062         MMHandleType attrs = 0;
1063         gint count = 0;
1064
1065         return_val_if_fail ( player, NULL );
1066
1067         while ( ! player->repeat_thread_exit )
1068         {
1069                 debug_log("repeat thread started. waiting for signal.\n");
1070                 g_cond_wait( player->repeat_thread_cond, player->repeat_thread_mutex );
1071
1072                 if ( player->repeat_thread_exit )
1073                 {
1074                         debug_log("exiting repeat thread\n");
1075                         break;
1076                 }
1077
1078                 if ( !player->cmd_lock )
1079                 {
1080                         debug_log("can't get cmd lock\n");
1081                         return NULL;
1082                 }
1083
1084                 /* lock */
1085                 g_mutex_lock(player->cmd_lock);
1086
1087                 attrs = MMPLAYER_GET_ATTRS(player);
1088
1089                 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1090                 {
1091                         debug_error("can not get play count\n");
1092                         break;
1093                 }
1094
1095                 if ( player->section_repeat )
1096                 {
1097                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1098                 }
1099                 else
1100                 {
1101                         if ( player->playback_rate < 0.0 )
1102                         {
1103                                 player->resumed_by_rewind = TRUE;
1104                                 _mmplayer_set_mute((MMHandleType)player, 0);
1105                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1106                         }
1107
1108                         ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
1109                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1110                                 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1111
1112                         /* initialize */
1113                         player->sent_bos = FALSE;
1114                 }
1115
1116                 if ( ! ret_value )
1117                 {
1118                         debug_error("failed to set position to zero for rewind\n");
1119                         continue;
1120                 }
1121
1122                 /* decrease play count */
1123                 if ( count > 1 )
1124                 {
1125                         /* we successeded to rewind. update play count and then wait for next EOS */
1126                         count--;
1127
1128                         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1129
1130                         /* commit attribute */
1131                         if ( mmf_attrs_commit ( attrs ) )
1132                         {
1133                                 debug_error("failed to commit attribute\n");
1134                         }
1135                 }
1136
1137                 /* unlock */
1138                 g_mutex_unlock(player->cmd_lock);
1139         }
1140
1141         return NULL;
1142 }
1143
1144 static void
1145 __mmplayer_handle_buffering_message ( mm_player_t* player )
1146 {
1147         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1148         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1149         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1150         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1151
1152         return_if_fail ( player );
1153
1154         prev_state = MMPLAYER_PREV_STATE(player),
1155         current_state = MMPLAYER_CURRENT_STATE(player);
1156         target_state = MMPLAYER_TARGET_STATE(player);
1157         pending_state = MMPLAYER_PENDING_STATE(player);
1158
1159         if ( MMPLAYER_IS_RTSP_STREAMING(player) )
1160                 return;
1161
1162         if ( !player->streamer->is_buffering )
1163         {
1164                 debug_log( "player state : prev %s, current %s, pending %s, target %s \n",
1165                         MMPLAYER_STATE_GET_NAME(prev_state),
1166                         MMPLAYER_STATE_GET_NAME(current_state),
1167                         MMPLAYER_STATE_GET_NAME(pending_state),
1168                         MMPLAYER_STATE_GET_NAME(target_state));
1169
1170                 /* NOTE : if buffering has done, player has to go to target state. */
1171                 switch ( target_state )
1172                 {
1173                         case MM_PLAYER_STATE_PAUSED :
1174                         {
1175                                 switch ( pending_state )
1176                                 {
1177                                         case MM_PLAYER_STATE_PLAYING:
1178                                         {
1179                                                 __gst_pause ( player, TRUE );
1180                                         }
1181                                         break;
1182
1183                                         case MM_PLAYER_STATE_PAUSED:
1184                                         {
1185                                                  debug_log("player is already going to paused state, there is nothing to do.\n");
1186                                         }
1187                                         break;
1188
1189                                         case MM_PLAYER_STATE_NONE:
1190                                         case MM_PLAYER_STATE_NULL:
1191                                         case MM_PLAYER_STATE_READY:
1192                                         default :
1193                                         {
1194                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1195                                         }
1196                                                 break;
1197                                 }
1198                         }
1199                         break;
1200
1201                         case MM_PLAYER_STATE_PLAYING :
1202                         {
1203                                 switch ( pending_state )
1204                                 {
1205                                         case MM_PLAYER_STATE_NONE:
1206                                         {
1207                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
1208                                                         __gst_resume ( player, TRUE );
1209                                         }
1210                                         break;
1211
1212                                         case MM_PLAYER_STATE_PAUSED:
1213                                         {
1214                                                 /* NOTE: It should be worked as asynchronously.
1215                                                  * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1216                                                  */
1217                                                 __gst_resume ( player, TRUE );
1218                                         }
1219                                         break;
1220
1221                                         case MM_PLAYER_STATE_PLAYING:
1222                                         {
1223                                                  debug_log("player is already going to playing state, there is nothing to do.\n");
1224                                         }
1225                                         break;
1226
1227                                         case MM_PLAYER_STATE_NULL:
1228                                         case MM_PLAYER_STATE_READY:
1229                                         default :
1230                                         {
1231                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1232                                         }
1233                                                 break;
1234                                 }
1235                         }
1236                         break;
1237
1238                         case MM_PLAYER_STATE_NULL :
1239                         case MM_PLAYER_STATE_READY :
1240                         case MM_PLAYER_STATE_NONE :
1241                         default:
1242                         {
1243                                 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1244                         }
1245                                 break;
1246                 }
1247         }
1248         else
1249         {
1250                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1251                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
1252                  */
1253                 switch ( pending_state )
1254                 {
1255                         case MM_PLAYER_STATE_NONE:
1256                         {
1257                                 if (current_state != MM_PLAYER_STATE_PAUSED)
1258                                         __gst_pause ( player, TRUE );
1259                         }
1260                         break;
1261
1262                         case MM_PLAYER_STATE_PLAYING:
1263                         {
1264                                 __gst_pause ( player, TRUE );
1265                         }
1266                         break;
1267
1268                         case MM_PLAYER_STATE_PAUSED:
1269                         {
1270                                  debug_log("player is already going to paused state, there is nothing to do.\n");
1271                         }
1272                         break;
1273
1274                         case MM_PLAYER_STATE_NULL:
1275                         case MM_PLAYER_STATE_READY:
1276                         default :
1277                         {
1278                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1279                         }
1280                                 break;
1281                 }
1282         }
1283 }
1284
1285
1286 static gboolean
1287 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
1288 {
1289         int pro_value = 0; // in the case of expection, default will be returned.
1290         int dest_angle = rotation_angle;
1291         int rotation_using_type = -1;
1292         #define ROTATION_USING_X        0
1293         #define ROTATION_USING_FIMC     1
1294         #define ROTATION_USING_FLIP     2
1295
1296         return_val_if_fail(player, FALSE);
1297         return_val_if_fail(value, FALSE);
1298         return_val_if_fail(rotation_angle >= 0, FALSE);
1299
1300         if (rotation_angle >= 360)
1301         {
1302                 dest_angle = rotation_angle - 360;
1303         }
1304
1305         /* chech if supported or not */
1306         if ( dest_angle % 90 )
1307         {
1308                 debug_log("not supported rotation angle = %d", rotation_angle);
1309                 return FALSE;
1310         }
1311
1312         if (player->use_video_stream)
1313         {
1314                 if (player->is_nv12_tiled)
1315                 {
1316                         rotation_using_type = ROTATION_USING_FIMC;
1317                 }
1318                 else
1319                 {
1320                         rotation_using_type = ROTATION_USING_FLIP;
1321                 }
1322         }
1323         else
1324         {
1325                 int surface_type = 0;
1326                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
1327                 debug_log("check display surface type for rotation: %d", surface_type);
1328
1329                 switch (surface_type)
1330                 {
1331                         case MM_DISPLAY_SURFACE_X:
1332                                 rotation_using_type = ROTATION_USING_X;
1333                                 break;
1334                         case MM_DISPLAY_SURFACE_EVAS:
1335                                 if (player->is_nv12_tiled && !strcmp(PLAYER_INI()->videosink_element_evas,"evasimagesink"))
1336                                 {
1337                                         rotation_using_type = ROTATION_USING_FIMC;
1338                                 }
1339                                 else if (!player->is_nv12_tiled)
1340                                 {
1341                                         rotation_using_type = ROTATION_USING_FLIP;
1342                                 }
1343                                 else
1344                                 {
1345                                         debug_error("it should not be here..");
1346                                         return FALSE;
1347                                 }
1348                                 break;
1349                         default:
1350                                 rotation_using_type = ROTATION_USING_FLIP;
1351                                 break;
1352                 }
1353         }
1354
1355         debug_log("using %d type for rotation", rotation_using_type);
1356
1357         /* get property value for setting */
1358         switch(rotation_using_type)
1359         {
1360                 case ROTATION_USING_X: // xvimagesink
1361                         {
1362                                 switch (dest_angle)
1363                                 {
1364                                         case 0:
1365                                                 break;
1366                                         case 90:
1367                                                 pro_value = 3; // clockwise 90
1368                                                 break;
1369                                         case 180:
1370                                                 pro_value = 2;
1371                                                 break;
1372                                         case 270:
1373                                                 pro_value = 1; // counter-clockwise 90
1374                                                 break;
1375                                 }
1376                         }
1377                         break;
1378                 case ROTATION_USING_FIMC: // fimcconvert
1379                         {
1380                                         switch (dest_angle)
1381                                         {
1382                                                 case 0:
1383                                                         break;
1384                                                 case 90:
1385                                                         pro_value = 90; // clockwise 90
1386                                                         break;
1387                                                 case 180:
1388                                                         pro_value = 180;
1389                                                         break;
1390                                                 case 270:
1391                                                         pro_value = 270; // counter-clockwise 90
1392                                                         break;
1393                                         }
1394                         }
1395                         break;
1396                 case ROTATION_USING_FLIP: // videoflip
1397                         {
1398                                         switch (dest_angle)
1399                                         {
1400
1401                                                 case 0:
1402                                                         break;
1403                                                 case 90:
1404                                                         pro_value = 1; // clockwise 90
1405                                                         break;
1406                                                 case 180:
1407                                                         pro_value = 2;
1408                                                         break;
1409                                                 case 270:
1410                                                         pro_value = 3; // counter-clockwise 90
1411                                                         break;
1412                                         }
1413                         }
1414                         break;
1415         }
1416
1417         debug_log("setting rotation property value : %d", pro_value);
1418
1419         *value = pro_value;
1420
1421         return TRUE;
1422 }
1423
1424 int
1425 _mmplayer_update_video_param(mm_player_t* player) // @
1426 {
1427         MMHandleType attrs = 0;
1428         int surface_type = 0;
1429         int org_angle = 0; // current supported angle values are 0, 90, 180, 270
1430         int user_angle = 0;
1431         int user_angle_type= 0;
1432         int rotation_value = 0;
1433
1434         debug_fenter();
1435
1436         /* check video sinkbin is created */
1437         return_val_if_fail ( player &&
1438                 player->pipeline &&
1439                 player->pipeline->videobin &&
1440                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
1441                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1442                 MM_ERROR_PLAYER_NOT_INITIALIZED );
1443
1444         attrs = MMPLAYER_GET_ATTRS(player);
1445         if ( !attrs )
1446         {
1447                 debug_error("cannot get content attribute");
1448                 return MM_ERROR_PLAYER_INTERNAL;
1449         }
1450
1451         /* update user roation */
1452         mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
1453
1454         /* get angle with user type */
1455         switch(user_angle_type)
1456         {
1457                 case MM_DISPLAY_ROTATION_NONE:
1458                         user_angle = 0;
1459                         break;
1460                 case MM_DISPLAY_ROTATION_90: // counter-clockwise 90
1461                         user_angle = 270;
1462                         break;
1463                 case MM_DISPLAY_ROTATION_180:
1464                         user_angle = 180;
1465                         break;
1466                 case MM_DISPLAY_ROTATION_270: // clockwise 90
1467                         user_angle = 90;
1468                         break;
1469         }
1470
1471         /* get original orientation */
1472         if (player->v_stream_caps)
1473         {
1474                 GstStructure *str = NULL;
1475
1476                 str = gst_caps_get_structure (player->v_stream_caps, 0);
1477                 if ( !gst_structure_get_int (str, "orientation", &org_angle))
1478                 {
1479                         debug_log ("missing 'orientation' field in video caps");
1480                 }
1481                 else
1482                 {
1483                         debug_log("origianl video orientation = %d", org_angle);
1484                 }
1485         }
1486
1487         debug_log("check user angle: %d, org angle: %d", user_angle, org_angle);
1488
1489         /* get rotation value to set */
1490         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
1491
1492         /* check video stream callback is used */
1493         if( player->use_video_stream )
1494         {
1495                 if (player->is_nv12_tiled)
1496                 {
1497                         gchar *ename = NULL;
1498                         int width = 0;
1499                         int height = 0;
1500
1501                         mm_attrs_get_int_by_name(attrs, "display_width", &width);
1502                         mm_attrs_get_int_by_name(attrs, "display_height", &height);
1503
1504                         /* resize video frame with requested values for fimcconvert */
1505 #ifdef GST_API_VERSION_1
1506                         ename = GST_OBJECT (gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
1507 #else
1508                         ename = GST_PLUGIN_FEATURE_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
1509 #endif
1510
1511                         if (g_strrstr(ename, "fimcconvert"))
1512                         {
1513                                 if (width)
1514                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
1515
1516                                 if (height)
1517                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
1518
1519                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "rotate", rotation_value, NULL);
1520                                 debug_log("updating fimcconvert - r[%d], w[%d], h[%d]", rotation_value, width, height);
1521                         }
1522                         else
1523                         {
1524                                 debug_error("no available video converter");
1525                                 return MM_ERROR_PLAYER_INTERNAL;
1526                         }
1527                 }
1528                 else
1529                 {
1530                         debug_log("using video stream callback with memsink. player handle : [%p]", player);
1531
1532                         g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
1533                 }
1534
1535                 return MM_ERROR_NONE;
1536         }
1537
1538         /* update display surface */
1539         mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
1540         debug_log("check display surface type attribute: %d", surface_type);
1541
1542         /* configuring display */
1543         switch ( surface_type )
1544         {
1545                 case MM_DISPLAY_SURFACE_X:
1546                 {
1547                         /* ximagesink or xvimagesink */
1548                         void *xid = NULL;
1549                         int zoom = 0;
1550                         int display_method = 0;
1551                         int roi_x = 0;
1552                         int roi_y = 0;
1553                         int roi_w = 0;
1554                         int roi_h = 0;
1555                         int force_aspect_ratio = 0;
1556                         gboolean visible = TRUE;
1557
1558                         /* common case if using x surface */
1559                         mm_attrs_get_data_by_name(attrs, "display_overlay", &xid);
1560                         if ( xid )
1561                         {
1562 #define GST_VAAPI_DISPLAY_TYPE_X11 1
1563                 if (!strncmp(PLAYER_INI()->videosink_element_x,"vaapisink", strlen("vaapisink"))){
1564                     debug_log("set video param: vaapisink display %d", GST_VAAPI_DISPLAY_TYPE_X11);
1565                     g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1566                             "display", GST_VAAPI_DISPLAY_TYPE_X11,
1567                             NULL);
1568                 }
1569
1570                                 debug_log("set video param : xid %d", *(int*)xid);
1571 #ifdef GST_API_VERSION_1
1572                                 gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)xid );
1573 #else
1574                                 gst_x_overlay_set_xwindow_id( GST_X_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)xid );
1575 #endif
1576                         }
1577                         else
1578                         {
1579                                 /* FIXIT : is it error case? */
1580                                 debug_warning("still we don't have xid on player attribute. create it's own surface.");
1581                         }
1582
1583                         /* if xvimagesink */
1584                         if (!strcmp(PLAYER_INI()->videosink_element_x,"xvimagesink"))
1585                         {
1586                                 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
1587                                 mm_attrs_get_int_by_name(attrs, "display_zoom", &zoom);
1588                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1589                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
1590                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
1591                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
1592                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
1593                                 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
1594
1595                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1596                                         "force-aspect-ratio", force_aspect_ratio,
1597                                         "zoom", zoom,
1598                                         "rotate", rotation_value,
1599                                         "handle-events", TRUE,
1600                                         "display-geometry-method", display_method,
1601                                         "draw-borders", FALSE,
1602                                         "dst-roi-x", roi_x,
1603                                         "dst-roi-y", roi_y,
1604                                         "dst-roi-w", roi_w,
1605                                         "dst-roi-h", roi_h,
1606                                         "visible", visible,
1607                                         NULL );
1608
1609                                 debug_log("set video param : zoom %d", zoom);
1610                                 debug_log("set video param : rotate %d", rotation_value);
1611                                 debug_log("set video param : method %d", display_method);
1612                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
1613                                                                 roi_x, roi_y, roi_w, roi_h );
1614                                 debug_log("set video param : visible %d", visible);
1615                                 debug_log("set video param : force aspect ratio %d", force_aspect_ratio);
1616                         }
1617
1618             /* if vaapisink */
1619             if (!strncmp(PLAYER_INI()->videosink_element_x, "vaapisink", strlen("vaapisink")))
1620             {
1621                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1622                         "rotation", rotation_value,
1623                         NULL);
1624                 debug_log("set video param: vaapisink rotation %d", rotation_value);
1625             }
1626                 }
1627                 break;
1628                 case MM_DISPLAY_SURFACE_EVAS:
1629                 {
1630                         void *object = NULL;
1631                         int scaling = 0;
1632                         gboolean visible = TRUE;
1633
1634                         /* common case if using evas surface */
1635                         mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
1636                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
1637                         mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
1638                         if (object)
1639                         {
1640                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1641                                                 "evas-object", object,
1642                                                 "visible", visible,
1643                                                 NULL);
1644                                 debug_log("set video param : evas-object %x", object);
1645                                 debug_log("set video param : visible %d", visible);
1646                         }
1647                         else
1648                         {
1649                                 debug_error("no evas object");
1650                                 return MM_ERROR_PLAYER_INTERNAL;
1651                         }
1652
1653                         /* if evasimagesink */
1654                         if (!strcmp(PLAYER_INI()->videosink_element_evas,"evasimagesink") && player->is_nv12_tiled)
1655                         {
1656                                 int width = 0;
1657                                 int height = 0;
1658                                 int no_scaling = !scaling;
1659
1660                                 mm_attrs_get_int_by_name(attrs, "display_width", &width);
1661                                 mm_attrs_get_int_by_name(attrs, "display_height", &height);
1662
1663                                 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
1664                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-buffer-num", 5, NULL);
1665
1666                                 if (no_scaling)
1667                                 {
1668                                         /* no-scaling order to fimcconvert, original width, height size of media src will be passed to sink plugin */
1669                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst,
1670                                                         "dst-width", 0, /* setting 0, output video width will be media src's width */
1671                                                         "dst-height", 0, /* setting 0, output video height will be media src's height */
1672                                                         NULL);
1673                                 }
1674                                 else
1675                                 {
1676                                         /* scaling order to fimcconvert */
1677                                         if (width)
1678                                         {
1679                                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
1680                                         }
1681                                         if (height)
1682                                         {
1683                                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
1684                                         }
1685                                         debug_log("set video param : video frame scaling down to width(%d) height(%d)", width, height);
1686                                 }
1687                                 debug_log("set video param : display_evas_do_scaling %d", scaling);
1688                         }
1689
1690                         /* if evaspixmapsink */
1691                         if (!strcmp(PLAYER_INI()->videosink_element_evas,"evaspixmapsink"))
1692                         {
1693                                 int display_method = 0;
1694                                 int roi_x = 0;
1695                                 int roi_y = 0;
1696                                 int roi_w = 0;
1697                                 int roi_h = 0;
1698                                 int origin_size = !scaling;
1699
1700                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1701                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
1702                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
1703                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
1704                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
1705
1706                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1707                                         "origin-size", origin_size,
1708                                         "dst-roi-x", roi_x,
1709                                         "dst-roi-y", roi_y,
1710                                         "dst-roi-w", roi_w,
1711                                         "dst-roi-h", roi_h,
1712                                         "display-geometry-method", display_method,
1713                                         NULL );
1714
1715                                 debug_log("set video param : method %d", display_method);
1716                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
1717                                                                 roi_x, roi_y, roi_w, roi_h );
1718                                 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
1719                         }
1720                         g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
1721                 }
1722                 break;
1723                 case MM_DISPLAY_SURFACE_X_EXT:  /* NOTE : this surface type is used for the videoTexture(canvasTexture) overlay */
1724                 {
1725                         void *pixmap_id_cb = NULL;
1726                         void *pixmap_id_cb_user_data = NULL;
1727                         int display_method = 0;
1728                         gboolean visible = TRUE;
1729
1730                         /* if xvimagesink */
1731                         if (strcmp(PLAYER_INI()->videosink_element_x,"xvimagesink"))
1732                         {
1733                                 debug_error("videosink is not xvimagesink");
1734                                 return MM_ERROR_PLAYER_INTERNAL;
1735                         }
1736
1737                         /* get information from attributes */
1738                         mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
1739                         mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
1740                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1741
1742                         if ( pixmap_id_cb )
1743                         {
1744                                 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
1745                                 if (pixmap_id_cb_user_data)
1746                                 {
1747                                         debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
1748                                 }
1749                         }
1750                         else
1751                         {
1752                                 debug_error("failed to set pixmap-id-callback");
1753                                 return MM_ERROR_PLAYER_INTERNAL;
1754                         }
1755                         debug_log("set video param : method %d", display_method);
1756                         debug_log("set video param : visible %d", visible);
1757
1758                         /* set properties of videosink plugin */
1759                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1760                                 "display-geometry-method", display_method,
1761                                 "draw-borders", FALSE,
1762                                 "visible", visible,
1763                                 "rotate", rotation_value,
1764                                 "pixmap-id-callback", pixmap_id_cb,
1765                                 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
1766                                 NULL );
1767                 }
1768                 break;
1769                 case MM_DISPLAY_SURFACE_NULL:
1770                 {
1771                         /* do nothing */
1772                 }
1773                 break;
1774         }
1775
1776         debug_fleave();
1777
1778         return MM_ERROR_NONE;
1779 }
1780
1781 static gboolean
1782 __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data)
1783 {
1784         mm_player_t* player = (mm_player_t*) u_data;
1785         gint size;
1786         guint8 *data;
1787
1788 #ifdef GST_API_VERSION_1
1789         GstMapInfo info;
1790         gst_buffer_map (buffer, &info, GST_MAP_WRITE);
1791         data = info.data;
1792         size = gst_buffer_get_size(buffer);
1793
1794         if (player->audio_stream_cb && size && data)
1795                 player->audio_stream_cb((void *)data, size, player->audio_stream_cb_user_param);
1796
1797         gst_buffer_unmap (buffer, &info);
1798 #else
1799         data = GST_BUFFER_DATA(buffer);
1800         size = GST_BUFFER_SIZE(buffer);
1801
1802         if (player->audio_stream_cb && size && data)
1803                 player->audio_stream_cb((void *)data, size, player->audio_stream_cb_user_param);
1804 #endif
1805
1806         return TRUE;
1807 }
1808
1809
1810 #ifdef GST_API_VERSION_1
1811 gboolean
1812 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
1813 {
1814         mm_player_t* player = (mm_player_t*) data;
1815         MMMessageParamType msg = {0, };
1816         GstClockTime duration = 0;
1817         guint8 *text = NULL;
1818         gboolean ret = TRUE;
1819         GstMapInfo info;
1820
1821         debug_fenter();
1822
1823         return_val_if_fail ( player, FALSE );
1824         return_val_if_fail ( buffer, FALSE );
1825
1826         gst_buffer_map (buffer, &info, GST_MAP_WRITE);
1827         text = info.data;
1828         gst_buffer_unmap (buffer, &info);
1829
1830         duration = GST_BUFFER_DURATION(buffer);
1831
1832         if ( player->is_subtitle_off )
1833         {
1834                 debug_log("subtitle is OFF.\n" );
1835                 return TRUE;
1836         }
1837
1838         if ( !text )
1839         {
1840                 debug_log("There is no subtitle to be displayed.\n" );
1841                 return TRUE;
1842         }
1843
1844         msg.data = (void *) text;
1845         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
1846
1847         debug_warning("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
1848
1849         MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
1850
1851         debug_fleave();
1852
1853         return ret;
1854 }
1855 #else
1856 gboolean
1857 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
1858 {
1859         mm_player_t* player = (mm_player_t*) data;
1860         MMMessageParamType msg = {0, };
1861         GstClockTime duration = 0;
1862         guint8 *text = NULL;
1863         gboolean ret = TRUE;
1864
1865         debug_fenter();
1866
1867         return_val_if_fail ( player, FALSE );
1868         return_val_if_fail ( buffer, FALSE );
1869
1870         text = GST_BUFFER_DATA(buffer);
1871         duration = GST_BUFFER_DURATION(buffer);
1872
1873         if ( player->is_subtitle_off )
1874         {
1875                 debug_log("subtitle is OFF.\n" );
1876                 return TRUE;
1877         }
1878
1879         if ( !text )
1880         {
1881                 debug_log("There is no subtitle to be displayed.\n" );
1882                 return TRUE;
1883         }
1884
1885         msg.data = (void *) text;
1886         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
1887
1888         debug_warning("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
1889
1890         MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
1891
1892         debug_fleave();
1893
1894         return ret;
1895 }
1896 #endif
1897
1898 #ifdef GST_API_VERSION_1
1899 int
1900 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
1901 {
1902         mm_player_t* player = (mm_player_t*)hplayer;
1903         GstBuffer *buffer = NULL;
1904         GstMapInfo info;
1905         GstFlowReturn gst_ret = GST_FLOW_OK;
1906         int ret = MM_ERROR_NONE;
1907
1908         debug_fenter();
1909
1910         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
1911
1912         /* check current state */
1913 //      MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
1914
1915
1916         /* NOTE : we should check and create pipeline again if not created as we destroy
1917          * whole pipeline when stopping in streamming playback
1918          */
1919         if ( ! player->pipeline )
1920         {
1921                 if ( MM_ERROR_NONE != __gst_realize( player ) )
1922                 {
1923                         debug_error("failed to realize before starting. only in streamming\n");
1924                         return MM_ERROR_PLAYER_INTERNAL;
1925                 }
1926         }
1927
1928         debug_msg("app-src: pushing data\n");
1929
1930         if ( buf == NULL )
1931         {
1932                 debug_error("buf is null\n");
1933                 return MM_ERROR_NONE;
1934         }
1935
1936         buffer = gst_buffer_new ();
1937
1938         if (size <= 0)
1939         {
1940                 debug_log("call eos appsrc\n");
1941                 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
1942                 return MM_ERROR_NONE;
1943         }
1944
1945         info.data = (guint8*)(buf);
1946         gst_buffer_set_size(buffer, size);
1947         gst_buffer_map (buffer, &info, GST_MAP_WRITE);
1948
1949         debug_log("feed buffer %p, length %u\n", buf, size);
1950         g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
1951
1952         debug_fleave();
1953
1954         return ret;
1955 }
1956 #else
1957 int
1958 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
1959 {
1960         mm_player_t* player = (mm_player_t*)hplayer;
1961         GstBuffer *buffer = NULL;
1962         GstFlowReturn gst_ret = GST_FLOW_OK;
1963         int ret = MM_ERROR_NONE;
1964
1965         debug_fenter();
1966
1967         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
1968
1969         /* check current state */
1970 //      MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
1971
1972
1973         /* NOTE : we should check and create pipeline again if not created as we destroy
1974          * whole pipeline when stopping in streamming playback
1975          */
1976         if ( ! player->pipeline )
1977         {
1978                 if ( MM_ERROR_NONE != __gst_realize( player ) )
1979                 {
1980                         debug_error("failed to realize before starting. only in streamming\n");
1981                         return MM_ERROR_PLAYER_INTERNAL;
1982                 }
1983         }
1984
1985         debug_msg("app-src: pushing data\n");
1986
1987         if ( buf == NULL )
1988         {
1989                 debug_error("buf is null\n");
1990                 return MM_ERROR_NONE;
1991         }
1992
1993         buffer = gst_buffer_new ();
1994
1995         if (size <= 0)
1996         {
1997                 debug_log("call eos appsrc\n");
1998                 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
1999                 return MM_ERROR_NONE;
2000         }
2001
2002         GST_BUFFER_DATA(buffer) = (guint8*)(buf);
2003         GST_BUFFER_SIZE(buffer) = size;
2004
2005         debug_log("feed buffer %p, length %u\n", buf, size);
2006         g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
2007
2008         debug_fleave();
2009
2010         return ret;
2011 }
2012 #endif
2013
2014 GstBusSyncReply
2015 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
2016 {
2017         mm_player_t *player = (mm_player_t *)data;
2018
2019         switch (GST_MESSAGE_TYPE (message))
2020         {
2021                 case GST_MESSAGE_TAG:
2022                         __mmplayer_gst_extract_tag_from_msg(player, message);
2023                         break;
2024                 case GST_MESSAGE_DURATION:
2025                         __mmplayer_gst_handle_duration(player, message);
2026                         break;
2027
2028                 default:
2029                         return GST_BUS_PASS;
2030         }
2031         gst_message_unref (message);
2032
2033         return GST_BUS_DROP;
2034 }
2035
2036 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
2037 {
2038         debug_fenter();
2039
2040         return_if_fail(player
2041                 && player->pipeline
2042                 && player->pipeline->audiobin
2043                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
2044
2045         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
2046
2047         usleep(time);
2048
2049         debug_fleave();
2050 }
2051
2052 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
2053 {
2054         debug_fenter();
2055
2056         return_if_fail(player
2057                 && player->pipeline
2058                 && player->pipeline->audiobin
2059                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
2060
2061         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
2062
2063         debug_fleave();
2064 }
2065
2066 static gboolean __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
2067 {
2068         gboolean ret = FALSE;
2069         char *path = NULL;
2070
2071         debug_fenter();
2072
2073         return_val_if_fail ( uri , FALSE);
2074         return_val_if_fail ( data , FALSE);
2075         return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
2076
2077         memset(data, 0, sizeof(MMPlayerParseProfile));
2078
2079         if ((path = strstr(uri, "file://")))
2080         {
2081                 if (util_exist_file_path(path + 7)) {
2082                         strncpy(data->uri, path, MM_MAX_URL_LEN-1);
2083
2084                         if ( util_is_sdp_file ( path ) )
2085                         {
2086                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
2087                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2088                         }
2089                         else
2090                         {
2091                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
2092                         }
2093                         ret = TRUE;
2094                 }
2095                 else
2096                 {
2097                         debug_warning("could  access %s.\n", path);
2098                 }
2099         }
2100         else if ((path = strstr(uri, "buff://")))
2101         {
2102                         data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
2103                         ret = TRUE;
2104         }
2105         else if ((path = strstr(uri, "rtsp://")))
2106         {
2107                 if (strlen(path)) {
2108                         strcpy(data->uri, uri);
2109                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2110                         ret = TRUE;
2111                 }
2112         }
2113         else if ((path = strstr(uri, "http://")))
2114         {
2115                 if (strlen(path)) {
2116                         strcpy(data->uri, uri);
2117                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
2118
2119                         ret = TRUE;
2120                 }
2121         }
2122         else if ((path = strstr(uri, "https://")))
2123         {
2124                 if (strlen(path)) {
2125                         strcpy(data->uri, uri);
2126                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
2127
2128                         ret = TRUE;
2129                 }
2130         }
2131         else if ((path = strstr(uri, "rtspu://")))
2132         {
2133                 if (strlen(path)) {
2134                         strcpy(data->uri, uri);
2135                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2136                         ret = TRUE;
2137                 }
2138         }
2139         else if ((path = strstr(uri, "rtspr://")))
2140         {
2141                 strcpy(data->uri, path);
2142                 char *separater =strstr(path, "*");
2143
2144                 if (separater) {
2145                         int urgent_len = 0;
2146                         char *urgent = separater + strlen("*");
2147
2148                         if ((urgent_len = strlen(urgent))) {
2149                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
2150                                 strcpy(data->urgent, urgent);
2151                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2152                                 ret = TRUE;
2153                         }
2154                 }
2155         }
2156         else if ((path = strstr(uri, "mms://")))
2157         {
2158                 if (strlen(path)) {
2159                         strcpy(data->uri, uri);
2160                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
2161                         ret = TRUE;
2162                 }
2163         }
2164         else if ((path = strstr(uri, "mem://")))
2165         {
2166                 if (strlen(path)) {
2167                         int mem_size = 0;
2168                         char *buffer = NULL;
2169                         char *seperator = strchr(path, ',');
2170                         char ext[100] = {0,}, size[100] = {0,};
2171
2172                         if (seperator) {
2173                                 if ((buffer = strstr(path, "ext="))) {
2174                                         buffer += strlen("ext=");
2175
2176                                         if (strlen(buffer)) {
2177                                                 strcpy(ext, buffer);
2178
2179                                                 if ((seperator = strchr(ext, ','))
2180                                                         || (seperator = strchr(ext, ' '))
2181                                                         || (seperator = strchr(ext, '\0'))) {
2182                                                         seperator[0] = '\0';
2183                                                 }
2184                                         }
2185                                 }
2186
2187                                 if ((buffer = strstr(path, "size="))) {
2188                                         buffer += strlen("size=");
2189
2190                                         if (strlen(buffer) > 0) {
2191                                                 strcpy(size, buffer);
2192
2193                                                 if ((seperator = strchr(size, ','))
2194                                                         || (seperator = strchr(size, ' '))
2195                                                         || (seperator = strchr(size, '\0'))) {
2196                                                         seperator[0] = '\0';
2197                                                 }
2198
2199                                                 mem_size = atoi(size);
2200                                         }
2201                                 }
2202                         }
2203
2204                         debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
2205                         if ( mem_size && param) {
2206                                 data->mem = param;
2207                                 data->mem_size = mem_size;
2208                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
2209                                 ret = TRUE;
2210                         }
2211                 }
2212         }
2213         else
2214         {
2215                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
2216                 if (util_exist_file_path(uri))
2217                 {
2218                         debug_warning("uri has no protocol-prefix. giving 'file://' by default.\n");
2219                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", uri);
2220
2221                         if ( util_is_sdp_file( (char*)uri ) )
2222                         {
2223                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
2224                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2225                         }
2226                         else
2227                         {
2228                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
2229                         }
2230                         ret = TRUE;
2231                 }
2232                 else
2233                 {
2234                         debug_error ("invalid uri, could not play..\n");
2235                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
2236                 }
2237         }
2238
2239         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
2240                 ret = FALSE;
2241         }
2242
2243         /* dump parse result */
2244         debug_log("profile parsing result ---\n");
2245         debug_warning("incomming uri : %s\n", uri);
2246         debug_log("uri : %s\n", data->uri);
2247         debug_log("uri_type : %d\n", data->uri_type);
2248         debug_log("play_mode : %d\n", data->play_mode);
2249         debug_log("mem : 0x%x\n", (guint)data->mem);
2250         debug_log("mem_size : %d\n", data->mem_size);
2251         debug_log("urgent : %s\n", data->urgent);
2252         debug_log("--------------------------\n");
2253
2254         debug_fleave();
2255
2256         return ret;
2257 }
2258
2259 gboolean _asm_postmsg(gpointer *data)
2260 {
2261         mm_player_t* player = (mm_player_t*)data;
2262         MMMessageParamType msg = {0, };
2263
2264         debug_fenter();
2265
2266         return_val_if_fail ( player, FALSE );
2267
2268         msg.union_type = MM_MSG_UNION_CODE;
2269         msg.code = player->sm.event_src;
2270
2271         MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
2272
2273         return FALSE;
2274 }
2275
2276 gboolean _asm_lazy_pause(gpointer *data)
2277 {
2278         mm_player_t* player = (mm_player_t*)data;
2279         int ret = MM_ERROR_NONE;
2280
2281         debug_fenter();
2282
2283         return_val_if_fail ( player, FALSE );
2284
2285         if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
2286         {
2287                 debug_log ("Ready to proceed lazy pause\n");
2288                 ret = _mmplayer_pause((MMHandleType)player);
2289                 if(MM_ERROR_NONE != ret)
2290                 {
2291                         debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
2292                 }
2293         }
2294         else
2295         {
2296                 debug_log ("Invalid state to proceed lazy pause\n");
2297         }
2298
2299         /* unset mute */
2300         if (player->pipeline && player->pipeline->audiobin)
2301                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
2302
2303         player->sm.by_asm_cb = 0; //should be reset here
2304
2305         debug_fleave();
2306
2307         return FALSE;
2308 }
2309
2310 ASM_cb_result_t
2311 __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
2312 {
2313         mm_player_t* player = (mm_player_t*) cb_data;
2314         ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
2315         int result = MM_ERROR_NONE;
2316         gboolean lazy_pause = FALSE;
2317
2318         debug_fenter();
2319
2320         return_val_if_fail ( player && player->pipeline, ASM_CB_RES_IGNORE );
2321         return_val_if_fail ( player->attrs, MM_ERROR_PLAYER_INTERNAL );
2322
2323         if (player->is_sound_extraction)
2324         {
2325                 debug_log("sound extraction is working...so, asm command is ignored.\n");
2326                 return result;
2327         }
2328
2329         player->sm.by_asm_cb = 1; // it should be enabled for player state transition with called application command
2330         player->sm.event_src = event_src;
2331
2332         if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG )
2333         {
2334                 int stop_by_asm = 0;
2335
2336                 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
2337                 if (!stop_by_asm)
2338                         return cb_res;
2339         }
2340         else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
2341         {
2342                 /* can use video overlay simultaneously */
2343                 /* video resource conflict */
2344                 if(player->pipeline->videobin)
2345                 {
2346                         if (PLAYER_INI()->multiple_codec_supported)
2347                         {
2348                                 debug_log("video conflict but, can support to use video overlay simultaneously");
2349                                 result = _mmplayer_pause((MMHandleType)player);
2350                                 cb_res = ASM_CB_RES_PAUSE;
2351                         }
2352                         else
2353                         {
2354                                 debug_log("video conflict, can't support for multiple codec instance");
2355                                 result = _mmplayer_unrealize((MMHandleType)player);
2356                                 cb_res = ASM_CB_RES_STOP;
2357                         }
2358                 }
2359                 return cb_res;
2360         }
2361
2362         switch(command)
2363         {
2364                 case ASM_COMMAND_PLAY:
2365                         debug_warning ("Got unexpected asm command (%d)", command);
2366                 break;
2367
2368                 case ASM_COMMAND_STOP: // notification case
2369                 {
2370                         debug_warning("Got msg from asm to stop");
2371
2372                         result = _mmplayer_stop((MMHandleType)player);
2373                         if (result != MM_ERROR_NONE)
2374                         {
2375                                 debug_warning("fail to set stop state by asm");
2376                                 cb_res = ASM_CB_RES_IGNORE;
2377                         }
2378                         else
2379                         {
2380                                 cb_res = ASM_CB_RES_STOP;
2381                         }
2382                         player->sm.by_asm_cb = 0; // reset because no message any more from asm
2383                 }
2384                 break;
2385
2386                 case ASM_COMMAND_PAUSE:
2387                 {
2388                         debug_warning("Got msg from asm to Pause");
2389
2390                         if(event_src == ASM_EVENT_SOURCE_CALL_START
2391                                 || event_src == ASM_EVENT_SOURCE_ALARM_START
2392                                 || event_src == ASM_EVENT_SOURCE_MEDIA)
2393                         {
2394                                 //hold 0.7 second to excute "fadedown mute" effect
2395                                 debug_warning ("do fade down->pause->undo fade down");
2396
2397                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
2398
2399                                 result = _mmplayer_pause((MMHandleType)player);
2400                                 if (result != MM_ERROR_NONE)
2401                                 {
2402                                         debug_warning("fail to set Pause state by asm");
2403                                         cb_res = ASM_CB_RES_IGNORE;
2404                                         break;
2405                                 }
2406                                 __mmplayer_undo_sound_fadedown(player);
2407                         }
2408                         else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
2409                         {
2410                                 lazy_pause = TRUE; // return as soon as possible, for fast start of other app
2411
2412                                 if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
2413                                         g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
2414
2415                                 player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
2416                                 debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
2417                         }
2418                         else
2419                         {
2420                                 //immediate pause
2421                                 debug_log ("immediate pause");
2422                                 result = _mmplayer_pause((MMHandleType)player);
2423                         }
2424                         cb_res = ASM_CB_RES_PAUSE;
2425                 }
2426                 break;
2427
2428                 case ASM_COMMAND_RESUME:
2429                 {
2430                         debug_warning("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
2431                         player->sm.by_asm_cb = 0;
2432                         //ASM server is single thread daemon. So use g_idle_add() to post resume msg
2433                         g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
2434                         cb_res = ASM_CB_RES_IGNORE;
2435                 }
2436                 break;
2437
2438                 default:
2439                 break;
2440         }
2441
2442         if (!lazy_pause)
2443                 player->sm.by_asm_cb = 0;
2444
2445         debug_fleave();
2446
2447         return cb_res;
2448 }
2449
2450 int
2451 _mmplayer_create_player(MMHandleType handle) // @
2452 {
2453         mm_player_t* player = MM_PLAYER_CAST(handle);
2454
2455         debug_fenter();
2456
2457         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2458
2459         MMTA_ACUM_ITEM_BEGIN("[KPI] media player service create->playing", FALSE);
2460
2461         /* initialize player state */
2462         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
2463         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
2464         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
2465         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
2466
2467         /* check current state */
2468         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
2469
2470         /* construct attributes */
2471         player->attrs = _mmplayer_construct_attribute(handle);
2472
2473         if ( !player->attrs )
2474         {
2475                 debug_critical("Failed to construct attributes\n");
2476                 goto ERROR;
2477         }
2478
2479         /* initialize gstreamer with configured parameter */
2480         if ( ! __mmplayer_gstreamer_init() )
2481         {
2482                 debug_critical("Initializing gstreamer failed\n");
2483                 goto ERROR;
2484         }
2485
2486         /* initialize factories if not using decodebin */
2487         if ( FALSE == PLAYER_INI()->use_decodebin )
2488         {
2489                 if( player->factories == NULL )
2490                     __mmplayer_init_factories(player);
2491         }
2492
2493         /* create lock. note that g_tread_init() has already called in gst_init() */
2494         player->fsink_lock = g_mutex_new();
2495         if ( ! player->fsink_lock )
2496         {
2497                 debug_critical("Cannot create mutex for command lock\n");
2498                 goto ERROR;
2499         }
2500
2501         /* create repeat mutex */
2502         player->repeat_thread_mutex = g_mutex_new();
2503         if ( ! player->repeat_thread_mutex )
2504         {
2505                 debug_critical("Cannot create repeat mutex\n");
2506                 goto ERROR;
2507         }
2508
2509         /* create repeat cond */
2510         player->repeat_thread_cond = g_cond_new();
2511         if ( ! player->repeat_thread_cond )
2512         {
2513                 debug_critical("Cannot create repeat cond\n");
2514                 goto ERROR;
2515         }
2516
2517         /* create repeat thread */
2518         player->repeat_thread =
2519                 g_thread_create (__mmplayer_repeat_thread, (gpointer)player, TRUE, NULL);
2520         if ( ! player->repeat_thread )
2521         {
2522                 goto ERROR;
2523         }
2524
2525         if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
2526         {
2527                 debug_error("failed to initialize video capture\n");
2528                 goto ERROR;
2529         }
2530
2531         /* register to asm */
2532         if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
2533         {
2534                 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
2535                 debug_error("failed to register asm server\n");
2536                 return MM_ERROR_POLICY_INTERNAL;
2537         }
2538
2539         if (MMPLAYER_IS_HTTP_PD(player))
2540         {
2541                 player->pd_downloader = NULL;
2542                 player->pd_file_save_path = NULL;
2543         }
2544
2545         /* give default value of audio effect setting */
2546         player->bypass_audio_effect = TRUE;
2547         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
2548         player->playback_rate = DEFAULT_PLAYBACK_RATE;
2549
2550         player->play_subtitle = FALSE;
2551         player->use_textoverlay = FALSE;
2552
2553         /* set player state to null */
2554         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout;
2555         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
2556
2557         debug_fleave();
2558
2559         return MM_ERROR_NONE;
2560
2561 ERROR:
2562         /* free lock */
2563         if ( player->fsink_lock )
2564                 g_mutex_free( player->fsink_lock );
2565         player->fsink_lock = NULL;
2566
2567         /* free thread */
2568         if ( player->repeat_thread_cond &&
2569                  player->repeat_thread_mutex &&
2570                  player->repeat_thread )
2571         {
2572                 player->repeat_thread_exit = TRUE;
2573                 g_cond_signal( player->repeat_thread_cond );
2574
2575                 g_thread_join( player->repeat_thread );
2576                 player->repeat_thread = NULL;
2577
2578                 g_mutex_free ( player->repeat_thread_mutex );
2579                 player->repeat_thread_mutex = NULL;
2580
2581                 g_cond_free ( player->repeat_thread_cond );
2582                 player->repeat_thread_cond = NULL;
2583         }
2584         /* clear repeat thread mutex/cond if still alive
2585          * this can happen if only thread creating has failed
2586          */
2587         if ( player->repeat_thread_mutex )
2588                 g_mutex_free ( player->repeat_thread_mutex );
2589
2590         if ( player->repeat_thread_cond )
2591                 g_cond_free ( player->repeat_thread_cond );
2592
2593         /* release attributes */
2594         _mmplayer_deconstruct_attribute(handle);
2595
2596         return MM_ERROR_PLAYER_INTERNAL;
2597 }
2598
2599 static gboolean
2600 __mmplayer_gstreamer_init(void) // @
2601 {
2602         static gboolean initialized = FALSE;
2603         static const int max_argc = 50;
2604         gint* argc = NULL;
2605         gchar** argv = NULL;
2606         GError *err = NULL;
2607         int i = 0;
2608
2609         debug_fenter();
2610
2611         if ( initialized )
2612         {
2613                 debug_log("gstreamer already initialized.\n");
2614                 return TRUE;
2615         }
2616
2617         /* alloc */
2618         argc = malloc( sizeof(int) );
2619         argv = malloc( sizeof(gchar*) * max_argc );
2620
2621         if ( !argc || !argv )
2622                 goto ERROR;
2623
2624         memset( argv, 0, sizeof(gchar*) * max_argc );
2625
2626         /* add initial */
2627         *argc = 1;
2628         argv[0] = g_strdup( "mmplayer" );
2629
2630         /* add gst_param */
2631         for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
2632         {
2633                 if ( strlen( PLAYER_INI()->gst_param[i] ) > 0 )
2634                 {
2635                         argv[*argc] = g_strdup( PLAYER_INI()->gst_param[i] );
2636                         (*argc)++;
2637                 }
2638         }
2639
2640         /* we would not do fork for scanning plugins */
2641         argv[*argc] = g_strdup("--gst-disable-registry-fork");
2642         (*argc)++;
2643
2644         /* check disable registry scan */
2645         if ( PLAYER_INI()->skip_rescan )
2646         {
2647                 argv[*argc] = g_strdup("--gst-disable-registry-update");
2648                 (*argc)++;
2649         }
2650
2651         /* check disable segtrap */
2652         if ( PLAYER_INI()->disable_segtrap )
2653         {
2654                 argv[*argc] = g_strdup("--gst-disable-segtrap");
2655                 (*argc)++;
2656         }
2657
2658         debug_log("initializing gstreamer with following parameter\n");
2659         debug_log("argc : %d\n", *argc);
2660
2661         for ( i = 0; i < *argc; i++ )
2662         {
2663                 debug_log("argv[%d] : %s\n", i, argv[i]);
2664         }
2665
2666
2667         /* initializing gstreamer */
2668         __ta__("gst_init time",
2669
2670                 if ( ! gst_init_check (argc, &argv, &err))
2671                 {
2672                         debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
2673                         if (err)
2674                         {
2675                                 g_error_free (err);
2676                         }
2677
2678                         goto ERROR;
2679                 }
2680         );
2681
2682         /* release */
2683         for ( i = 0; i < *argc; i++ )
2684         {
2685                 MMPLAYER_FREEIF( argv[i] );
2686         }
2687
2688         MMPLAYER_FREEIF( argv );
2689         MMPLAYER_FREEIF( argc );
2690
2691         /* done */
2692         initialized = TRUE;
2693
2694         debug_fleave();
2695
2696         return TRUE;
2697
2698 ERROR:
2699
2700         MMPLAYER_FREEIF( argv );
2701         MMPLAYER_FREEIF( argc );
2702
2703         return FALSE;
2704 }
2705
2706 int
2707 __mmplayer_destroy_streaming_ext(mm_player_t* player)
2708 {
2709         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2710
2711         if (player->pd_downloader)
2712                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
2713
2714         if (MMPLAYER_IS_HTTP_PD(player))
2715                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
2716
2717         if (MMPLAYER_IS_STREAMING(player))
2718         {
2719                 if (player->streamer)
2720                 {
2721                         __mm_player_streaming_deinitialize (player->streamer);
2722                         __mm_player_streaming_destroy(player->streamer);
2723                         player->streamer = NULL;
2724                 }
2725         }
2726         return MM_ERROR_NONE;
2727 }
2728
2729 int
2730 _mmplayer_destroy(MMHandleType handle) // @
2731 {
2732         mm_player_t* player = MM_PLAYER_CAST(handle);
2733
2734         debug_fenter();
2735
2736         /* check player handle */
2737         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2738
2739         /* destroy can called at anytime */
2740         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
2741
2742         __mmplayer_destroy_streaming_ext(player);
2743
2744         /* release repeat thread */
2745         if ( player->repeat_thread_cond &&
2746                  player->repeat_thread_mutex &&
2747                  player->repeat_thread )
2748         {
2749                 player->repeat_thread_exit = TRUE;
2750                 g_cond_signal( player->repeat_thread_cond );
2751
2752                 debug_log("waitting for repeat thread exit\n");
2753                 g_thread_join ( player->repeat_thread );
2754                 g_mutex_free ( player->repeat_thread_mutex );
2755                 g_cond_free ( player->repeat_thread_cond );
2756                 debug_log("repeat thread released\n");
2757         }
2758
2759         if (MM_ERROR_NONE != _mmplayer_release_video_capture(player))
2760         {
2761                 debug_error("failed to release video capture\n");
2762                 return MM_ERROR_PLAYER_INTERNAL;
2763         }
2764
2765         /* withdraw asm */
2766         if ( MM_ERROR_NONE != _mmplayer_asm_unregister(&player->sm) )
2767         {
2768                 debug_error("failed to deregister asm server\n");
2769                 return MM_ERROR_PLAYER_INTERNAL;
2770         }
2771
2772         /* release pipeline */
2773         if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
2774         {
2775                 debug_error("failed to destory pipeline\n");
2776                 return MM_ERROR_PLAYER_INTERNAL;
2777         }
2778
2779         /* release attributes */
2780         _mmplayer_deconstruct_attribute( handle );
2781
2782         /* release factories */
2783         __mmplayer_release_factories( player );
2784
2785         /* release lock */
2786         if ( player->fsink_lock )
2787                 g_mutex_free( player->fsink_lock );
2788
2789         if ( player->msg_cb_lock )
2790                 g_mutex_free( player->msg_cb_lock );
2791
2792         if (player->lazy_pause_event_id)
2793         {
2794                 g_source_remove (player->lazy_pause_event_id);
2795                 player->lazy_pause_event_id = 0;
2796         }
2797
2798         debug_fleave();
2799
2800         return MM_ERROR_NONE;
2801 }
2802
2803 int
2804 __mmplayer_realize_streaming_ext(mm_player_t* player)
2805 {
2806         int ret = MM_ERROR_NONE;
2807
2808         debug_fenter();
2809         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2810
2811         if (MMPLAYER_IS_HTTP_PD(player))
2812         {
2813                 gboolean bret = FALSE;
2814
2815                 player->pd_downloader = _mmplayer_create_pd_downloader();
2816                 if ( !player->pd_downloader )
2817                 {
2818                         debug_error ("Unable to create PD Downloader...");
2819                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
2820                 }
2821
2822                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
2823
2824                 if (FALSE == bret)
2825                 {
2826                         debug_error ("Unable to create PD Downloader...");
2827                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
2828                 }
2829         }
2830
2831         debug_fleave();
2832         return ret;
2833 }
2834
2835 int
2836 _mmplayer_realize(MMHandleType hplayer) // @
2837 {
2838         mm_player_t* player =  (mm_player_t*)hplayer;
2839         char *uri =NULL;
2840         void *param = NULL;
2841         int application_pid = -1;
2842         gboolean update_registry = FALSE;
2843         MMHandleType attrs = 0;
2844         int ret = MM_ERROR_NONE;
2845
2846         debug_fenter();
2847
2848         /* check player handle */
2849         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
2850
2851         /* check current state */
2852         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
2853
2854         attrs = MMPLAYER_GET_ATTRS(player);
2855         if ( !attrs )
2856         {
2857                 debug_error("fail to get attributes.\n");
2858                 return MM_ERROR_PLAYER_INTERNAL;
2859         }
2860
2861         mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
2862         player->sm.pid = application_pid;
2863
2864         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
2865         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
2866
2867         if (! __mmfplayer_parse_profile((const char*)uri, param, &player->profile) )
2868         {
2869                 debug_error("failed to parse profile\n");
2870                 return MM_ERROR_PLAYER_INVALID_URI;
2871         }
2872
2873         /* FIXIT : we can use thouse in player->profile directly */
2874         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
2875         {
2876                 player->mem_buf.buf = (char *)player->profile.mem;
2877                 player->mem_buf.len = player->profile.mem_size;
2878                 player->mem_buf.offset = 0;
2879         }
2880
2881         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
2882         {
2883                 debug_warning("mms protocol is not supported format.\n");
2884                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
2885         }
2886
2887         if (MMPLAYER_IS_STREAMING(player))
2888                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->live_state_change_timeout;
2889         else
2890                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout;
2891
2892         player->videodec_linked  = 0;
2893         player->videosink_linked = 0;
2894         player->audiodec_linked  = 0;
2895         player->audiosink_linked = 0;
2896         player->textsink_linked = 0;
2897
2898         /* set the subtitle ON default */
2899         player->is_subtitle_off = FALSE;
2900
2901         /* registry should be updated for downloadable codec */
2902         mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
2903
2904         if ( update_registry )
2905         {
2906                 debug_log("updating registry...\n");
2907                 gst_update_registry();
2908
2909                 /* then we have to rebuild factories */
2910                 __mmplayer_release_factories( player );
2911                 __mmplayer_init_factories(player);
2912         }
2913
2914         /* realize pipeline */
2915         ret = __gst_realize( player );
2916         if ( ret != MM_ERROR_NONE )
2917         {
2918                 debug_error("fail to realize the player.\n");
2919         }
2920         else
2921         {
2922                 ret = __mmplayer_realize_streaming_ext(player);
2923         }
2924
2925         debug_fleave();
2926
2927         return ret;
2928 }
2929
2930 int
2931 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
2932 {
2933         debug_fenter();
2934         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2935
2936         /* destroy can called at anytime */
2937         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
2938         {
2939                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
2940                 player->pd_downloader = NULL;
2941         }
2942
2943         debug_fleave();
2944         return MM_ERROR_NONE;
2945 }
2946
2947 int
2948 _mmplayer_unrealize(MMHandleType hplayer) // @
2949 {
2950         mm_player_t* player = (mm_player_t*)hplayer;
2951         int ret = MM_ERROR_NONE;
2952
2953         debug_fenter();
2954
2955         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
2956
2957         /* check current state */
2958         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
2959
2960         __mmplayer_unrealize_streaming_ext(player);
2961
2962         /* unrealize pipeline */
2963         ret = __gst_unrealize( player );
2964
2965         /* set player state if success */
2966         if ( MM_ERROR_NONE == ret )
2967         {
2968                 if (player->sm.state != ASM_STATE_STOP) {
2969                         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP);
2970                         if ( ret )
2971                         {
2972                                 debug_error("failed to set asm state to STOP\n");
2973                                 return ret;
2974                         }
2975                 }
2976         }
2977
2978         debug_fleave();
2979
2980         return ret;
2981 }
2982
2983 int
2984 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
2985 {
2986         mm_player_t* player = (mm_player_t*)hplayer;
2987
2988         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
2989
2990         return __gst_set_message_callback(player, callback, user_param);
2991 }
2992
2993 int
2994 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
2995 {
2996         mm_player_t *player = (mm_player_t*)hplayer;
2997
2998         return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
2999
3000         *state = MMPLAYER_CURRENT_STATE(player);
3001
3002         return MM_ERROR_NONE;
3003 }
3004
3005
3006 int
3007 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
3008 {
3009         mm_player_t* player = (mm_player_t*) hplayer;
3010         GstElement* vol_element = NULL;
3011         int i = 0;
3012
3013         debug_fenter();
3014
3015         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3016
3017         debug_log("volume [L]=%f:[R]=%f\n",
3018                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
3019
3020         /* invalid factor range or not */
3021         for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
3022         {
3023                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
3024                         debug_error("Invalid factor! (valid factor:0~1.0)\n");
3025                         return MM_ERROR_INVALID_ARGUMENT;
3026                 }
3027         }
3028
3029         /* Save volume to handle. Currently the first array element will be saved. */
3030         player->sound.volume = volume.level[0];
3031
3032         /* check pipeline handle */
3033         if ( ! player->pipeline || ! player->pipeline->audiobin )
3034         {
3035                 debug_log("audiobin is not created yet\n");
3036                 debug_log("but, current stored volume will be set when it's created.\n");
3037
3038                 /* NOTE : stored volume will be used in create_audiobin
3039                  * returning MM_ERROR_NONE here makes application to able to
3040                  * set volume at anytime.
3041                  */
3042                 return MM_ERROR_NONE;
3043         }
3044
3045         /* setting volume to volume element */
3046         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
3047
3048         if ( vol_element )
3049         {
3050                 debug_log("volume is set [%f]\n", player->sound.volume);
3051                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
3052         }
3053
3054         debug_fleave();
3055
3056         return MM_ERROR_NONE;
3057 }
3058
3059
3060 int
3061 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
3062 {
3063         mm_player_t* player = (mm_player_t*) hplayer;
3064         int i = 0;
3065
3066         debug_fenter();
3067
3068         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3069         return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
3070
3071         /* returning stored volume */
3072         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
3073                 volume->level[i] = player->sound.volume;
3074
3075         debug_fleave();
3076
3077         return MM_ERROR_NONE;
3078 }
3079
3080
3081
3082 int
3083 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
3084 {
3085         mm_player_t* player = (mm_player_t*) hplayer;
3086         GstElement* vol_element = NULL;
3087
3088         debug_fenter();
3089
3090         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3091
3092         debug_log("mute : %d\n", mute);
3093
3094         /* mute value shoud 0 or 1 */
3095         if ( mute != 0 && mute != 1 )
3096         {
3097                 debug_error("bad mute value\n");
3098
3099                 /* FIXIT : definitly, we need _BAD_PARAM error code */
3100                 return MM_ERROR_INVALID_ARGUMENT;
3101         }
3102
3103
3104         /* just hold mute value if pipeline is not ready */
3105         if ( !player->pipeline || !player->pipeline->audiobin )
3106         {
3107                 debug_log("pipeline is not ready. holding mute value\n");
3108                 player->sound.mute = mute;
3109                 return MM_ERROR_NONE;
3110         }
3111
3112
3113         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
3114
3115         /* NOTE : volume will only created when the bt is enabled */
3116         if ( vol_element )
3117         {
3118                 g_object_set(vol_element, "mute", mute, NULL);
3119         }
3120         else
3121         {
3122                 debug_log("volume elemnet is not created. using volume in audiosink\n");
3123         }
3124
3125         player->sound.mute = mute;
3126
3127         debug_fleave();
3128
3129         return MM_ERROR_NONE;
3130 }
3131
3132 int
3133 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
3134 {
3135         mm_player_t* player = (mm_player_t*) hplayer;
3136         GstElement* vol_element = NULL;
3137
3138         debug_fenter();
3139
3140         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3141         return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
3142
3143         /* just hold mute value if pipeline is not ready */
3144         if ( !player->pipeline || !player->pipeline->audiobin )
3145         {
3146                 debug_log("pipeline is not ready. returning stored value\n");
3147                 *pmute = player->sound.mute;
3148                 return MM_ERROR_NONE;
3149         }
3150
3151
3152         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
3153
3154         if ( vol_element )
3155         {
3156                 g_object_get(vol_element, "mute", pmute, NULL);
3157                 debug_log("mute=%d\n\n", *pmute);
3158         }
3159         else
3160         {
3161                 *pmute = player->sound.mute;
3162         }
3163
3164         debug_fleave();
3165
3166         return MM_ERROR_NONE;
3167 }
3168
3169 int
3170 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
3171 {
3172         mm_player_t* player = (mm_player_t*) hplayer;
3173
3174         debug_fenter();
3175
3176         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3177         return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
3178
3179         player->video_stream_cb = callback;
3180         player->video_stream_cb_user_param = user_param;
3181         player->use_video_stream = TRUE;
3182         debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
3183
3184         debug_fleave();
3185
3186         return MM_ERROR_NONE;
3187 }
3188
3189 int
3190 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
3191 {
3192         mm_player_t* player = (mm_player_t*) hplayer;
3193
3194         debug_fenter();
3195
3196         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3197         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3198
3199         player->audio_stream_cb = callback;
3200         player->audio_stream_cb_user_param = user_param;
3201         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
3202
3203         debug_fleave();
3204
3205         return MM_ERROR_NONE;
3206 }
3207
3208 int
3209 _mmplayer_set_audiobuffer_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
3210 {
3211         mm_player_t* player = (mm_player_t*) hplayer;
3212
3213         debug_fenter();
3214
3215         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3216         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3217
3218         player->audio_buffer_cb = callback;
3219         player->audio_buffer_cb_user_param = user_param;
3220         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_buffer_cb);
3221
3222         debug_fleave();
3223
3224         return MM_ERROR_NONE;
3225 }
3226
3227 int
3228 _mmplayer_set_buffer_need_data_cb(MMHandleType hplayer, mm_player_buffer_need_data_callback callback, void *user_param) // @
3229 {
3230         mm_player_t* player = (mm_player_t*) hplayer;
3231
3232         debug_fenter();
3233
3234         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3235         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3236
3237         player->need_data_cb = callback;
3238         player->buffer_cb_user_param = user_param;
3239
3240         debug_log("buffer need dataHandle value is %p : %p\n", player, player->need_data_cb);
3241
3242         debug_fleave();
3243
3244         return MM_ERROR_NONE;
3245 }
3246
3247 int
3248 _mmplayer_set_buffer_enough_data_cb(MMHandleType hplayer, mm_player_buffer_enough_data_callback callback, void *user_param) // @
3249 {
3250         mm_player_t* player = (mm_player_t*) hplayer;
3251
3252         debug_fenter();
3253
3254         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3255         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3256
3257         player->enough_data_cb = callback;
3258         player->buffer_cb_user_param = user_param;
3259
3260         debug_log("buffer enough data cb Handle value is %p : %p\n", player, player->enough_data_cb);
3261
3262         debug_fleave();
3263
3264         return MM_ERROR_NONE;
3265 }
3266
3267 int
3268 _mmplayer_set_buffer_seek_data_cb(MMHandleType hplayer, mm_player_buffer_seek_data_callback callback, void *user_param) // @
3269 {
3270         mm_player_t* player = (mm_player_t*) hplayer;
3271
3272         debug_fenter();
3273
3274         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3275         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3276
3277         player->seek_data_cb = callback;
3278         player->buffer_cb_user_param = user_param;
3279
3280         debug_log("buffer seek data cb Handle value is %p : %p\n", player, player->seek_data_cb);
3281
3282         debug_fleave();
3283
3284         return MM_ERROR_NONE;
3285 }
3286
3287 int
3288 _mmplayer_set_videoframe_render_error_cb(MMHandleType hplayer, mm_player_video_frame_render_error_callback callback, void *user_param) // @
3289 {
3290         mm_player_t* player = (mm_player_t*) hplayer;
3291
3292         debug_fenter();
3293
3294         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3295         return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
3296
3297         player->video_frame_render_error_cb = callback;
3298         player->video_frame_render_error_cb_user_param = user_param;
3299
3300         debug_log("Video frame render error cb Handle value is %p : %p\n", player, player->video_frame_render_error_cb);
3301
3302         debug_fleave();
3303
3304         return MM_ERROR_NONE;
3305 }
3306
3307 int
3308 __mmplayer_start_streaming_ext(mm_player_t *player)
3309 {
3310         gint ret = MM_ERROR_NONE;
3311
3312         debug_fenter();
3313         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3314
3315         if (MMPLAYER_IS_HTTP_PD(player))
3316         {
3317                 if ( !player->pd_downloader )
3318                 {
3319                         ret = __mmplayer_realize_streaming_ext(player);
3320
3321                         if ( ret != MM_ERROR_NONE)
3322                         {
3323                                 debug_error ("failed to realize streaming ext\n");
3324                                 return ret;
3325                         }
3326                 }
3327
3328                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
3329                 {
3330                         ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
3331                         if ( !ret )
3332                         {
3333                                 debug_error ("ERROR while starting PD...\n");
3334                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
3335                         }
3336                         ret = MM_ERROR_NONE;
3337                 }
3338         }
3339
3340         debug_fleave();
3341         return ret;
3342 }
3343
3344 int
3345 _mmplayer_start(MMHandleType hplayer) // @
3346 {
3347         mm_player_t* player = (mm_player_t*) hplayer;
3348         gint ret = MM_ERROR_NONE;
3349
3350         debug_fenter();
3351
3352         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3353
3354         /* check current state */
3355         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
3356
3357         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING);
3358         if ( ret != MM_ERROR_NONE )
3359         {
3360                 debug_error("failed to set asm state to PLAYING\n");
3361                 return ret;
3362         }
3363
3364         /* NOTE : we should check and create pipeline again if not created as we destroy
3365          * whole pipeline when stopping in streamming playback
3366          */
3367         if ( ! player->pipeline )
3368         {
3369                 ret = __gst_realize( player );
3370                 if ( MM_ERROR_NONE != ret )
3371                 {
3372                         debug_error("failed to realize before starting. only in streamming\n");
3373                         return ret;
3374                 }
3375         }
3376
3377         ret = __mmplayer_start_streaming_ext(player);
3378         if ( ret != MM_ERROR_NONE )
3379         {
3380                 debug_error("failed to start streaming ext \n");
3381         }
3382
3383         /* start pipeline */
3384         ret = __gst_start( player );
3385         if ( ret != MM_ERROR_NONE )
3386         {
3387                 debug_error("failed to start player.\n");
3388         }
3389
3390         debug_fleave();
3391
3392         return ret;
3393 }
3394
3395 /* NOTE : it should be able to call 'stop' anytime*/
3396 int
3397 _mmplayer_stop(MMHandleType hplayer) // @
3398 {
3399         mm_player_t* player = (mm_player_t*)hplayer;
3400         int ret = MM_ERROR_NONE;
3401
3402         debug_fenter();
3403
3404         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3405
3406         /* check current state */
3407         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
3408
3409         /* NOTE : application should not wait for EOS after calling STOP */
3410         __mmplayer_cancel_delayed_eos( player );
3411
3412         __mmplayer_unrealize_streaming_ext(player);
3413
3414         /* stop pipeline */
3415         ret = __gst_stop( player );
3416
3417         if ( ret != MM_ERROR_NONE )
3418         {
3419                 debug_error("failed to stop player.\n");
3420         }
3421
3422         debug_fleave();
3423
3424         return ret;
3425 }
3426
3427 int
3428 _mmplayer_pause(MMHandleType hplayer) // @
3429 {
3430         mm_player_t* player = (mm_player_t*)hplayer;
3431 #ifndef GST_API_VERSION_1
3432         GstFormat fmt = GST_FORMAT_TIME;
3433 #endif
3434         gint64 pos_msec = 0;
3435         gboolean async = FALSE;
3436         gint ret = MM_ERROR_NONE;
3437
3438         debug_fenter();
3439
3440         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3441
3442         /* check current state */
3443         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
3444
3445         switch (MMPLAYER_CURRENT_STATE(player))
3446         {
3447                 case MM_PLAYER_STATE_READY:
3448                 {
3449                         /* check prepare async or not.
3450                          * In the case of streaming playback, it's recommned to avoid blocking wait.
3451                          */
3452                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
3453                         debug_log("prepare mode : %s", (async ? "async" : "sync"));
3454                 }
3455                 break;
3456
3457                 case MM_PLAYER_STATE_PLAYING:
3458                 {
3459                         /* NOTE : store current point to overcome some bad operation
3460                         * ( returning zero when getting current position in paused state) of some
3461                         * elements
3462                         */
3463 #ifdef GST_API_VERSION_1
3464                         ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
3465 #else
3466                         ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &pos_msec);
3467 #endif
3468                         if ( ! ret )
3469                         debug_warning("getting current position failed in paused\n");
3470
3471                         player->last_position = pos_msec;
3472                 }
3473                 break;
3474         }
3475
3476         /* pause pipeline */
3477         ret = __gst_pause( player, async );
3478
3479         if ( ret != MM_ERROR_NONE )
3480         {
3481                 debug_error("failed to pause player. ret : 0x%x\n", ret);
3482         }
3483
3484         debug_fleave();
3485
3486         return ret;
3487 }
3488
3489 int
3490 _mmplayer_resume(MMHandleType hplayer)
3491 {
3492         mm_player_t* player = (mm_player_t*)hplayer;
3493         int ret = MM_ERROR_NONE;
3494         gboolean async = FALSE;
3495
3496         debug_fenter();
3497
3498         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3499
3500         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING);
3501         if ( ret )
3502         {
3503                 debug_error("failed to set asm state to PLAYING\n");
3504                 return ret;
3505         }
3506
3507         /* check current state */
3508         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
3509
3510         /* resume pipeline */
3511         ret = __gst_resume( player, FALSE );
3512
3513         if ( ret != MM_ERROR_NONE )
3514         {
3515                 debug_error("failed to resume player.\n");
3516         }
3517
3518
3519         debug_fleave();
3520
3521         return ret;
3522 }
3523
3524 int
3525 __mmplayer_set_play_count(mm_player_t* player, gint count)
3526 {
3527         MMHandleType attrs = 0;
3528
3529         debug_fenter();
3530
3531         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3532
3533         attrs =  MMPLAYER_GET_ATTRS(player);
3534         if ( !attrs )
3535         {
3536                 debug_error("fail to get attributes.\n");
3537                 return MM_ERROR_PLAYER_INTERNAL;
3538         }
3539
3540         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
3541         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
3542                 debug_error("failed to commit\n");
3543
3544         debug_fleave();
3545
3546         return  MM_ERROR_NONE;
3547 }
3548
3549 int
3550 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
3551 {
3552         mm_player_t* player = (mm_player_t*)hplayer;
3553         gint64 start_pos = 0;
3554         gint64 end_pos = 0;
3555         gint infinity = -1;
3556
3557         debug_fenter();
3558
3559         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3560         return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
3561
3562         player->section_repeat = TRUE;
3563         player->section_repeat_start = start;
3564         player->section_repeat_end = end;
3565
3566         start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
3567         end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
3568
3569         __mmplayer_set_play_count( player, infinity );
3570
3571         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3572                                         player->playback_rate,
3573                                         GST_FORMAT_TIME,
3574                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3575                                         GST_SEEK_TYPE_SET, start_pos,
3576                                         GST_SEEK_TYPE_SET, end_pos)))
3577         {
3578                 debug_error("failed to activate section repeat\n");
3579
3580                 return MM_ERROR_PLAYER_SEEK;
3581         }
3582
3583         debug_log("succeeded to set section repeat from %d to %d\n",
3584                 player->section_repeat_start, player->section_repeat_end);
3585
3586         debug_fleave();
3587
3588         return  MM_ERROR_NONE;
3589 }
3590
3591 static int
3592 __mmplayer_set_pcm_extraction(mm_player_t* player)
3593 {
3594         guint64 start_nsec = 0;
3595         guint64 end_nsec = 0;
3596         guint64 dur_nsec = 0;
3597         guint64 dur_msec = 0;
3598 #ifndef GST_API_VERSION_1
3599         GstFormat fmt = GST_FORMAT_TIME;
3600 #endif
3601         int required_start = 0;
3602         int required_end = 0;
3603         int ret = 0;
3604
3605         debug_fenter();
3606
3607         return_val_if_fail( player, FALSE );
3608
3609         mm_attrs_multiple_get(player->attrs,
3610                 NULL,
3611                 "pcm_extraction_start_msec", &required_start,
3612                 "pcm_extraction_end_msec", &required_end,
3613                 NULL);
3614
3615         debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
3616
3617         if (required_start == 0 && required_end == 0)
3618         {
3619                 debug_log("extracting entire stream");
3620                 return MM_ERROR_NONE;
3621         }
3622         else if (required_start < 0 || required_start > required_end || required_end < 0 )
3623         {
3624                 debug_log("invalid range for pcm extraction");
3625                 return MM_ERROR_INVALID_ARGUMENT;
3626         }
3627
3628         /* get duration */
3629 #ifdef GST_API_VERSION_1
3630         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
3631 #else
3632         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec);
3633 #endif
3634         if ( !ret )
3635         {
3636                 debug_error("failed to get duration");
3637                 return MM_ERROR_PLAYER_INTERNAL;
3638         }
3639         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
3640
3641         if (dur_msec < required_end) // FIXME
3642         {
3643                 debug_log("invalid end pos for pcm extraction");
3644                 return MM_ERROR_INVALID_ARGUMENT;
3645         }
3646
3647         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
3648         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
3649
3650         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3651                                         1.0,
3652                                         GST_FORMAT_TIME,
3653                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3654                                         GST_SEEK_TYPE_SET, start_nsec,
3655                                         GST_SEEK_TYPE_SET, end_nsec)))
3656         {
3657                 debug_error("failed to seek for pcm extraction\n");
3658
3659                 return MM_ERROR_PLAYER_SEEK;
3660         }
3661
3662         debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
3663
3664         debug_fleave();
3665
3666         return MM_ERROR_NONE;
3667 }
3668
3669 int
3670 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
3671 {
3672         mm_player_t* player = (mm_player_t*)hplayer;
3673         gint64 cur_pos = 0;
3674 #ifndef GST_API_VERSION_1
3675         GstFormat fmt  = GST_FORMAT_TIME;
3676 #endif
3677         gint onetime = 1;
3678
3679         debug_fenter();
3680
3681         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3682
3683         player->section_repeat = FALSE;
3684
3685         __mmplayer_set_play_count( player, onetime );
3686 #ifdef GST_API_VERSION_1
3687         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_pos);
3688 #else
3689         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &cur_pos);
3690 #endif
3691
3692         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3693                                         1.0,
3694                                         GST_FORMAT_TIME,
3695                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3696                                         GST_SEEK_TYPE_SET, cur_pos,
3697                                         GST_SEEK_TYPE_SET, player->duration )))
3698         {
3699                 debug_error("failed to deactivate section repeat\n");
3700
3701                 return MM_ERROR_PLAYER_SEEK;
3702         }
3703
3704         debug_fenter();
3705
3706         return MM_ERROR_NONE;
3707 }
3708
3709 int
3710 _mmplayer_set_playspeed(MMHandleType hplayer, gdouble rate)
3711 {
3712         mm_player_t* player = (mm_player_t*)hplayer;
3713         signed long long pos_msec = 0;
3714         int ret = MM_ERROR_NONE;
3715         int mute = FALSE;
3716 #ifndef GST_API_VERSION_1
3717         GstFormat format =GST_FORMAT_TIME;
3718 #endif
3719         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
3720         debug_fenter();
3721
3722         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3723         return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
3724
3725         /* The sound of video is not supported under 0.0 and over 2.0. */
3726         if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
3727         {
3728                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
3729                         mute = TRUE;
3730         }
3731         _mmplayer_set_mute(hplayer, mute);
3732
3733         if (player->playback_rate == rate)
3734                 return MM_ERROR_NONE;
3735
3736         /* If the position is reached at start potion during fast backward, EOS is posted.
3737          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
3738          * */
3739         player->playback_rate = rate;
3740
3741         current_state = MMPLAYER_CURRENT_STATE(player);
3742 #ifdef GST_API_VERSION_1
3743         if ( current_state != MM_PLAYER_STATE_PAUSED )
3744                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
3745 #else
3746         if ( current_state != MM_PLAYER_STATE_PAUSED )
3747                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &pos_msec);
3748 #endif
3749
3750         debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
3751
3752         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
3753                 || ( ! ret ))
3754                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
3755         {
3756                 debug_warning("returning last point : %lld\n", player->last_position );
3757                 pos_msec = player->last_position;
3758         }
3759
3760         if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3761                                 rate,
3762                                 GST_FORMAT_TIME,
3763                                 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3764                                 //( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT),
3765                                 GST_SEEK_TYPE_SET, pos_msec,
3766                                 //GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
3767                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)))
3768         {
3769                 debug_error("failed to set speed playback\n");
3770                 return MM_ERROR_PLAYER_SEEK;
3771         }
3772
3773         debug_log("succeeded to set speed playback as %fl\n", rate);
3774
3775         debug_fleave();
3776
3777         return MM_ERROR_NONE;;
3778 }
3779
3780 int
3781 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
3782 {
3783         mm_player_t* player = (mm_player_t*)hplayer;
3784         int ret = MM_ERROR_NONE;
3785
3786         debug_fenter();
3787
3788         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3789
3790         ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
3791
3792         debug_fleave();
3793
3794         return ret;
3795 }
3796
3797 int
3798 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
3799 {
3800         mm_player_t* player = (mm_player_t*)hplayer;
3801         int ret = MM_ERROR_NONE;
3802
3803         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3804
3805         ret = __gst_get_position ( player, format, position );
3806
3807         return ret;
3808 }
3809
3810 int
3811 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
3812 {
3813         mm_player_t* player = (mm_player_t*)hplayer;
3814         int ret = MM_ERROR_NONE;
3815
3816         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3817
3818         ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
3819
3820         return ret;
3821 }
3822
3823 int
3824 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
3825 {
3826         mm_player_t* player = (mm_player_t*)hplayer;
3827         int ret = MM_ERROR_NONE;
3828
3829         debug_fenter();
3830
3831         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3832
3833         ret = __gst_adjust_subtitle_position(player, format, position);
3834
3835         debug_fleave();
3836
3837         return ret;
3838 }
3839
3840 static gboolean
3841 __mmplayer_is_midi_type( gchar* str_caps)
3842 {
3843         if ( ( g_strrstr(str_caps, "audio/midi") ) ||
3844                 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
3845                 ( g_strrstr(str_caps, "application/x-smaf") ) ||
3846                 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
3847                 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
3848                 ( g_strrstr(str_caps, "audio/xmf") ) ||
3849                 ( g_strrstr(str_caps, "audio/mxmf") ) )
3850         {
3851                 debug_log("midi\n");
3852
3853                 return TRUE;
3854         }
3855
3856         return FALSE;
3857 }
3858
3859 static gboolean
3860 __mmplayer_is_amr_type (gchar *str_caps)
3861 {
3862         if ((g_strrstr(str_caps, "AMR")) ||
3863                 (g_strrstr(str_caps, "amr")))
3864         {
3865                 return TRUE;
3866         }
3867         return FALSE;
3868 }
3869
3870 static gboolean
3871 __mmplayer_is_only_mp3_type (gchar *str_caps)
3872 {
3873         if (g_strrstr(str_caps, "application/x-id3") ||
3874                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
3875         {
3876                 return TRUE;
3877         }
3878         return FALSE;
3879 }
3880
3881 void
3882 __mmplayer_typefind_have_type(  GstElement *tf, guint probability,  // @
3883 GstCaps *caps, gpointer data)
3884 {
3885         mm_player_t* player = (mm_player_t*)data;
3886         GstPad* pad = NULL;
3887
3888         debug_fenter();
3889
3890         return_if_fail( player && tf && caps );
3891
3892         /* store type string */
3893         MMPLAYER_FREEIF(player->type);
3894         player->type = gst_caps_to_string(caps);
3895         if (player->type)
3896                 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
3897
3898         /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
3899         if ( __mmplayer_is_midi_type(player->type))
3900         {
3901                 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
3902         }
3903         else if (__mmplayer_is_amr_type(player->type))
3904         {
3905                 player->bypass_audio_effect = FALSE;
3906                 if ( (PLAYER_INI()->use_audio_effect_preset || PLAYER_INI()->use_audio_effect_custom) )
3907                 {
3908                         if ( player->audio_effect_info.effect_type == MM_AUDIO_EFFECT_TYPE_PRESET )
3909                         {
3910                                 if (!_mmplayer_audio_effect_preset_apply(player, player->audio_effect_info.preset))
3911                                 {
3912                                         debug_msg("apply audio effect(preset:%d) setting success\n",player->audio_effect_info.preset);
3913                                 }
3914                         }
3915                         else if ( player->audio_effect_info.effect_type == MM_AUDIO_EFFECT_TYPE_CUSTOM )
3916                         {
3917                                 if (!_mmplayer_audio_effect_custom_apply(player))
3918                                 {
3919                                         debug_msg("apply audio effect(custom) setting success\n");
3920                                 }
3921                         }
3922                 }
3923         }
3924         else if ( g_strrstr(player->type, "application/x-hls"))
3925         {
3926                 /* If it can't know exact type when it parses uri because of redirection case,
3927                   * it will be fixed by typefinder here.
3928                   */
3929                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
3930         }
3931
3932         pad = gst_element_get_static_pad(tf, "src");
3933         if ( !pad )
3934         {
3935                 debug_error("fail to get typefind src pad.\n");
3936                 return;
3937         }
3938
3939         /* try to plug */
3940         if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
3941         {
3942                 gboolean async = FALSE;
3943
3944                 debug_error("failed to autoplug %s\n", player->type);
3945                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
3946
3947                 if ( async && player->msg_posted == FALSE )
3948                 {
3949                         __mmplayer_handle_missed_plugin( player );
3950                 }
3951
3952                 goto DONE;
3953         }
3954
3955         /* finish autopluging if no dynamic pad waiting */
3956         if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
3957         {
3958                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
3959                 {
3960                         __mmplayer_pipeline_complete( NULL, (gpointer)player );
3961                 }
3962         }
3963
3964 DONE:
3965         gst_object_unref( GST_OBJECT(pad) );
3966
3967         debug_fleave();
3968
3969         return;
3970 }
3971
3972 static gboolean
3973 __mmplayer_warm_up_video_codec( mm_player_t* player,  GstElementFactory *factory)
3974 {
3975         GstElement *element;
3976         GstStateChangeReturn  ret;
3977         gboolean usable = TRUE;
3978
3979         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3980         return_val_if_fail ( factory, MM_ERROR_COMMON_INVALID_ARGUMENT );
3981
3982         element = gst_element_factory_create (factory, NULL);
3983
3984         ret = gst_element_set_state (element, GST_STATE_READY);
3985
3986         if (ret != GST_STATE_CHANGE_SUCCESS)
3987         {
3988 #ifdef GST_API_VERSION_1
3989                 debug_error ("resource conflict so,  %s unusable\n", gst_object_get_name (GST_OBJECT (factory)));
3990 #else
3991                 debug_error ("resource conflict so,  %s unusable\n", GST_PLUGIN_FEATURE_NAME (factory));
3992 #endif
3993                 usable = FALSE;
3994         }
3995
3996         gst_element_set_state (element, GST_STATE_NULL);
3997         gst_object_unref (element);
3998
3999         return usable;
4000 }
4001
4002 /* it will return first created element */
4003 static gboolean
4004 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
4005 {
4006         MMPlayerGstElement* mainbin = NULL;
4007         const char* mime = NULL;
4008         const GList* item = NULL;
4009         const gchar* klass = NULL;
4010         GstCaps* res = NULL;
4011         gboolean skip = FALSE;
4012         GstPad* queue_pad = NULL;
4013         GstElement* queue = NULL;
4014         GstElement *element = NULL;
4015
4016         debug_fenter();
4017
4018         return_val_if_fail( player && player->pipeline && player->pipeline->mainbin, FALSE );
4019
4020         mainbin = player->pipeline->mainbin;
4021
4022         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
4023
4024         /* return if we got raw output */
4025         if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
4026                 || g_str_has_prefix(mime, "video/x-surface")
4027                 || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup"))
4028         {
4029
4030                 element = (GstElement*)gst_pad_get_parent(pad);
4031 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
4032  * No queue will be added. I think it can caused breaking sound when playing raw audio
4033  * frames but there's no different. Decodebin also doesn't add with those wav fils.
4034  * Anyway, currentely raw-queue seems not necessary.
4035  */
4036 #if 1
4037                 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
4038                  * has linked. if so, we need to add queue for quality of output. note that
4039                  * decodebin also has same problem.
4040                  */
4041                 klass = gst_element_factory_get_klass( gst_element_get_factory(element) );
4042
4043                 /* add queue if needed */
4044                 if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
4045                         || g_strrstr(klass, "Parse")) &&  !g_str_has_prefix(mime, "text"))
4046                 {
4047                         debug_log("adding raw queue\n");
4048
4049                         queue = gst_element_factory_make("queue", NULL);
4050                         if ( ! queue )
4051                         {
4052                                 debug_warning("failed to create queue\n");
4053                                 goto ERROR;
4054                         }
4055
4056                         /* warmup */
4057                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
4058                         {
4059                                 debug_warning("failed to set state READY to queue\n");
4060                                 goto ERROR;
4061                         }
4062
4063                         /* add to pipeline */
4064                         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
4065                         {
4066                                 debug_warning("failed to add queue\n");
4067                                 goto ERROR;
4068                         }
4069
4070                         /* link queue */
4071                         queue_pad = gst_element_get_static_pad(queue, "sink");
4072
4073                         if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
4074                         {
4075                                 debug_warning("failed to link queue\n");
4076                                 goto ERROR;
4077                         }
4078                         gst_object_unref ( GST_OBJECT(queue_pad) );
4079                         queue_pad = NULL;
4080
4081                         /* running */
4082                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
4083                         {
4084                                 debug_warning("failed to set state READY to queue\n");
4085                                 goto ERROR;
4086                         }
4087
4088                         /* replace given pad to queue:src */
4089                         pad = gst_element_get_static_pad(queue, "src");
4090                         if ( ! pad )
4091                         {
4092                                 debug_warning("failed to get pad from queue\n");
4093                                 goto ERROR;
4094                         }
4095                 }
4096 #endif
4097                 /* check if player can do start continually */
4098                 MMPLAYER_CHECK_CMD_IF_EXIT(player);
4099
4100                 if(__mmplayer_link_sink(player,pad))
4101                         __mmplayer_gst_decode_callback(element, pad, FALSE, player);
4102
4103                 gst_object_unref( GST_OBJECT(element));
4104                 element = NULL;
4105
4106                 return TRUE;
4107         }
4108
4109         item = player->factories;
4110         for(; item != NULL ; item = item->next)
4111         {
4112                 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
4113                 const GList *pads;
4114                 gint idx = 0;
4115
4116                 skip = FALSE;
4117
4118                 /* filtering exclude keyword */
4119 #ifdef GST_API_VERSION_1
4120                 for ( idx = 0; PLAYER_INI()->exclude_element_keyword[idx][0] != '\0'; idx++ )
4121                 {
4122                         if ( g_strrstr(gst_object_get_name (GST_OBJECT (factory)),
4123                                         PLAYER_INI()->exclude_element_keyword[idx]) )
4124                         {
4125                                 debug_warning("skipping [%s] by exculde keyword [%s]\n",
4126                                         gst_object_get_name (GST_OBJECT (factory)),
4127                                         PLAYER_INI()->exclude_element_keyword[idx] );
4128
4129                                 skip = TRUE;
4130                                 break;
4131                         }
4132                 }
4133 #else
4134                 for ( idx = 0; PLAYER_INI()->exclude_element_keyword[idx][0] != '\0'; idx++ )
4135                 {
4136                         if ( g_strrstr(GST_PLUGIN_FEATURE_NAME (factory),
4137                                         PLAYER_INI()->exclude_element_keyword[idx] ) )
4138                         {
4139                                 debug_warning("skipping [%s] by exculde keyword [%s]\n",
4140                                         GST_PLUGIN_FEATURE_NAME (factory),
4141                                         PLAYER_INI()->exclude_element_keyword[idx] );
4142
4143                                 skip = TRUE;
4144                                 break;
4145                         }
4146                 }
4147 #endif
4148
4149                 if ( skip ) continue;
4150
4151                 /* check factory class for filtering */
4152                 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory));
4153
4154                 /* NOTE : msl don't need to use image plugins.
4155                  * So, those plugins should be skipped for error handling.
4156                  */
4157                 if ( g_strrstr(klass, "Codec/Decoder/Image") )
4158                 {
4159 #ifdef GST_API_VERSION_1
4160                         debug_log("skipping [%s] by not required\n",
4161                                 gst_object_get_name (GST_OBJECT (factory)) );
4162 #else
4163                         debug_log("skipping [%s] by not required\n",
4164                                 GST_PLUGIN_FEATURE_NAME (factory) );
4165 #endif
4166                         continue;
4167                 }
4168
4169                 /* check pad compatability */
4170                 for(pads = gst_element_factory_get_static_pad_templates(factory);
4171                         pads != NULL; pads=pads->next)
4172                 {
4173                         GstStaticPadTemplate *temp1 = pads->data;
4174                         GstCaps* static_caps = NULL;
4175
4176                         if( temp1->direction != GST_PAD_SINK ||
4177                                 temp1->presence != GST_PAD_ALWAYS)
4178                                 continue;
4179
4180                         if ( GST_IS_CAPS( &temp1->static_caps.caps) )
4181                         {
4182                                 /* using existing caps */
4183                                 static_caps = gst_caps_ref( &temp1->static_caps.caps );
4184                         }
4185                         else
4186                         {
4187                                 /* create one */
4188                                 static_caps = gst_caps_from_string ( temp1->static_caps.string );
4189                         }
4190
4191                         res = gst_caps_intersect(caps, static_caps);
4192
4193                         gst_caps_unref( static_caps );
4194                         static_caps = NULL;
4195
4196                         if( res && !gst_caps_is_empty(res) )
4197                         {
4198 #ifdef GST_API_VERSION_1
4199                                 GstElement *new_element;
4200                                 GList *elements = player->parsers;
4201                                 char *name_template = g_strdup(temp1->name_template);
4202                                 gchar *name_to_plug = gst_object_get_name (GST_OBJECT (factory));
4203
4204                                 gst_caps_unref(res);
4205
4206                                 debug_log("found %s to plug\n", name_to_plug);
4207
4208                                 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
4209                                 if ( ! new_element )
4210                                 {
4211                                         debug_error("failed to create element [%s]. continue with next.\n",
4212                                                 gst_object_get_name (GST_OBJECT (factory)));
4213
4214                                         MMPLAYER_FREEIF(name_template);
4215
4216                                         continue;
4217                                 }
4218 #else
4219                                 GstElement *new_element;
4220                                 GList *elements = player->parsers;
4221                                 char *name_template = g_strdup(temp1->name_template);
4222                                 gchar *name_to_plug = GST_PLUGIN_FEATURE_NAME(factory);
4223
4224                                 gst_caps_unref(res);
4225
4226                                 debug_log("found %s to plug\n", name_to_plug);
4227
4228                                 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
4229                                 if ( ! new_element )
4230                                 {
4231                                         debug_error("failed to create element [%s]. continue with next.\n",
4232                                                 GST_PLUGIN_FEATURE_NAME (factory));
4233
4234                                         MMPLAYER_FREEIF(name_template);
4235
4236                                         continue;
4237                                 }
4238 #endif
4239
4240                                 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
4241                                  * because parser can accept its own output as input.
4242                                  */
4243                                 if (g_strrstr(klass, "Parser"))
4244                                 {
4245                                         gchar *selected = NULL;
4246
4247                                         for ( ; elements; elements = g_list_next(elements))
4248                                         {
4249                                                 gchar *element_name = elements->data;
4250
4251                                                 if (g_strrstr(element_name, name_to_plug))
4252                                                 {
4253                                                         debug_log("but, %s already linked, so skipping it\n", name_to_plug);
4254                                                         skip = TRUE;
4255                                                 }
4256                                         }
4257
4258                                         if (skip) continue;
4259
4260                                         selected = g_strdup(name_to_plug);
4261
4262                                         player->parsers = g_list_append(player->parsers, selected);
4263                                 }
4264
4265                                 /* store specific handles for futher control */
4266                                 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
4267                                 {
4268                                         /* FIXIT : first value will be overwritten if there's more
4269                                          * than 1 demuxer/parser
4270                                          */
4271                                         debug_log("plugged element is demuxer. take it\n");
4272                                         mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
4273                                         mainbin[MMPLAYER_M_DEMUX].gst = new_element;
4274                                 }
4275                                 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
4276                                 {
4277                                         if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
4278                                         {
4279                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
4280                                                 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
4281                                                 mainbin[MMPLAYER_M_DEC1].gst = new_element;
4282                                         }
4283                                         else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
4284                                         {
4285                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
4286                                                 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
4287                                                 mainbin[MMPLAYER_M_DEC2].gst = new_element;
4288                                         }
4289                                         /* NOTE : IF one codec is found, add it to supported_codec and remove from
4290                                          * missing plugin. Both of them are used to check what's supported codec
4291                                          * before returning result of play start. And, missing plugin should be
4292                                          * updated here for multi track files.
4293                                          */
4294                                         if(g_str_has_prefix(mime, "video"))
4295                                         {
4296                                                 GstPad *src_pad = NULL;
4297                                                 GstPadTemplate *pad_templ = NULL;
4298                                                 GstCaps *caps = NULL;
4299                                                 gchar *caps_type = NULL;
4300
4301                                                 debug_log("found VIDEO decoder\n");
4302                                                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
4303                                                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
4304
4305                                                 src_pad = gst_element_get_static_pad (new_element, "src");
4306                                                 pad_templ = gst_pad_get_pad_template (src_pad);
4307                                                 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
4308
4309                                                 caps_type = gst_caps_to_string(caps);
4310
4311                                                 if ( g_strrstr( caps_type, "ST12") )
4312                                                         player->is_nv12_tiled = TRUE;
4313
4314                                                 /* clean */
4315                                                 MMPLAYER_FREEIF( caps_type );
4316                                                 gst_object_unref (src_pad);
4317                                         }
4318                                         else if (g_str_has_prefix(mime, "audio"))
4319                                         {
4320                                                 debug_log("found AUDIO decoder\n");
4321                                                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
4322                                                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
4323                                         }
4324                                 }
4325                                 if ( ! __mmplayer_close_link(player, pad, new_element,
4326                                                 name_template,gst_element_factory_get_static_pad_templates(factory)) )
4327                                 {
4328                                         if (player->keep_detecting_vcodec)
4329                                                 continue;
4330
4331                                         /* Link is failed even though a supportable codec is found. */
4332                                         __mmplayer_check_not_supported_codec(player, (gchar *)mime);
4333
4334                                         MMPLAYER_FREEIF(name_template);
4335                                         debug_error("failed to call _close_link\n");
4336                                         return FALSE;
4337                                 }
4338
4339                                 MMPLAYER_FREEIF(name_template);
4340                                 return TRUE;
4341                         }
4342
4343                         gst_caps_unref(res);
4344
4345                         break;
4346                 }
4347         }
4348
4349         /* There is no available codec. */
4350         __mmplayer_check_not_supported_codec(player,(gchar *)mime);
4351
4352         debug_fleave();
4353
4354         return FALSE;
4355
4356 ERROR:
4357         /* release */
4358         if ( queue )
4359                 gst_object_unref( queue );
4360
4361
4362         if ( queue_pad )
4363                 gst_object_unref( queue_pad );
4364
4365         if ( element )
4366                 gst_object_unref ( element );
4367
4368         return FALSE;
4369 }
4370
4371
4372 static
4373 int __mmplayer_check_not_supported_codec(mm_player_t* player, gchar* mime)
4374 {
4375         debug_fenter();
4376
4377         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4378         return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
4379
4380         debug_log("mimetype to check: %s\n", mime );
4381
4382         /* add missing plugin */
4383         /* NOTE : msl should check missing plugin for image mime type.
4384          * Some motion jpeg clips can have playable audio track.
4385          * So, msl have to play audio after displaying popup written video format not supported.
4386          */
4387         if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
4388         {
4389                 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
4390                 {
4391                         debug_log("not found demuxer\n");
4392                         player->not_found_demuxer = TRUE;
4393                         player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
4394
4395                         goto DONE;
4396                 }
4397         }
4398
4399         if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
4400         {
4401                 debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
4402                         player->can_support_codec, player->videodec_linked, player->audiodec_linked);
4403
4404                 /* check that clip have multi tracks or not */
4405                 if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
4406                 {
4407                         debug_log("video plugin is already linked\n");
4408                 }
4409                 else
4410                 {
4411                         debug_warning("add VIDEO to missing plugin\n");
4412                         player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
4413                 }
4414         }
4415         else if ( g_str_has_prefix(mime, "audio") )
4416         {
4417                 if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
4418                 {
4419                         debug_log("audio plugin is already linked\n");
4420                 }
4421                 else
4422                 {
4423                         debug_warning("add AUDIO to missing plugin\n");
4424                         player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
4425                 }
4426         }
4427
4428 DONE:
4429         debug_fleave();
4430
4431         return MM_ERROR_NONE;
4432 }
4433
4434
4435 static void __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data) // @
4436 {
4437     mm_player_t* player = (mm_player_t*)data;
4438
4439         debug_fenter();
4440
4441         return_if_fail( player );
4442
4443         /* remove fakesink */
4444         if ( ! __mmplayer_gst_remove_fakesink( player,
4445                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
4446         {
4447                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
4448                  * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
4449                  * source element are not same. To overcome this situation, this function will called
4450                  * several places and several times. Therefore, this is not an error case.
4451                  */
4452                 return;
4453         }
4454         debug_log("pipeline has completely constructed\n");
4455
4456         player->pipeline_is_constructed = TRUE;
4457
4458         if ( ( PLAYER_INI()->async_start ) &&
4459                 ( player->msg_posted == FALSE ) &&
4460                 ( player->cmd >= MMPLAYER_COMMAND_START ))
4461         {
4462                 __mmplayer_handle_missed_plugin( player );
4463         }
4464
4465         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complete" );
4466 }
4467
4468 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
4469 {
4470         debug_fenter();
4471
4472         return_val_if_fail ( player, FALSE );
4473
4474
4475         if ( MMPLAYER_IS_STREAMING(player) )
4476                 return FALSE;
4477
4478         /* This callback can be set to music player only. */
4479         if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
4480         {
4481                 debug_warning("audio callback is not supported for video");
4482                 return FALSE;
4483         }
4484
4485         if (player->audio_stream_cb)
4486         {
4487                 {
4488                         GstPad *pad = NULL;
4489
4490 #ifdef GST_API_VERSION_1
4491                         pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
4492 #else
4493                         pad = gst_element_get_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
4494 #endif
4495
4496                         if ( !pad )
4497                         {
4498                                 debug_error("failed to get sink pad from audiosink to probe data\n");
4499                                 return FALSE;
4500                         }
4501
4502 #ifdef GST_API_VERSION_1
4503                         player->audio_cb_probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
4504                                 __mmplayer_audio_stream_probe, player, NULL);
4505 #else
4506                         player->audio_cb_probe_id = gst_pad_add_buffer_probe (pad,
4507                                 G_CALLBACK (__mmplayer_audio_stream_probe), player);
4508 #endif
4509
4510                         gst_object_unref (pad);
4511
4512                         pad = NULL;
4513                 }
4514         }
4515         else
4516         {
4517                 debug_error("There is no audio callback to configure.\n");
4518                 return FALSE;
4519         }
4520
4521         debug_fleave();
4522
4523         return TRUE;
4524 }
4525
4526 static void
4527 __mmplayer_init_factories(mm_player_t* player) // @
4528 {
4529         debug_fenter();
4530
4531         return_if_fail ( player );
4532
4533 #ifdef GST_API_VERSION_1
4534         player->factories = gst_registry_feature_filter(gst_registry_get(),
4535                                         (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
4536 #else
4537         player->factories = gst_registry_feature_filter(gst_registry_get_default(),
4538                                         (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
4539 #endif
4540
4541         player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
4542
4543         debug_fleave();
4544 }
4545
4546 static void
4547 __mmplayer_release_factories(mm_player_t* player) // @
4548 {
4549         debug_fenter();
4550
4551         return_if_fail ( player );
4552
4553         if (player->factories)
4554         {
4555                 gst_plugin_feature_list_free (player->factories);
4556                 player->factories = NULL;
4557         }
4558
4559         debug_fleave();
4560 }
4561
4562 static void
4563 __mmplayer_release_misc(mm_player_t* player)
4564 {
4565         int i;
4566         debug_fenter();
4567
4568         return_if_fail ( player );
4569
4570         player->use_video_stream = FALSE;
4571         player->video_stream_cb = NULL;
4572         player->video_stream_cb_user_param = NULL;
4573
4574         player->audio_stream_cb = NULL;
4575         player->audio_stream_cb_user_param = NULL;
4576
4577         player->audio_buffer_cb = NULL;
4578         player->audio_buffer_cb_user_param = NULL;
4579
4580         player->sent_bos = FALSE;
4581         player->playback_rate = DEFAULT_PLAYBACK_RATE;
4582
4583         player->doing_seek = FALSE;
4584
4585         player->streamer = NULL;
4586         player->updated_bitrate_count = 0;
4587         player->total_bitrate = 0;
4588         player->updated_maximum_bitrate_count = 0;
4589         player->total_maximum_bitrate = 0;
4590
4591         player->not_found_demuxer = 0;
4592
4593         player->last_position = 0;
4594         player->duration = 0;
4595         player->http_content_size = 0;
4596         player->not_supported_codec = MISSING_PLUGIN_NONE;
4597         player->can_support_codec = FOUND_PLUGIN_NONE;
4598         player->pending_seek.is_pending = FALSE;
4599         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
4600         player->pending_seek.pos = 0;
4601         player->msg_posted = FALSE;
4602         player->has_many_types = FALSE;
4603
4604         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
4605         {
4606                 player->bitrate[i] = 0;
4607                 player->maximum_bitrate[i] = 0;
4608         }
4609
4610         /* clean found parsers */
4611         if (player->parsers)
4612         {
4613                 g_list_free(player->parsers);
4614                 player->parsers = NULL;
4615         }
4616
4617         MMPLAYER_FREEIF(player->album_art);
4618
4619         /* free memory related to audio effect */
4620         if(player->audio_effect_info.custom_ext_level_for_plugin)
4621         {
4622                 free(player->audio_effect_info.custom_ext_level_for_plugin);
4623         }
4624
4625         debug_fleave();
4626 }
4627
4628 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
4629 {
4630         GstElement *element = NULL;
4631         GstPad *sinkpad;
4632
4633         debug_log("creating %s to plug\n", name);
4634
4635         element = gst_element_factory_make(name, NULL);
4636         if ( ! element )
4637         {
4638                 debug_error("failed to create queue\n");
4639                 return NULL;
4640         }
4641
4642         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
4643         {
4644                 debug_error("failed to set state READY to %s\n", name);
4645                 return NULL;
4646         }
4647
4648         if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
4649         {
4650                 debug_error("failed to add %s\n", name);
4651                 return NULL;
4652         }
4653
4654         sinkpad = gst_element_get_static_pad(element, "sink");
4655
4656         if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
4657         {
4658                 debug_error("failed to link %s\n", name);
4659                 gst_object_unref (sinkpad);
4660
4661                 return NULL;
4662         }
4663
4664         debug_log("linked %s to pipeline successfully\n", name);
4665
4666         gst_object_unref (sinkpad);
4667
4668         return element;
4669 }
4670
4671 static gboolean
4672 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
4673 const char *padname, const GList *templlist)
4674 {
4675         GstPad *pad = NULL;
4676         gboolean has_dynamic_pads = FALSE;
4677         gboolean has_many_types = FALSE;
4678         const char *klass = NULL;
4679         GstStaticPadTemplate *padtemplate = NULL;
4680         GstElementFactory *factory = NULL;
4681         GstElement* queue = NULL;
4682         GstElement* parser = NULL;
4683         GstPad *pssrcpad = NULL;
4684         GstPad *qsrcpad = NULL, *qsinkpad = NULL;
4685         MMPlayerGstElement *mainbin = NULL;
4686         GstStructure* str = NULL;
4687         GstCaps* srccaps = NULL;
4688         GstState warmup = GST_STATE_READY;
4689         gboolean isvideo_decoder = FALSE;
4690         guint q_max_size_time = 0;
4691
4692         debug_fenter();
4693
4694         return_val_if_fail ( player &&
4695                 player->pipeline &&
4696                 player->pipeline->mainbin,
4697                 FALSE );
4698
4699         mainbin = player->pipeline->mainbin;
4700
4701         debug_log("plugging pad %s:%s to newly create %s:%s\n",
4702                                         GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
4703                         GST_PAD_NAME( srcpad ),
4704                         GST_ELEMENT_NAME( sinkelement ),
4705                         padname);
4706
4707         factory = gst_element_get_factory(sinkelement);
4708         klass = gst_element_factory_get_klass(factory);
4709
4710         /* check if player can do start continually */
4711         MMPLAYER_CHECK_CMD_IF_EXIT(player);
4712
4713         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, warmup) )
4714         {
4715                 if (isvideo_decoder)
4716                         player->keep_detecting_vcodec = TRUE;
4717
4718                 debug_error("failed to set %d state to %s\n", warmup, GST_ELEMENT_NAME( sinkelement ));
4719                 goto ERROR;
4720         }
4721
4722         /* add to pipeline */
4723         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
4724         {
4725                 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
4726                 goto ERROR;
4727         }
4728
4729         debug_log("element klass : %s\n", klass);
4730
4731         /* added to support multi track files */
4732         /* only decoder case and any of the video/audio still need to link*/
4733         if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
4734         {
4735                 gchar *name = NULL;
4736
4737                 name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
4738
4739                 if (g_strrstr(name, "mpegtsdemux"))
4740                 {
4741                         gchar *demux_caps = NULL;
4742                         gchar *parser_name = NULL;
4743                         GstCaps *dcaps = NULL;
4744
4745 #ifdef GST_API_VERSION_1
4746                         dcaps = gst_pad_get_current_caps(srcpad);
4747 #else
4748                         dcaps = gst_pad_get_caps(srcpad);
4749 #endif
4750                         demux_caps = gst_caps_to_string(dcaps);
4751
4752                         if (g_strrstr(demux_caps, "video/x-h264"))
4753                         {
4754                                 parser_name = g_strdup("h264parse");
4755                         }
4756                         else if (g_strrstr(demux_caps, "video/mpeg"))
4757                         {
4758                                 parser_name = g_strdup("mpeg4videoparse");
4759                         }
4760
4761                         gst_caps_unref(dcaps);
4762                         MMPLAYER_FREEIF( demux_caps );
4763
4764                         if (parser_name)
4765                         {
4766                                 parser = __mmplayer_element_create_and_link(player, srcpad, parser_name);
4767
4768                                 MMPLAYER_FREEIF(parser_name);
4769
4770                                 if ( ! parser )
4771                                 {
4772                                         debug_error("failed to create parser\n");
4773                                 }
4774                                 else
4775                                 {
4776                                         /* update srcpad if parser is created */
4777                                         pssrcpad = gst_element_get_static_pad(parser, "src");
4778                                         srcpad = pssrcpad;
4779                                 }
4780                         }
4781                 }
4782                 MMPLAYER_FREEIF(name);
4783
4784                 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
4785                 if ( ! queue )
4786                 {
4787                         debug_error("failed to create queue\n");
4788                         goto ERROR;
4789                 }
4790
4791                 /* update srcpad to link with decoder */
4792                 qsrcpad = gst_element_get_static_pad(queue, "src");
4793                 srcpad = qsrcpad;
4794
4795                 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
4796
4797                 /* assigning queue handle for futher manipulation purpose */
4798                 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
4799                 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
4800                 {
4801                         mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
4802                         mainbin[MMPLAYER_M_Q1].gst = queue;
4803
4804                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
4805                 }
4806                 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
4807                 {
4808                         mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
4809                         mainbin[MMPLAYER_M_Q2].gst = queue;
4810
4811                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
4812                 }
4813                 else
4814                 {
4815                         debug_critical("Not supporting more then two elementary stream\n");
4816                         g_assert(1);
4817                 }
4818
4819                 pad = gst_element_get_static_pad(sinkelement, padname);
4820
4821                 if ( ! pad )
4822                 {
4823                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
4824                                 padname, GST_ELEMENT_NAME(sinkelement) );
4825
4826                         pad = gst_element_get_static_pad(sinkelement, "sink");
4827                         if ( ! pad )
4828                         {
4829                                 debug_error("failed to get pad(sink) from %s. \n",
4830                                 GST_ELEMENT_NAME(sinkelement) );
4831                                 goto ERROR;
4832                         }
4833                 }
4834
4835                 /*  to check the video/audio type set the proper flag*/
4836                 {
4837 #ifdef GST_API_VERSION_1
4838                         srccaps = gst_pad_get_current_caps( srcpad );
4839 #else
4840                         srccaps = gst_pad_get_caps( srcpad );
4841 #endif
4842                         if ( !srccaps )
4843                                 goto ERROR;
4844
4845                         str = gst_caps_get_structure( srccaps, 0 );
4846                         if ( ! str )
4847                                 goto ERROR;
4848
4849                         name = gst_structure_get_name(str);
4850                         if ( ! name )
4851                                 goto ERROR;
4852                 }
4853
4854                 /* link queue and decoder. so, it will be queue - decoder. */
4855                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
4856                 {
4857                         gst_object_unref(GST_OBJECT(pad));
4858                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
4859
4860                         /* reconstitute supportable codec */
4861                         if (strstr(name, "video"))
4862                         {
4863                                 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
4864                         }
4865                         else if (strstr(name, "audio"))
4866                         {
4867                                 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
4868                         }
4869                         goto ERROR;
4870                 }
4871
4872                 if (strstr(name, "video"))
4873                 {
4874                         player->videodec_linked = 1;
4875                         debug_msg("player->videodec_linked set to 1\n");
4876
4877                 }
4878                 else if (strstr(name, "audio"))
4879                 {
4880                         player->audiodec_linked = 1;
4881                         debug_msg("player->auddiodec_linked set to 1\n");
4882                 }
4883
4884                 gst_object_unref(GST_OBJECT(pad));
4885                 gst_caps_unref(GST_CAPS(srccaps));
4886                 srccaps = NULL;
4887         }
4888
4889         if ( !MMPLAYER_IS_HTTP_PD(player) )
4890         {
4891                 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
4892                 {
4893                         if (MMPLAYER_IS_HTTP_STREAMING(player))
4894                         {
4895 #ifndef GST_API_VERSION_1
4896                                 GstFormat fmt  = GST_FORMAT_BYTES;
4897 #endif
4898                                 gint64 dur_bytes = 0L;
4899                                 gchar *file_buffering_path = NULL;
4900                                 gboolean use_file_buffer = FALSE;
4901
4902                                 if ( !mainbin[MMPLAYER_M_S_BUFFER].gst)
4903                                 {
4904                                         debug_log("creating http streaming buffering queue\n");
4905
4906                                         queue = gst_element_factory_make("queue2", "http_streaming_buffer");
4907                                         if ( ! queue )
4908                                         {
4909                                                 debug_critical ( "failed to create buffering queue element\n" );
4910                                                 goto ERROR;
4911                                         }
4912
4913                                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
4914                                         {
4915                                                 debug_error("failed to set state READY to buffering queue\n");
4916                                                 goto ERROR;
4917                                         }
4918
4919                                         if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
4920                                         {
4921                                                 debug_error("failed to add buffering queue\n");
4922                                                 goto ERROR;
4923                                         }
4924
4925                                         qsinkpad = gst_element_get_static_pad(queue, "sink");
4926                                         qsrcpad = gst_element_get_static_pad(queue, "src");
4927
4928                                         if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
4929                                         {
4930                                                 debug_error("failed to link buffering queue\n");
4931                                                 goto ERROR;
4932                                         }
4933                                         srcpad = qsrcpad;
4934
4935
4936                                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_S_BUFFER;
4937                                         mainbin[MMPLAYER_M_S_BUFFER].gst = queue;
4938
4939                                         if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
4940                                         {
4941 #ifdef GST_API_VERSION_1
4942                                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
4943                                                         debug_error("fail to get duration.\n");
4944 #else
4945                                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
4946                                                         debug_error("fail to get duration.\n");
4947 #endif
4948
4949                                                 if (dur_bytes>0)
4950                                                 {
4951                                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
4952                                                         file_buffering_path = g_strdup(PLAYER_INI()->http_file_buffer_path);
4953                                                 }
4954                                         }
4955
4956                                         __mm_player_streaming_set_buffer(player->streamer,
4957                                                 queue,
4958                                                 TRUE,
4959                                                 PLAYER_INI()->http_max_size_bytes,
4960                                                 1.0,
4961                                                 PLAYER_INI()->http_buffering_limit,
4962                                                 PLAYER_INI()->http_buffering_time,
4963                                                 use_file_buffer,
4964                                                 file_buffering_path,
4965                                                 dur_bytes);
4966
4967                                         MMPLAYER_FREEIF(file_buffering_path);
4968                                 }
4969                         }
4970                 }
4971         }
4972         /* if it is not decoder or */
4973         /* in decoder case any of the video/audio still need to link*/
4974         if(!g_strrstr(klass, "Decoder"))
4975         {
4976
4977                 pad = gst_element_get_static_pad(sinkelement, padname);
4978                 if ( ! pad )
4979                 {
4980                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
4981                                         padname, GST_ELEMENT_NAME(sinkelement) );
4982
4983                         pad = gst_element_get_static_pad(sinkelement, "sink");
4984
4985                         if ( ! pad )
4986                         {
4987                                 debug_error("failed to get pad(sink) from %s. \n",
4988                                         GST_ELEMENT_NAME(sinkelement) );
4989                                 goto ERROR;
4990                         }
4991                 }
4992
4993                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
4994                 {
4995                         gst_object_unref(GST_OBJECT(pad));
4996                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
4997                         goto ERROR;
4998                 }
4999
5000                 gst_object_unref(GST_OBJECT(pad));
5001         }
5002
5003         for(;templlist != NULL; templlist = templlist->next)
5004         {
5005                 padtemplate = templlist->data;
5006
5007                 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
5008
5009                 if(     padtemplate->direction != GST_PAD_SRC ||
5010                         padtemplate->presence == GST_PAD_REQUEST        )
5011                         continue;
5012
5013                 switch(padtemplate->presence)
5014                 {
5015                         case GST_PAD_ALWAYS:
5016                         {
5017                                 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
5018 #ifdef GST_API_VERSION_1
5019                                 GstCaps *caps = gst_pad_get_current_caps(srcpad);
5020 #else
5021                                 GstCaps *caps = gst_pad_get_caps(srcpad);
5022 #endif
5023
5024                                 /* Check whether caps has many types */
5025                                 if ( gst_caps_get_size (caps) > 1 && g_strrstr(klass, "Parser")) {
5026                                         debug_log ("has_many_types for this caps [%s]\n", gst_caps_to_string(caps));
5027                                         has_many_types = TRUE;
5028                                         break;
5029                                 }
5030
5031                                 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
5032                                 {
5033                                         gst_object_unref(GST_OBJECT(srcpad));
5034                                         gst_caps_unref(GST_CAPS(caps));
5035
5036                                         debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
5037                                         goto ERROR;
5038                                 }
5039
5040                                 gst_caps_unref(GST_CAPS(caps));
5041                                 gst_object_unref(GST_OBJECT(srcpad));
5042
5043                         }
5044                         break;
5045
5046
5047                         case GST_PAD_SOMETIMES:
5048                                 has_dynamic_pads = TRUE;
5049                         break;
5050
5051                         default:
5052                                 break;
5053                 }
5054         }
5055
5056         /* check if player can do start continually */
5057         MMPLAYER_CHECK_CMD_IF_EXIT(player);
5058
5059         if( has_dynamic_pads )
5060         {
5061                 player->have_dynamic_pad = TRUE;
5062                 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, "pad-added",
5063                         G_CALLBACK(__mmplayer_add_new_pad), player);
5064
5065                 /* for streaming, more then one typefind will used for each elementary stream
5066                  * so this doesn't mean the whole pipeline completion
5067                  */
5068                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
5069                 {
5070                         MMPLAYER_SIGNAL_CONNECT( player, sinkelement, "no-more-pads",
5071                                 G_CALLBACK(__mmplayer_pipeline_complete), player);
5072                 }
5073         }
5074
5075         if (has_many_types)
5076         {
5077                 GstPad *pad = NULL;
5078
5079                 player->has_many_types = has_many_types;
5080
5081                 pad = gst_element_get_static_pad(sinkelement, "src");
5082                 MMPLAYER_SIGNAL_CONNECT (player, pad, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
5083                 gst_object_unref (GST_OBJECT(pad));
5084         }
5085
5086
5087         /* check if player can do start continually */
5088         MMPLAYER_CHECK_CMD_IF_EXIT(player);
5089
5090         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
5091         {
5092                 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
5093                 goto ERROR;
5094         }
5095
5096         if ( queue )
5097         {
5098                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
5099                 {
5100                         debug_error("failed to set state PAUSED to queue\n");
5101                         goto ERROR;
5102                 }
5103
5104                 queue = NULL;
5105
5106                 gst_object_unref (GST_OBJECT(qsrcpad));
5107                 qsrcpad = NULL;
5108         }
5109
5110         if ( parser )
5111         {
5112                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
5113                 {
5114                         debug_error("failed to set state PAUSED to queue\n");
5115                         goto ERROR;
5116                 }
5117
5118                 parser = NULL;
5119
5120                 gst_object_unref (GST_OBJECT(pssrcpad));
5121                 pssrcpad = NULL;
5122         }
5123
5124         debug_fleave();
5125
5126         return TRUE;
5127
5128 ERROR:
5129
5130         if ( queue )
5131         {
5132                 gst_object_unref(GST_OBJECT(qsrcpad));
5133
5134                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
5135                  * You need to explicitly set elements to the NULL state before
5136                  * dropping the final reference, to allow them to clean up.
5137                  */
5138                 gst_element_set_state(queue, GST_STATE_NULL);
5139                 /* And, it still has a parent "player".
5140                  * You need to let the parent manage the object instead of unreffing the object directly.
5141                  */
5142
5143                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
5144                 //gst_object_unref( queue );
5145         }
5146
5147         if ( srccaps )
5148                 gst_caps_unref(GST_CAPS(srccaps));
5149
5150     return FALSE;
5151 }
5152
5153 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
5154 {
5155         const gchar *klass;
5156         //const gchar *name;
5157
5158         /* we only care about element factories */
5159         if (!GST_IS_ELEMENT_FACTORY(feature))
5160                 return FALSE;
5161
5162         /* only parsers, demuxers and decoders */
5163         klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
5164         //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
5165
5166         if( g_strrstr(klass, "Demux") == NULL &&
5167                 g_strrstr(klass, "Codec/Decoder") == NULL &&
5168                 g_strrstr(klass, "Depayloader") == NULL &&
5169                 g_strrstr(klass, "Parse") == NULL)
5170         {
5171                 return FALSE;
5172         }
5173     return TRUE;
5174 }
5175
5176
5177 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
5178 {
5179         mm_player_t* player = (mm_player_t*) data;
5180         GstCaps *caps = NULL;
5181         GstStructure *str = NULL;
5182         const char *name;
5183
5184         debug_fenter();
5185
5186         return_if_fail ( pad )
5187         return_if_fail ( unused )
5188         return_if_fail ( data )
5189
5190 #ifdef GST_API_VERSION_1
5191         caps = gst_pad_get_current_caps(pad);
5192 #else
5193         caps = gst_pad_get_caps(pad);
5194 #endif
5195         if ( !caps )
5196                 return;
5197
5198         str = gst_caps_get_structure(caps, 0);
5199         if ( !str )
5200                 return;
5201
5202         name = gst_structure_get_name(str);
5203         if ( !name )
5204                 return;
5205         debug_log("name=%s\n", name);
5206
5207         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
5208         {
5209                 debug_error("failed to autoplug for type (%s)\n", name);
5210                 gst_caps_unref(caps);
5211                 return;
5212         }
5213
5214         gst_caps_unref(caps);
5215
5216         __mmplayer_pipeline_complete( NULL, (gpointer)player );
5217
5218         debug_fleave();
5219
5220         return;
5221 }
5222
5223 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
5224 {
5225         GstStructure *str;
5226         gint version = 0;
5227         const char *stream_type;
5228         gchar *version_field = NULL;
5229
5230         debug_fenter();
5231
5232         return_if_fail ( player );
5233         return_if_fail ( caps );
5234
5235         str = gst_caps_get_structure(caps, 0);
5236         if ( !str )
5237                 return;
5238
5239         stream_type = gst_structure_get_name(str);
5240         if ( !stream_type )
5241                 return;
5242
5243
5244         /* set unlinked mime type for downloadable codec */
5245         if (g_str_has_prefix(stream_type, "video/"))
5246         {
5247                 if (g_str_has_prefix(stream_type, "video/mpeg"))
5248                 {
5249                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
5250                         version_field = MM_PLAYER_MPEG_VNAME;
5251                 }
5252                 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
5253                 {
5254                         gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
5255                         version_field = MM_PLAYER_WMV_VNAME;
5256
5257                 }
5258                 else if (g_str_has_prefix(stream_type, "video/x-divx"))
5259                 {
5260                         gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
5261                         version_field = MM_PLAYER_DIVX_VNAME;
5262                 }
5263
5264                 if (version)
5265                 {
5266                         player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
5267                 }
5268                 else
5269                 {
5270                         player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
5271                 }
5272         }
5273         else if (g_str_has_prefix(stream_type, "audio/"))
5274         {
5275                 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
5276                 {
5277                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
5278                         version_field = MM_PLAYER_MPEG_VNAME;
5279                 }
5280                 else if (g_str_has_prefix(stream_type, "audio/x-wma"))
5281                 {
5282                         gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
5283                         version_field = MM_PLAYER_WMA_VNAME;
5284                 }
5285
5286                 if (version)
5287                 {
5288                         player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
5289                 }
5290                 else
5291                 {
5292                         player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
5293                 }
5294         }
5295
5296         debug_fleave();
5297 }
5298
5299 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
5300 {
5301         mm_player_t* player = (mm_player_t*) data;
5302         GstCaps *caps = NULL;
5303         GstStructure *str = NULL;
5304         const char *name;
5305
5306         debug_fenter();
5307         return_if_fail ( player );
5308         return_if_fail ( pad );
5309
5310         GST_OBJECT_LOCK (pad);
5311 #ifdef GST_API_VERSION_1
5312         if ((caps = gst_pad_get_current_caps (pad)))
5313                 gst_caps_ref(caps);
5314 #else
5315         if ((caps = GST_PAD_CAPS(pad)))
5316                 gst_caps_ref(caps);
5317 #endif
5318         GST_OBJECT_UNLOCK (pad);
5319
5320         if ( NULL == caps )
5321         {
5322 #ifdef GST_API_VERSION_1
5323                 caps = gst_pad_get_current_caps(pad);
5324 #else
5325                 caps = gst_pad_get_caps(pad);
5326 #endif
5327                 if ( !caps ) return;
5328         }
5329
5330         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5331
5332         str = gst_caps_get_structure(caps, 0);
5333         if ( !str )
5334                 return;
5335
5336         name = gst_structure_get_name(str);
5337         if ( !name )
5338                 return;
5339
5340         player->num_dynamic_pad++;
5341         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
5342
5343         /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
5344           *     If want to play it, remove this code.
5345           */
5346         if (g_strrstr(name, "application"))
5347         {
5348                 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
5349                 {
5350                         /* If id3/ape tag comes, keep going */
5351                         debug_log("application mime exception : id3/ape tag");
5352                 }
5353                 else
5354                 {
5355                         /* Otherwise, we assume that this stream is subtile. */
5356                         debug_log(" application mime type pad is closed.");
5357                         return;
5358                 }
5359         }
5360         else if (g_strrstr(name, "audio"))
5361         {
5362                 gint samplerate = 0, channels = 0;
5363
5364                 /* set stream information */
5365                 /* if possible, set it here because the caps is not distrubed by resampler. */
5366                 gst_structure_get_int (str, "rate", &samplerate);
5367                 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
5368
5369                 gst_structure_get_int (str, "channels", &channels);
5370                 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
5371
5372                 debug_log("audio samplerate : %d        channels : %d", samplerate, channels);
5373         }
5374         else if (g_strrstr(name, "video"))
5375         {
5376                 gint stype;
5377                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
5378
5379                 /* don't make video because of not required */
5380                 if (stype == MM_DISPLAY_SURFACE_NULL)
5381                 {
5382                         debug_log("no video because it's not required");
5383                         return;
5384                 }
5385
5386                 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
5387         }
5388
5389         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
5390         {
5391                 debug_error("failed to autoplug for type (%s)", name);
5392
5393                 __mmplayer_set_unlinked_mime_type(player, caps);
5394         }
5395
5396         gst_caps_unref(caps);
5397
5398         debug_fleave();
5399         return;
5400 }
5401
5402 /* test API for tuning audio gain. this API should be
5403  * deprecated before the day of final release
5404  */
5405 int
5406 _mmplayer_set_volume_tune(MMHandleType hplayer, MMPlayerVolumeType volume)
5407 {
5408         mm_player_t* player = (mm_player_t*) hplayer;
5409         gint error = MM_ERROR_NONE;
5410         gint vol_max = 0;
5411         gboolean isMidi = FALSE;
5412         gint i = 0;
5413
5414         debug_fenter();
5415
5416         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5417         return_val_if_fail( player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED )
5418
5419         debug_log("clip type=%d(1-midi, 0-others), volume [L]=%d:[R]=%d\n",
5420                 player->profile.play_mode, volume.level[0], volume.level[1]);
5421
5422         isMidi = ( player->profile.play_mode == MM_PLAYER_MODE_MIDI ) ? TRUE : FALSE;
5423
5424         if ( isMidi )
5425                 vol_max = 1000;
5426         else
5427                 vol_max = 100;
5428
5429         /* is it proper volume level? */
5430         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; ++i)
5431         {
5432                 if (volume.level[i] < 0 || volume.level[i] > vol_max) {
5433                         debug_log("Invalid Volume level!!!! \n");
5434                         return MM_ERROR_INVALID_ARGUMENT;
5435                 }
5436         }
5437
5438         if ( isMidi )
5439         {
5440                 if ( player->pipeline->mainbin )
5441                 {
5442                         GstElement *midi_element = player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst;
5443
5444                         if ( midi_element && ( strstr(GST_ELEMENT_NAME(midi_element), "midiparse")) )
5445                         {
5446                                 debug_log("setting volume (%d) level to midi plugin\n", volume.level[0]);
5447
5448                                 g_object_set(midi_element, "volume", volume.level[0], NULL);
5449                         }
5450                 }
5451         }
5452         else
5453         {
5454                 if ( player->pipeline->audiobin )
5455                 {
5456                         GstElement *sink_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
5457
5458                         /* Set to Avsysaudiosink element */
5459                         if ( sink_element )
5460                         {
5461                                 gint vol_value = 0;
5462                                 gboolean mute = FALSE;
5463                                 vol_value = volume.level[0];
5464
5465                                 g_object_set(G_OBJECT(sink_element), "tuningvolume", vol_value, NULL);
5466
5467                                 mute = (vol_value == 0)? TRUE:FALSE;
5468
5469                                 g_object_set(G_OBJECT(sink_element), "mute", mute, NULL);
5470                         }
5471
5472                 }
5473         }
5474
5475         debug_fleave();
5476
5477         return error;
5478 }
5479
5480 static gboolean
5481 __mmplayer_can_extract_pcm( mm_player_t* player )
5482 {
5483         MMHandleType attrs = 0;
5484         gboolean is_drm = FALSE;
5485         gboolean sound_extraction = FALSE;
5486
5487         return_val_if_fail ( player, FALSE );
5488
5489         attrs = MMPLAYER_GET_ATTRS(player);
5490         if ( !attrs )
5491         {
5492                 debug_error("fail to get attributes.");
5493                 return FALSE;
5494         }
5495
5496         /* check file is drm or not */
5497         g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
5498
5499         /* get sound_extraction property */
5500         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
5501
5502         if ( ! sound_extraction || is_drm )
5503         {
5504                 debug_log("checking pcm extraction mode : %d, drm : %d", sound_extraction, is_drm);
5505                 return FALSE;
5506         }
5507
5508         return TRUE;
5509 }
5510
5511 static void
5512 __mmplayer_cancel_delayed_eos( mm_player_t* player )
5513 {
5514         debug_fenter();
5515
5516         return_if_fail( player );
5517
5518         if ( player->eos_timer )
5519         {
5520                 g_source_remove( player->eos_timer );
5521         }
5522
5523         player->eos_timer = 0;
5524
5525         debug_fleave();
5526
5527         return;
5528 }
5529
5530 gboolean
5531 __mmplayer_eos_timer_cb(gpointer u_data)
5532 {
5533         mm_player_t* player = NULL;
5534         player = (mm_player_t*) u_data;
5535
5536         debug_fenter();
5537
5538         return_val_if_fail( player, FALSE );
5539
5540         /* posting eos */
5541         MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
5542
5543         /* cleare timer id */
5544         player->eos_timer = 0;
5545
5546         debug_fleave();
5547
5548         /* we are returning FALSE as we need only one posting */
5549         return FALSE;
5550 }
5551
5552 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force)
5553 {
5554         gint antishock = FALSE;
5555         MMHandleType attrs = 0;
5556
5557         debug_fenter();
5558
5559         return_if_fail ( player && player->pipeline );
5560
5561         /* It should be passed for video only clip */
5562         if ( ! player->pipeline->audiobin )
5563                 return;
5564
5565         if ( ( g_strrstr(PLAYER_INI()->name_of_audiosink, "avsysaudiosink")) )
5566         {
5567                 attrs = MMPLAYER_GET_ATTRS(player);
5568                 if ( ! attrs )
5569                 {
5570                         debug_error("fail to get attributes.\n");
5571                         return;
5572                 }
5573
5574                 mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock);
5575
5576                 debug_log("setting antishock as (%d)\n", antishock);
5577
5578                 if ( disable_by_force )
5579                 {
5580                         debug_log("but, antishock is disabled by force when is seeked\n");
5581
5582                         antishock = FALSE;
5583                 }
5584
5585                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "fadeup", antishock, NULL);
5586         }
5587
5588         debug_fleave();
5589
5590         return;
5591 }
5592
5593 /* Note : if silent is true, then subtitle would not be displayed. :*/
5594 int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent)
5595 {
5596         mm_player_t* player = (mm_player_t*) hplayer;
5597
5598         debug_fenter();
5599
5600         /* check player handle */
5601         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5602
5603         player->is_subtitle_off = silent;
5604
5605         debug_log("subtitle is %s.\n", player->is_subtitle_off ? "ON" : "OFF");
5606
5607         debug_fleave();
5608
5609         return MM_ERROR_NONE;
5610 }
5611
5612
5613 int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent)
5614 {
5615         mm_player_t* player = (mm_player_t*) hplayer;
5616
5617         debug_fenter();
5618
5619         /* check player handle */
5620         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5621
5622         *silent = player->is_subtitle_off;
5623
5624         debug_log("subtitle is %s.\n", silent ? "ON" : "OFF");
5625
5626         debug_fleave();
5627
5628         return MM_ERROR_NONE;
5629 }
5630
5631 int _mmplayer_get_track_count(MMHandleType hplayer,  MMPlayerTrackType track_type, int *count)
5632 {
5633         mm_player_t* player = (mm_player_t*) hplayer;
5634         MMHandleType attrs = 0;
5635         int ret = MM_ERROR_NONE;
5636
5637         debug_fenter();
5638
5639         /* check player handle */
5640         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5641         return_val_if_fail(count, MM_ERROR_COMMON_INVALID_ARGUMENT);
5642         return_val_if_fail((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
5643                  ||(MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING),
5644                 MM_ERROR_PLAYER_INVALID_STATE);
5645
5646         attrs = MMPLAYER_GET_ATTRS(player);
5647         if ( !attrs )
5648         {
5649                 debug_error("cannot get content attribute");
5650                 return MM_ERROR_PLAYER_INTERNAL;
5651         }
5652
5653         switch (track_type)
5654         {
5655                 case MM_PLAYER_TRACK_TYPE_AUDIO:
5656                         ret = mm_attrs_get_int_by_name(attrs, "content_audio_track_num", count);
5657                         break;
5658                 case MM_PLAYER_TRACK_TYPE_VIDEO:
5659                         ret = mm_attrs_get_int_by_name(attrs, "content_video_track_num", count);
5660                         break;
5661                 case MM_PLAYER_TRACK_TYPE_TEXT:
5662                         ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
5663                         break;
5664                 default:
5665                         ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
5666                         break;
5667         }
5668
5669         debug_log ("%d track num is %d\n", track_type, *count);
5670
5671         debug_fleave();
5672
5673         return ret;
5674 }
5675
5676 const gchar *
5677 __get_state_name ( int state )
5678 {
5679         switch ( state )
5680         {
5681                 case MM_PLAYER_STATE_NULL:
5682                         return "NULL";
5683                 case MM_PLAYER_STATE_READY:
5684                         return "READY";
5685                 case MM_PLAYER_STATE_PAUSED:
5686                         return "PAUSED";
5687                 case MM_PLAYER_STATE_PLAYING:
5688                         return "PLAYING";
5689                 case MM_PLAYER_STATE_NONE:
5690                         return "NONE";
5691                 default:
5692                         return "INVAID";
5693         }
5694 }
5695