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