5f3bc7e403e18e13cce8d62dbe28d5f9ca379d42
[platform/core/multimedia/libmm-player.git] / src / mm_player_priv.c
1 /*
2  * libmm-player
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
7  * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 /*===========================================================================================
24 |                                                                                                                                                                                       |
25 |  INCLUDE FILES                                                                                                                                                        |
26 |                                                                                                                                                                                       |
27 ========================================================================================== */
28 #include <glib.h>
29 #include <gst/gst.h>
30 #include <gst/app/gstappsrc.h>
31 #include <gst/video/videooverlay.h>
32 #include <gst/wayland/wayland.h>
33 #include <gst/audio/gstaudiobasesink.h>
34 #include <unistd.h>
35 #include <sys/stat.h>
36 #include <string.h>
37 #include <sys/time.h>
38 #include <stdlib.h>
39 #include <dlog.h>
40
41 #include <mm_error.h>
42 #include <mm_attrs.h>
43 #include <mm_attrs_private.h>
44 #include <mm_sound.h>
45 #include <mm_sound_focus.h>
46
47 #include "mm_player_priv.h"
48 #include "mm_player_ini.h"
49 #include "mm_player_attrs.h"
50 #include "mm_player_capture.h"
51 #include "mm_player_utils.h"
52 #include "mm_player_tracks.h"
53
54 /*===========================================================================================
55 |                                                                                                                                                                                       |
56 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
57 |                                                                                                                                                                                       |
58 ========================================================================================== */
59
60 /*---------------------------------------------------------------------------
61 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
62 ---------------------------------------------------------------------------*/
63
64 /*---------------------------------------------------------------------------
65 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
66 ---------------------------------------------------------------------------*/
67
68 /*---------------------------------------------------------------------------
69 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
70 ---------------------------------------------------------------------------*/
71
72 /*---------------------------------------------------------------------------
73 |    LOCAL #defines:                                                                                                            |
74 ---------------------------------------------------------------------------*/
75 #define TRICK_PLAY_MUTE_THRESHOLD_MAX   2.0
76 #define TRICK_PLAY_MUTE_THRESHOLD_MIN   0.0
77
78 #define MM_VOLUME_FACTOR_DEFAULT                1.0
79 #define MM_VOLUME_FACTOR_MIN                    0
80 #define MM_VOLUME_FACTOR_MAX                    1.0
81
82 /* Don't need to sleep for sound fadeout
83  * fadeout related fucntion will be deleted(Deprecated)
84  */
85 #define MM_PLAYER_FADEOUT_TIME_DEFAULT  0
86
87 #define MM_PLAYER_MPEG_VNAME                    "mpegversion"
88 #define MM_PLAYER_DIVX_VNAME                    "divxversion"
89 #define MM_PLAYER_WMV_VNAME                             "wmvversion"
90 #define MM_PLAYER_WMA_VNAME                             "wmaversion"
91
92 #define DEFAULT_PLAYBACK_RATE                   1.0
93 #define PLAYBACK_RATE_EX_AUDIO_MIN              0.5
94 #define PLAYBACK_RATE_EX_AUDIO_MAX              2.0
95 #define PLAYBACK_RATE_EX_VIDEO_MIN              0.5
96 #define PLAYBACK_RATE_EX_VIDEO_MAX              1.5
97 #define DEFAULT_NUM_OF_V_OUT_BUFFER             3
98
99 #define GST_QUEUE_DEFAULT_TIME                  4
100 #define GST_QUEUE_HLS_TIME                              8
101
102 #define MMPLAYER_USE_FILE_FOR_BUFFERING(player) \
103         (((player)->profile.uri_type != MM_PLAYER_URI_TYPE_HLS) && \
104         (player->ini.http_use_file_buffer) && \
105         (player->http_file_buffering_path) && \
106         (strlen(player->http_file_buffering_path) > 0))
107 #define MM_PLAYER_NAME  "mmplayer"
108
109 #define PLAYER_DISPLAY_MODE_DST_ROI             5
110
111 /*---------------------------------------------------------------------------
112 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
113 ---------------------------------------------------------------------------*/
114
115 /*---------------------------------------------------------------------------
116 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
117 ---------------------------------------------------------------------------*/
118
119 /*---------------------------------------------------------------------------
120 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
121 ---------------------------------------------------------------------------*/
122
123 /*---------------------------------------------------------------------------
124 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
125 ---------------------------------------------------------------------------*/
126
127 /*---------------------------------------------------------------------------
128 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
129 ---------------------------------------------------------------------------*/
130 static int              __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
131 static int              __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
132 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player);
133 static int              __mmplayer_gst_create_subtitle_src(mm_player_t* player);
134 static int              __mmplayer_gst_create_pipeline(mm_player_t* player);
135 static int              __mmplayer_gst_destroy_pipeline(mm_player_t* player);
136 static int              __mmplayer_gst_element_link_bucket(GList* element_bucket);
137
138 static GstPadProbeReturn        __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data);
139 static void             __mmplayer_gst_decode_pad_added(GstElement* elem, GstPad* pad, gpointer data);
140 static void             __mmplayer_gst_decode_no_more_pads(GstElement* elem, gpointer data);
141 static void             __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gpointer data);
142 static void             __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad, GstCaps *caps, gpointer data);
143 static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
144 static gint             __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad, GstCaps * caps, GstElementFactory* factory, gpointer data);
145 //static GValueArray* __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
146 static void __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad, gpointer data);
147 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
148 static void     __mmplayer_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
149 static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
150 static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
151
152 static void     __mmplayer_typefind_have_type(GstElement *tf, guint probability, GstCaps *caps, gpointer data);
153 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
154 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
155 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
156 static gboolean __mmplayer_is_only_mp3_type(gchar *str_caps);
157 static void     __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
158 //static void   __mmplayer_check_video_zero_cpoy(mm_player_t* player, GstElementFactory* factory);
159
160 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
161 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
162 static void             __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
163
164 static void             __mmplayer_gst_rtp_no_more_pads(GstElement *element,  gpointer data);
165 //static void    __mmplayer_gst_wfd_dynamic_pad(GstElement *element, GstPad *pad, gpointer data);
166 static void             __mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data);
167 static gboolean __mmplayer_get_stream_service_type(mm_player_t* player);
168 static gboolean __mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
169
170
171 static void             __mmplayer_init_factories(mm_player_t* player);
172 static void             __mmplayer_release_factories(mm_player_t* player);
173 static void             __mmplayer_release_misc(mm_player_t* player);
174 static void             __mmplayer_release_misc_post(mm_player_t* player);
175 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
176 static GstBusSyncReply __mmplayer_bus_sync_callback(GstBus * bus, GstMessage * message, gpointer data);
177 static gboolean __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data);
178
179 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
180 static gboolean      __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
181
182 int             __mmplayer_switch_audio_sink(mm_player_t* player);
183 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
184 static GstPadProbeReturn __mmplayer_audio_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
185 static void __mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
186 static void __mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
187 static GstPadProbeReturn __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
188 static int __mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index);
189
190 static gboolean __mmplayer_check_subtitle(mm_player_t* player);
191 static gboolean __mmplayer_handle_streaming_error(mm_player_t* player, GstMessage * message);
192 static void             __mmplayer_handle_eos_delay(mm_player_t* player, int delay_in_ms);
193 static void             __mmplayer_cancel_eos_timer(mm_player_t* player);
194 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
195 static gboolean __mmplayer_link_decoder(mm_player_t* player, GstPad *srcpad);
196 static gboolean __mmplayer_link_sink(mm_player_t* player, GstPad *srcpad);
197 static int              __mmplayer_handle_missed_plugin(mm_player_t* player);
198 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
199 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
200 static void             __mmplayer_add_sink(mm_player_t* player, GstElement* sink);
201 static void             __mmplayer_del_sink(mm_player_t* player, GstElement* sink);
202 static void             __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
203 static gpointer __mmplayer_next_play_thread(gpointer data);
204 static gpointer __mmplayer_repeat_thread(gpointer data);
205 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
206
207
208 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
209 static GstPadProbeReturn __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data);
210 static void __mmplayer_release_dump_list(GList *dump_list);
211
212 static int              __gst_realize(mm_player_t* player);
213 static int              __gst_unrealize(mm_player_t* player);
214 static int              __gst_start(mm_player_t* player);
215 static int              __gst_stop(mm_player_t* player);
216 static int              __gst_pause(mm_player_t* player, gboolean async);
217 static int              __gst_resume(mm_player_t* player, gboolean async);
218 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
219                                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
220                                         gint64 cur, GstSeekType stop_type, gint64 stop);
221 static int __gst_pending_seek(mm_player_t* player);
222
223 static int              __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called);
224 static int              __gst_get_position(mm_player_t* player, int format, unsigned long *position);
225 static int              __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
226 static int              __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
227 static int              __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
228
229 static gboolean __gst_send_event_to_sink(mm_player_t* player, GstEvent* event);
230
231 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
232 static gboolean __mmplayer_can_extract_pcm(mm_player_t* player);
233
234 /*fadeout */
235 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
236 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
237
238 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
239 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
240
241 /* util */
242 static gboolean __is_ms_buff_src(mm_player_t* player);
243 static gboolean __has_suffix(mm_player_t * player, const gchar * suffix);
244
245 static int __mmplayer_realize_streaming_ext(mm_player_t* player);
246 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
247 static int __mmplayer_start_streaming_ext(mm_player_t *player);
248 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
249 static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
250
251 static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
252 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
253 static void __mmplayer_check_pipeline(mm_player_t* player);
254 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
255 static void __mmplayer_deactivate_old_path(mm_player_t *player);
256 #if 0 // We'll need this in future.
257 static int __mmplayer_gst_switching_element(mm_player_t *player, GstElement *search_from, const gchar *removal_name, const gchar *new_element_name);
258 #endif
259
260 static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg);
261 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
262
263 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
264 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name);
265 static void             __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data);
266 static void             __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data);
267 static void     __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data);
268 static void             __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data);
269 static void             __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data);
270 static gboolean __gst_seek_audio_data(GstElement * appsrc, guint64 position, gpointer user_data);
271 static gboolean __gst_seek_video_data(GstElement * appsrc, guint64 position, gpointer user_data);
272 static gboolean __gst_seek_subtitle_data(GstElement * appsrc, guint64 position, gpointer user_data);
273 static void             __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data);
274 static void             __mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all);
275 static void             __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer);
276 static void             __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type);
277
278 /*===========================================================================================
279 |                                                                                                                                                                                       |
280 |  FUNCTION DEFINITIONS                                                                                                                                         |
281 |                                                                                                                                                                                       |
282 ========================================================================================== */
283
284 #if 0 //debug
285 static void
286 print_tag(const GstTagList * list, const gchar * tag, gpointer unused)
287 {
288         gint i, count;
289
290         count = gst_tag_list_get_tag_size(list, tag);
291
292         LOGD("count = %d", count);
293
294         for (i = 0; i < count; i++) {
295                 gchar *str;
296
297                 if (gst_tag_get_type(tag) == G_TYPE_STRING) {
298                         if (!gst_tag_list_get_string_index(list, tag, i, &str))
299                                 g_assert_not_reached();
300                 } else
301                         str = g_strdup_value_contents(gst_tag_list_get_value_index(list, tag, i));
302
303                 if (i == 0)
304                         g_print("  %15s: %s\n", gst_tag_get_nick(tag), str);
305                 else
306                         g_print("                 : %s\n", str);
307
308                 g_free(str);
309         }
310 }
311 #endif
312
313 /* This function should be called after the pipeline goes PAUSED or higher
314 state. */
315 gboolean
316 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
317 {
318         static gboolean has_duration = FALSE;
319         static gboolean has_video_attrs = FALSE;
320         static gboolean has_audio_attrs = FALSE;
321         static gboolean has_bitrate = FALSE;
322         gboolean missing_only = FALSE;
323         gboolean all = FALSE;
324         gint64 dur_nsec = 0;
325         GstStructure* p = NULL;
326         MMHandleType attrs = 0;
327         gchar *path = NULL;
328         gint stream_service_type = STREAMING_SERVICE_NONE;
329         struct stat sb;
330
331         MMPLAYER_FENTER();
332
333         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
334
335         /* check player state here */
336         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
337                 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) {
338                 /* give warning now only */
339                 LOGW("be careful. content attributes may not available in this state ");
340         }
341
342         /* get content attribute first */
343         attrs = MMPLAYER_GET_ATTRS(player);
344         if (!attrs) {
345                 LOGE("cannot get content attribute");
346                 return FALSE;
347         }
348
349         /* get update flag */
350
351         if (flag & ATTR_MISSING_ONLY) {
352                 missing_only = TRUE;
353                 LOGD("updating missed attr only");
354         }
355
356         if (flag & ATTR_ALL) {
357                 all = TRUE;
358                 has_duration = FALSE;
359                 has_video_attrs = FALSE;
360                 has_audio_attrs = FALSE;
361                 has_bitrate = FALSE;
362
363                 LOGD("updating all attrs");
364         }
365
366         if (missing_only && all) {
367                 LOGW("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
368                 missing_only = FALSE;
369         }
370
371         if ((flag & ATTR_DURATION) ||   (!has_duration && missing_only) || all) {
372                 LOGD("try to update duration");
373                 has_duration = FALSE;
374
375                 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
376                         player->duration = dur_nsec;
377                         LOGW("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
378                 }
379
380                 if (player->duration < 0) {
381                         LOGW("duration : %lld is Non-Initialized !!! \n",player->duration);
382                         player->duration = 0;
383                 }
384
385                 /* try to get streaming service type */
386                 stream_service_type = __mmplayer_get_stream_service_type(player);
387                 mm_attrs_set_int_by_name(attrs, "streaming_type", stream_service_type);
388
389                 /* check duration is OK */
390                 if (dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING(player)) {
391                         /* FIXIT : find another way to get duration here. */
392                         LOGE("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
393                 } else {
394                         /*update duration */
395                         mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
396                         has_duration = TRUE;
397                 }
398         }
399
400         if ((flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all) {
401                 /* update audio params
402                 NOTE : We need original audio params and it can be only obtained from src pad of audio
403                 decoder. Below code only valid when we are not using 'resampler' just before
404                 'audioconverter'. */
405
406                 LOGD("try to update audio attrs");
407                 has_audio_attrs = FALSE;
408
409                 if (player->pipeline->audiobin &&
410                          player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
411                         GstCaps *caps_a = NULL;
412                         GstPad* pad = NULL;
413                         gint samplerate = 0, channels = 0;
414
415                         pad = gst_element_get_static_pad(
416                                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink");
417
418                         if (pad) {
419                                 caps_a = gst_pad_get_current_caps(pad);
420
421                                 if (caps_a) {
422                                         p = gst_caps_get_structure(caps_a, 0);
423
424                                         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
425
426                                         gst_structure_get_int(p, "rate", &samplerate);
427                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
428
429                                         gst_structure_get_int(p, "channels", &channels);
430                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
431
432                                         SECURE_LOGD("samplerate : %d    channels : %d", samplerate, channels);
433
434                                         gst_caps_unref(caps_a);
435                                         caps_a = NULL;
436
437                                         has_audio_attrs = TRUE;
438                                 } else
439                                         LOGW("not ready to get audio caps");
440
441                                 gst_object_unref(pad);
442                         } else
443                                 LOGW("failed to get pad from audiosink");
444                 }
445         }
446
447         if ((flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all) {
448                 LOGD("try to update video attrs");
449                 has_video_attrs = FALSE;
450
451                 if (player->pipeline->videobin &&
452                          player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
453                         GstCaps *caps_v = NULL;
454                         GstPad* pad = NULL;
455                         gint tmpNu, tmpDe;
456                         gint width, height;
457
458                         pad = gst_element_get_static_pad(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink");
459                         if (pad) {
460                                 caps_v = gst_pad_get_current_caps(pad);
461
462                                 /* Use v_stream_caps, if fail to get video_sink sink pad*/
463                                 if (!caps_v && player->v_stream_caps) {
464                                         caps_v = player->v_stream_caps;
465                                         gst_caps_ref(caps_v);
466                                 }
467
468                                 if (caps_v) {
469                                         p = gst_caps_get_structure(caps_v, 0);
470                                         gst_structure_get_int(p, "width", &width);
471                                         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
472
473                                         gst_structure_get_int(p, "height", &height);
474                                         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
475
476                                         gst_structure_get_fraction(p, "framerate", &tmpNu, &tmpDe);
477
478                                         SECURE_LOGD("width : %d     height : %d", width, height);
479
480                                         gst_caps_unref(caps_v);
481                                         caps_v = NULL;
482
483                                         if (tmpDe > 0) {
484                                                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
485                                                 SECURE_LOGD("fps : %d", tmpNu / tmpDe);
486                                         }
487
488                                         has_video_attrs = TRUE;
489                                 } else
490                                         LOGD("no negitiated caps from videosink");
491                                 gst_object_unref(pad);
492                                 pad = NULL;
493                         } else
494                                 LOGD("no videosink sink pad");
495                 }
496         }
497
498
499         if ((flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all) {
500                 has_bitrate = FALSE;
501
502                 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
503                 if (player->duration) {
504                         guint64 data_size = 0;
505
506                         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
507                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
508
509                                 if (stat(path, &sb) == 0)
510                                         data_size = (guint64)sb.st_size;
511                         } else if (MMPLAYER_IS_HTTP_STREAMING(player))
512                                 data_size = player->http_content_size;
513                         LOGD("try to update bitrate : data_size = %lld", data_size);
514
515                         if (data_size) {
516                                 guint64 bitrate = 0;
517                                 guint64 msec_dur = 0;
518
519                                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
520                                 bitrate = data_size * 8 * 1000 / msec_dur;
521                                 SECURE_LOGD("file size : %u, video bitrate = %llu", data_size, bitrate);
522                                 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
523
524                                 has_bitrate = TRUE;
525                         }
526
527                         if (MMPLAYER_IS_RTSP_STREAMING(player)) {
528                                 if (player->total_bitrate) {
529                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
530                                         has_bitrate = TRUE;
531                                 }
532                         }
533                 }
534         }
535
536         /* validate all */
537         if (mmf_attrs_commit(attrs)) {
538                 LOGE("failed to update attributes\n");
539                 return FALSE;
540         }
541
542         MMPLAYER_FLEAVE();
543
544         return TRUE;
545 }
546
547 static gboolean __mmplayer_get_stream_service_type(mm_player_t* player)
548 {
549         gint streaming_type = STREAMING_SERVICE_NONE;
550
551         MMPLAYER_FENTER();
552
553         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
554                         player->pipeline &&
555                         player->pipeline->mainbin &&
556                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
557                         FALSE);
558
559         /* streaming service type if streaming */
560         if (!MMPLAYER_IS_STREAMING(player))
561                 return STREAMING_SERVICE_NONE;
562
563         if (MMPLAYER_IS_HTTP_STREAMING(player))
564                 streaming_type = (player->duration == 0) ?
565                         STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
566
567         switch (streaming_type) {
568         case STREAMING_SERVICE_LIVE:
569                 LOGD("it's live streaming");
570                 break;
571         case STREAMING_SERVICE_VOD:
572                 LOGD("it's vod streaming");
573                 break;
574         default:
575                 LOGE("should not get here");
576         }
577
578         player->streaming_type = streaming_type;
579         MMPLAYER_FLEAVE();
580
581         return streaming_type;
582 }
583
584
585 /* this function sets the player state and also report
586  * it to applicaton by calling callback function
587  */
588 int
589 __mmplayer_set_state(mm_player_t* player, int state) // @
590 {
591         MMMessageParamType msg = {0, };
592         int sound_result = MM_ERROR_NONE;
593         gboolean post_bos = FALSE;
594         gboolean interrupted_by_focus = FALSE;
595         gboolean interrupted_by_resource = FALSE;
596
597         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
598
599         if (MMPLAYER_CURRENT_STATE(player) == state) {
600                 LOGW("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
601                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
602                 return MM_ERROR_NONE;
603         }
604
605         /* update player states */
606         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
607         MMPLAYER_CURRENT_STATE(player) = state;
608
609         /* FIXIT : it's better to do like below code
610         if (MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player))
611                         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
612         and add more code to handling PENDING_STATE.
613         */
614         if (MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player))
615                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
616
617         /* print state */
618         MMPLAYER_PRINT_STATE(player);
619
620         /* do some FSM stuffs before posting new state to application  */
621         interrupted_by_focus = player->sound_focus.by_asm_cb;
622         interrupted_by_resource = player->resource_manager.by_rm_cb;
623
624         switch (MMPLAYER_CURRENT_STATE(player)) {
625         case MM_PLAYER_STATE_NULL:
626         case MM_PLAYER_STATE_READY:
627                 {
628                         if (player->cmd == MMPLAYER_COMMAND_STOP) {
629                                 sound_result = _mmplayer_sound_release_focus(&player->sound_focus);
630                                 if (sound_result != MM_ERROR_NONE) {
631                                         LOGE("failed to release sound focus\n");
632                                         return MM_ERROR_POLICY_INTERNAL;
633                                 }
634                         }
635                 }
636                 break;
637
638         case MM_PLAYER_STATE_PAUSED:
639                 {
640                          if (!player->sent_bos) {
641                                 int found = 0;
642                                 #define MMPLAYER_MAX_SOUND_PRIORITY     3
643
644                                 /* rtsp case, get content attrs by GstMessage */
645                                 if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
646                                         /* it's first time to update all content attrs. */
647                                         _mmplayer_update_content_attrs( player, ATTR_ALL );
648                                 }
649
650                                 /* set max sound priority to keep own sound and not to mute other's one */
651                                 mm_attrs_get_int_by_name(player->attrs, "content_video_found", &found);
652                                 if (found) {
653                                         mm_attrs_get_int_by_name(player->attrs, "content_audio_found", &found);
654                                         if (found) {
655                                                 LOGD("set max audio priority");
656                                                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "priority", MMPLAYER_MAX_SOUND_PRIORITY, NULL);
657                                         }
658                                 }
659
660                          }
661
662                         /* add audio callback probe if condition is satisfied */
663                         if (!player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
664                                 __mmplayer_configure_audio_callback(player);
665                                 /* FIXIT : handle return value */
666
667                         if (!MMPLAYER_IS_STREAMING(player) || (player->streamer && !player->streamer->is_buffering)) {
668                                 sound_result = _mmplayer_sound_release_focus(&player->sound_focus);
669                                 if (sound_result != MM_ERROR_NONE) {
670                                         LOGE("failed to release sound focus\n");
671                                         return MM_ERROR_POLICY_INTERNAL;
672                                 }
673                         }
674                 }
675                 break;
676
677         case MM_PLAYER_STATE_PLAYING:
678                 {
679                         /* try to get content metadata */
680                         if (!player->sent_bos) {
681                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
682                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
683                                  * legacy mmfw-player api */
684                                 _mmplayer_update_content_attrs(player, ATTR_MISSING_ONLY);
685                         }
686
687                         if ((player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME)) {
688                                 if (!player->sent_bos)
689                                         __mmplayer_handle_missed_plugin(player);
690                                 sound_result = _mmplayer_sound_acquire_focus(&player->sound_focus);
691                                 if (sound_result != MM_ERROR_NONE) {
692                                         // FIXME : need to check history
693                                         if (player->pipeline->videobin) {
694                                                 MMMessageParamType msg = {0, };
695
696                                                 LOGE("failed to go ahead because of video conflict\n");
697
698                                                 msg.union_type = MM_MSG_UNION_CODE;
699                                                 msg.code = MM_PLAYER_FOCUS_CHANGED_BY_RESOURCE_CONFLICT;
700                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
701
702                                                 _mmplayer_unrealize((MMHandleType)player);
703                                         } else {
704                                                 LOGE("failed to play by sound focus error : 0x%X\n", sound_result);
705                                                 _mmplayer_pause((MMHandleType)player);
706                                         }
707
708                                         return MM_ERROR_POLICY_INTERNAL;
709                                 }
710                         }
711
712                         if (player->resumed_by_rewind && player->playback_rate < 0.0) {
713                                 /* initialize because auto resume is done well. */
714                                 player->resumed_by_rewind = FALSE;
715                                 player->playback_rate = 1.0;
716                         }
717
718                         if (!player->sent_bos) {
719                                 /* check audio codec field is set or not
720                                  * we can get it from typefinder or codec's caps.
721                                  */
722                                 gchar *audio_codec = NULL;
723                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
724
725                                 /* The codec format can't be sent for audio only case like amr, mid etc.
726                                  * Because, parser don't make related TAG.
727                                  * So, if it's not set yet, fill it with found data.
728                                  */
729                                 if (!audio_codec) {
730                                         if (g_strrstr(player->type, "audio/midi"))
731                                                 audio_codec = g_strdup("MIDI");
732                                         else if (g_strrstr(player->type, "audio/x-amr"))
733                                                 audio_codec = g_strdup("AMR");
734                                         else if (g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion= (int)1"))
735                                                 audio_codec = g_strdup("AAC");
736                                         else
737                                                 audio_codec = g_strdup("unknown");
738                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
739
740                                         MMPLAYER_FREEIF(audio_codec);
741                                         mmf_attrs_commit(player->attrs);
742                                         LOGD("set audio codec type with caps\n");
743                                 }
744
745                                 post_bos = TRUE;
746                         }
747                 }
748                 break;
749
750         case MM_PLAYER_STATE_NONE:
751         default:
752                 LOGW("invalid target state, there is nothing to do.\n");
753                 break;
754         }
755
756
757         /* post message to application */
758         if (MMPLAYER_TARGET_STATE(player) == state) {
759                 /* fill the message with state of player */
760                 msg.union_type = MM_MSG_UNION_STATE;
761                 msg.state.previous = MMPLAYER_PREV_STATE(player);
762                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
763
764                 LOGD("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
765
766                 /* state changed by focus or resource callback */
767                 if (interrupted_by_focus || interrupted_by_resource) {
768                         if (interrupted_by_focus)
769                                 msg.state.code = player->sound_focus.focus_changed_msg;
770                         else if (interrupted_by_resource)
771                                 msg.state.code = MM_PLAYER_FOCUS_CHANGED_BY_RESOURCE_CONFLICT;
772                         MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
773                 } else { /* state changed by usecase */
774                         MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_CHANGED, &msg);
775                 }
776         } else {
777                 LOGD("intermediate state, do nothing.\n");
778                 MMPLAYER_PRINT_STATE(player);
779                 return MM_ERROR_NONE;
780         }
781
782         if (post_bos) {
783                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BEGIN_OF_STREAM, NULL);
784                 player->sent_bos = TRUE;
785         }
786
787         return MM_ERROR_NONE;
788 }
789
790 static gpointer __mmplayer_next_play_thread(gpointer data)
791 {
792         mm_player_t* player = (mm_player_t*) data;
793         MMPlayerGstElement *mainbin = NULL;
794
795         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
796
797         MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
798         while (!player->next_play_thread_exit) {
799                 LOGD("next play thread started. waiting for signal.\n");
800                 MMPLAYER_NEXT_PLAY_THREAD_WAIT(player);
801
802                 LOGD("reconfigure pipeline for gapless play.\n");
803
804                 if (player->next_play_thread_exit) {
805                         if (player->gapless.reconfigure) {
806                                 player->gapless.reconfigure = false;
807                                 MMPLAYER_PLAYBACK_UNLOCK(player);
808                         }
809                         LOGD("exiting gapless play thread\n");
810                         break;
811                 }
812
813                 mainbin = player->pipeline->mainbin;
814
815                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
816                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
817                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
818                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
819                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
820
821                 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
822         }
823         MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
824
825         return NULL;
826 }
827
828 static gpointer __mmplayer_repeat_thread(gpointer data)
829 {
830         mm_player_t* player = (mm_player_t*) data;
831         gboolean ret_value = FALSE;
832         MMHandleType attrs = 0;
833         gint count = 0;
834
835         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
836
837         MMPLAYER_REPEAT_THREAD_LOCK(player);
838         while (!player->repeat_thread_exit) {
839                 LOGD("repeat thread started. waiting for signal.\n");
840                 MMPLAYER_REPEAT_THREAD_WAIT(player);
841
842                 if (player->repeat_thread_exit) {
843                         LOGD("exiting repeat thread\n");
844                         break;
845                 }
846
847
848                 /* lock */
849                 MMPLAYER_CMD_LOCK(player);
850
851                 attrs = MMPLAYER_GET_ATTRS(player);
852
853                 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE) {
854                         LOGE("can not get play count\n");
855                         MMPLAYER_CMD_UNLOCK(player);
856                         break;
857                 }
858
859                 if (player->section_repeat) {
860                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
861                 } else {
862                         if (player->playback_rate < 0.0) {
863                                 player->resumed_by_rewind = TRUE;
864                                 _mmplayer_set_mute((MMHandleType)player, 0);
865                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_RESUMED_BY_REW, NULL);
866                         }
867
868                         ret_value = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
869                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
870                                 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
871
872                         /* initialize */
873                         player->sent_bos = FALSE;
874                 }
875
876                 if (!ret_value) {
877                         LOGE("failed to set position to zero for rewind\n");
878                         MMPLAYER_CMD_UNLOCK(player);
879                         continue;
880                 }
881
882                 /* decrease play count */
883                 if (count > 1) {
884                         /* we successeded to rewind. update play count and then wait for next EOS */
885                         count--;
886
887                         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
888
889                         /* commit attribute */
890                         if (mmf_attrs_commit(attrs))
891                                 LOGE("failed to commit attribute\n");
892                 }
893
894                 /* unlock */
895                 MMPLAYER_CMD_UNLOCK(player);
896         }
897
898         MMPLAYER_REPEAT_THREAD_UNLOCK(player);
899         return NULL;
900 }
901
902 static void
903 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
904 {
905         MMHandleType attrs = 0;
906         guint64 data_size = 0;
907         gchar* path = NULL;
908         unsigned long pos_msec = 0;
909         struct stat sb;
910
911         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
912
913         __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_msec);       // update last_position
914
915         attrs = MMPLAYER_GET_ATTRS(player);
916         if (!attrs) {
917                 LOGE("fail to get attributes.\n");
918                 return;
919         }
920
921         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
922                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
923
924                 if (stat(path, &sb) == 0)
925                         data_size = (guint64)sb.st_size;
926         } else if (MMPLAYER_IS_HTTP_STREAMING(player))
927                 data_size = player->http_content_size;
928
929         __mm_player_streaming_buffering(player->streamer,
930                                                                                 buffering_msg,
931                                                                                 data_size,
932                                                                                 player->last_position,
933                                                                                 player->duration);
934
935         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
936
937         return;
938 }
939
940 static int
941 __mmplayer_handle_buffering_message(mm_player_t* player)
942 {
943         int ret = MM_ERROR_NONE;
944         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
945         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
946         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
947         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
948
949         if (!player || !player->streamer || (MMPLAYER_IS_LIVE_STREAMING(player) && MMPLAYER_IS_RTSP_STREAMING(player))) {
950                 LOGW("do nothing for buffering msg\n");
951                 ret = MM_ERROR_PLAYER_INVALID_STATE;
952                 goto exit;
953         }
954
955         prev_state = MMPLAYER_PREV_STATE(player);
956         current_state = MMPLAYER_CURRENT_STATE(player);
957         target_state = MMPLAYER_TARGET_STATE(player);
958         pending_state = MMPLAYER_PENDING_STATE(player);
959
960         LOGD("player state : prev %s, current %s, pending %s, target %s, buffering %d",
961                 MMPLAYER_STATE_GET_NAME(prev_state),
962                 MMPLAYER_STATE_GET_NAME(current_state),
963                 MMPLAYER_STATE_GET_NAME(pending_state),
964                 MMPLAYER_STATE_GET_NAME(target_state),
965                 player->streamer->is_buffering);
966
967         if (!player->streamer->is_buffering) {
968                 /* NOTE : if buffering has done, player has to go to target state. */
969                 switch (target_state) {
970                 case MM_PLAYER_STATE_PAUSED:
971                         {
972                                 switch (pending_state) {
973                                 case MM_PLAYER_STATE_PLAYING:
974                                         __gst_pause(player, TRUE);
975                                         break;
976
977                                 case MM_PLAYER_STATE_PAUSED:
978                                         LOGD("player is already going to paused state, there is nothing to do.\n");
979                                         break;
980
981                                 case MM_PLAYER_STATE_NONE:
982                                 case MM_PLAYER_STATE_NULL:
983                                 case MM_PLAYER_STATE_READY:
984                                 default:
985                                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
986                                         break;
987                                 }
988                         }
989                         break;
990
991                 case MM_PLAYER_STATE_PLAYING:
992                         {
993                                 switch (pending_state) {
994                                 case MM_PLAYER_STATE_NONE:
995                                         {
996                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
997                                                         __gst_resume(player, TRUE);
998                                         }
999                                         break;
1000
1001                                 case MM_PLAYER_STATE_PAUSED:
1002                                         /* NOTE: It should be worked as asynchronously.
1003                                          * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1004                                          */
1005                                         __gst_resume(player, TRUE);
1006                                         break;
1007
1008                                 case MM_PLAYER_STATE_PLAYING:
1009                                         LOGD("player is already going to playing state, there is nothing to do.\n");
1010                                         break;
1011
1012                                 case MM_PLAYER_STATE_NULL:
1013                                 case MM_PLAYER_STATE_READY:
1014                                 default:
1015                                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
1016                                         break;
1017                                 }
1018                         }
1019                         break;
1020
1021                 case MM_PLAYER_STATE_NULL:
1022                 case MM_PLAYER_STATE_READY:
1023                 case MM_PLAYER_STATE_NONE:
1024                 default:
1025                         LOGW("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state));
1026                         break;
1027                 }
1028         } else {
1029                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1030                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
1031                  */
1032                 switch (pending_state) {
1033                 case MM_PLAYER_STATE_NONE:
1034                         {
1035                                 if (current_state != MM_PLAYER_STATE_PAUSED) {
1036                                         /* rtsp streaming pause makes rtsp server stop sending data. */
1037                                         if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
1038                                                 LOGD("set pause state during buffering\n");
1039                                                 __gst_pause( player, TRUE );
1040                                         }
1041                                 }
1042                         }
1043                         break;
1044
1045                 case MM_PLAYER_STATE_PLAYING:
1046                         /* rtsp streaming pause makes rtsp server stop sending data. */
1047                         if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
1048                                 __gst_pause ( player, TRUE );
1049                         }
1050                         break;
1051
1052                 case MM_PLAYER_STATE_PAUSED:
1053                         break;
1054
1055                 case MM_PLAYER_STATE_NULL:
1056                 case MM_PLAYER_STATE_READY:
1057                 default:
1058                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
1059                         break;
1060                 }
1061         }
1062
1063 exit:
1064         return ret;
1065 }
1066
1067 static void
1068 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
1069 {
1070         MMPlayerGstElement *textbin;
1071         MMPLAYER_FENTER();
1072
1073         MMPLAYER_RETURN_IF_FAIL(player &&
1074                                         player->pipeline &&
1075                                         player->pipeline->textbin);
1076
1077         MMPLAYER_RETURN_IF_FAIL(player->pipeline->textbin[MMPLAYER_T_IDENTITY].gst);
1078
1079         textbin = player->pipeline->textbin;
1080
1081         if (is_drop) {
1082                 LOGD("Drop subtitle text after getting EOS\n");
1083
1084                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
1085                 g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1086
1087                 player->is_subtitle_force_drop = TRUE;
1088         } else {
1089                 if (player->is_subtitle_force_drop == TRUE) {
1090                         LOGD("Enable subtitle data path without drop\n");
1091
1092                         g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1093                         g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
1094
1095                         LOGD("non-connected with external display");
1096
1097                         player->is_subtitle_force_drop = FALSE;
1098                 }
1099         }
1100 }
1101
1102 static gboolean
1103 __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
1104 {
1105         mm_player_t* player = (mm_player_t*) data;
1106         gboolean ret = TRUE;
1107         static gboolean async_done = FALSE;
1108
1109         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
1110         MMPLAYER_RETURN_VAL_IF_FAIL(msg && GST_IS_MESSAGE(msg), FALSE);
1111
1112         switch (GST_MESSAGE_TYPE(msg)) {
1113         case GST_MESSAGE_UNKNOWN:
1114                 LOGD("unknown message received\n");
1115                 break;
1116
1117         case GST_MESSAGE_EOS:
1118                 {
1119                         MMHandleType attrs = 0;
1120                         gint count = 0;
1121
1122                         LOGD("GST_MESSAGE_EOS received\n");
1123
1124                         /* NOTE : EOS event is comming multiple time. watch out it */
1125                         /* check state. we only process EOS when pipeline state goes to PLAYING */
1126                         if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)) {
1127                                 LOGD("EOS received on non-playing state. ignoring it\n");
1128                                 break;
1129                         }
1130
1131                         if (player->pipeline) {
1132                                 if (player->pipeline->textbin)
1133                                         __mmplayer_drop_subtitle(player, TRUE);
1134
1135                                 if ((player->audio_stream_cb) && (player->set_mode.pcm_extraction) && (!player->audio_stream_render_cb_ex)) {
1136                                         GstPad *pad = NULL;
1137
1138                                         pad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1139
1140                                         LOGD("release audio callback\n");
1141
1142                                         /* release audio callback */
1143                                         gst_pad_remove_probe(pad, player->audio_cb_probe_id);
1144                                         player->audio_cb_probe_id = 0;
1145                                         /* audio callback should be free because it can be called even though probe remove.*/
1146                                         player->audio_stream_cb = NULL;
1147                                         player->audio_stream_cb_user_param = NULL;
1148
1149                                 }
1150                         }
1151                         if ((player->audio_stream_render_cb_ex) && (!player->audio_stream_sink_sync))
1152                                 __mmplayer_audio_stream_clear_buffer(player, TRUE);
1153
1154                         /* rewind if repeat count is greater then zero */
1155                         /* get play count */
1156                         attrs = MMPLAYER_GET_ATTRS(player);
1157
1158                         if (attrs) {
1159                                 gboolean smooth_repeat = FALSE;
1160
1161                                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1162                                 mm_attrs_get_int_by_name(attrs, "profile_smooth_repeat", &smooth_repeat);
1163
1164                                 player->play_count = count;
1165
1166                                 LOGD("remaining play count: %d, playback rate: %f\n", count, player->playback_rate);
1167
1168                                 if (count > 1 || count == -1 || player->playback_rate < 0.0) /* default value is 1 */ {
1169                                         if (smooth_repeat) {
1170                                                 LOGD("smooth repeat enabled. seeking operation will be excuted in new thread\n");
1171
1172                                                 MMPLAYER_REPEAT_THREAD_SIGNAL(player);
1173
1174                                                 break;
1175                                         } else {
1176                                                 gint ret_value = 0;
1177
1178                                                 if (player->section_repeat) {
1179                                                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1180                                                 } else {
1181                                                         if (player->playback_rate < 0.0) {
1182                                                                 player->resumed_by_rewind = TRUE;
1183                                                                 _mmplayer_set_mute((MMHandleType)player, 0);
1184                                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_RESUMED_BY_REW, NULL);
1185                                                         }
1186
1187                                                         __mmplayer_handle_eos_delay(player, player->ini.delay_before_repeat);
1188
1189                                                         /* initialize */
1190                                                         player->sent_bos = FALSE;
1191                                                 }
1192
1193                                                 if (MM_ERROR_NONE != ret_value)
1194                                                         LOGE("failed to set position to zero for rewind\n");
1195
1196                                                 /* not posting eos when repeating */
1197                                                 break;
1198                                         }
1199                                 }
1200                         }
1201
1202                         if (player->pipeline)
1203                                 MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-eos");
1204
1205                         /* post eos message to application */
1206                         __mmplayer_handle_eos_delay(player, player->ini.eos_delay);
1207
1208                         /* reset last position */
1209                         player->last_position = 0;
1210                 }
1211                 break;
1212
1213         case GST_MESSAGE_ERROR:
1214                 {
1215                         GError *error = NULL;
1216                         gchar* debug = NULL;
1217
1218                         /* generating debug info before returning error */
1219                         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-error");
1220
1221                         /* get error code */
1222                         gst_message_parse_error(msg, &error, &debug);
1223
1224                         if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
1225                                 /* Note : the streaming error from the streaming source is handled
1226                                  *   using __mmplayer_handle_streaming_error.
1227                                  */
1228                                 __mmplayer_handle_streaming_error(player, msg);
1229
1230                                 /* dump state of all element */
1231                                 __mmplayer_dump_pipeline_state(player);
1232                         } else {
1233                                 /* traslate gst error code to msl error code. then post it
1234                                  * to application if needed
1235                                  */
1236                                 __mmplayer_handle_gst_error(player, msg, error);
1237
1238                                 if (debug)
1239                                         LOGE("error debug : %s", debug);
1240                         }
1241
1242                         if (MMPLAYER_IS_HTTP_PD(player))
1243                                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
1244
1245                         MMPLAYER_FREEIF(debug);
1246                         g_error_free(error);
1247                 }
1248                 break;
1249
1250         case GST_MESSAGE_WARNING:
1251                 {
1252                         char* debug = NULL;
1253                         GError* error = NULL;
1254
1255                         gst_message_parse_warning(msg, &error, &debug);
1256
1257                         LOGD("warning : %s\n", error->message);
1258                         LOGD("debug : %s\n", debug);
1259
1260                         MMPLAYER_POST_MSG(player, MM_MESSAGE_WARNING, NULL);
1261
1262                         MMPLAYER_FREEIF(debug);
1263                         g_error_free(error);
1264                 }
1265                 break;
1266
1267         case GST_MESSAGE_TAG:
1268                 {
1269                         LOGD("GST_MESSAGE_TAG\n");
1270                         if (!__mmplayer_gst_extract_tag_from_msg(player, msg))
1271                                 LOGW("failed to extract tags from gstmessage\n");
1272                 }
1273                 break;
1274
1275         case GST_MESSAGE_BUFFERING:
1276                 {
1277                         MMMessageParamType msg_param = {0, };
1278                         int bRet = MM_ERROR_NONE;
1279
1280                         if (!MMPLAYER_IS_STREAMING(player))
1281                                 break;
1282
1283                         /* ignore the prev buffering message */
1284                         if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (player->streamer->is_buffering_done == TRUE)) {
1285                                 gint buffer_percent = 0;
1286
1287                                 gst_message_parse_buffering(msg, &buffer_percent);
1288
1289                                 if (buffer_percent == MAX_BUFFER_PERCENT) {
1290                                         LOGD("Ignored all the previous buffering msg!(got %d%%)\n", buffer_percent);
1291                                         player->streamer->is_buffering_done = FALSE;
1292                                 }
1293
1294                                 break;
1295                         }
1296
1297                         MMPLAYER_CMD_LOCK(player);
1298                         __mmplayer_update_buffer_setting(player, msg);
1299
1300                         bRet = __mmplayer_handle_buffering_message(player);
1301
1302                         if (bRet == MM_ERROR_NONE) {
1303                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1304                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1305
1306                                 if (MMPLAYER_IS_RTSP_STREAMING(player) &&
1307                                         player->pending_resume &&
1308                                         (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) {
1309
1310                                         player->is_external_subtitle_added_now = FALSE;
1311                                         player->pending_resume = FALSE;
1312                                         _mmplayer_resume((MMHandleType)player);
1313                                 }
1314
1315                                 if (MMPLAYER_IS_RTSP_STREAMING(player) &&
1316                                         (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) {
1317
1318                                         if (player->doing_seek) {
1319                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
1320                                                         player->doing_seek = FALSE;
1321                                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1322                                                 } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
1323                                                         async_done = TRUE;
1324                                                 }
1325                                         }
1326                                 }
1327                         } else if (bRet == MM_ERROR_PLAYER_INVALID_STATE) {
1328                                 if (!player->streamer) {
1329                                         LOGW("player->streamer is NULL, so discarding the buffering percent update\n");
1330                                         MMPLAYER_CMD_UNLOCK(player);
1331                                         break;
1332                                 }
1333
1334                                 if ((MMPLAYER_IS_LIVE_STREAMING(player)) && (MMPLAYER_IS_RTSP_STREAMING(player))) {
1335
1336                                         LOGD("player->last_position=%lld , player->streamer->buffering_percent=%d \n",
1337                                                         GST_TIME_AS_SECONDS(player->last_position), player->streamer->buffering_percent);
1338
1339                                         if ((GST_TIME_AS_SECONDS(player->last_position) <= 0) && (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED)) {
1340                                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1341                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_BUFFERING, &msg_param );
1342                                         } else {
1343                                                 LOGD("Not updating Buffering Message for Live RTSP case !!!\n");
1344                                         }
1345                                 } else {
1346                                         msg_param.connection.buffering = player->streamer->buffering_percent;
1347                                         MMPLAYER_POST_MSG( player, MM_MESSAGE_BUFFERING, &msg_param );
1348                                 }
1349                         }
1350                         MMPLAYER_CMD_UNLOCK(player);
1351                 }
1352                 break;
1353
1354         case GST_MESSAGE_STATE_CHANGED:
1355                 {
1356                         MMPlayerGstElement *mainbin;
1357                         const GValue *voldstate, *vnewstate, *vpending;
1358                         GstState oldstate = GST_STATE_NULL;
1359                         GstState newstate = GST_STATE_NULL;
1360                         GstState pending = GST_STATE_NULL;
1361
1362                         if (!(player->pipeline && player->pipeline->mainbin)) {
1363                                 LOGE("player pipeline handle is null");
1364                                 break;
1365                         }
1366
1367                         mainbin = player->pipeline->mainbin;
1368
1369                         /* we only handle messages from pipeline */
1370                         if (msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst)
1371                                 break;
1372
1373                         /* get state info from msg */
1374                         voldstate = gst_structure_get_value(gst_message_get_structure(msg), "old-state");
1375                         vnewstate = gst_structure_get_value(gst_message_get_structure(msg), "new-state");
1376                         vpending = gst_structure_get_value(gst_message_get_structure(msg), "pending-state");
1377
1378                         if (!voldstate || !vnewstate) {
1379                                 LOGE("received msg has wrong format.");
1380                                 break;
1381                         }
1382
1383                         oldstate = (GstState)voldstate->data[0].v_int;
1384                         newstate = (GstState)vnewstate->data[0].v_int;
1385                         if (vpending)
1386                                 pending = (GstState)vpending->data[0].v_int;
1387
1388                         LOGD("state changed [%s] : %s ---> %s     final : %s\n",
1389                                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
1390                                 gst_element_state_get_name((GstState)oldstate),
1391                                 gst_element_state_get_name((GstState)newstate),
1392                                 gst_element_state_get_name((GstState)pending));
1393
1394                         if (newstate == GST_STATE_PLAYING) {
1395                                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) && (player->pending_seek.is_pending)) {
1396
1397                                         int retVal = MM_ERROR_NONE;
1398                                         LOGD("trying to play from (%lu) pending position\n", player->pending_seek.pos);
1399
1400                                         retVal = __gst_set_position( player, player->pending_seek.format, player->pending_seek.pos, TRUE );
1401
1402                                         if (MM_ERROR_NONE != retVal)
1403                                                 LOGE("failed to seek pending postion. just keep staying current position.\n");
1404
1405                                         player->pending_seek.is_pending = FALSE;
1406                                 }
1407                         }
1408
1409                         if (oldstate == newstate) {
1410                                 LOGD("pipeline reports state transition to old state");
1411                                 break;
1412                         }
1413
1414                         switch (newstate) {
1415                         case GST_STATE_VOID_PENDING:
1416                                 break;
1417
1418                         case GST_STATE_NULL:
1419                                 break;
1420
1421                         case GST_STATE_READY:
1422                                 break;
1423
1424                         case GST_STATE_PAUSED:
1425                                 {
1426                                         gboolean prepare_async = FALSE;
1427
1428                                         if (!player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
1429                                                 __mmplayer_configure_audio_callback(player);
1430
1431                                         if (!player->sent_bos && oldstate == GST_STATE_READY) {
1432                                                 // managed prepare async case
1433                                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
1434                                                 LOGD("checking prepare mode for async transition - %d", prepare_async);
1435                                         }
1436
1437                                         if (MMPLAYER_IS_STREAMING(player) || MMPLAYER_IS_MS_BUFF_SRC(player) || prepare_async) {
1438                                                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
1439
1440                                                 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
1441                                                         __mm_player_streaming_set_content_bitrate(player->streamer,
1442                                                                 player->total_maximum_bitrate, player->total_bitrate);
1443                                         }
1444                                 }
1445                                 break;
1446
1447                         case GST_STATE_PLAYING:
1448                                 {
1449                                         if (MMPLAYER_IS_STREAMING(player)) {
1450                                                 // managed prepare async case when buffering is completed
1451                                                 // pending state should be reset otherwise, it's still playing even though it's resumed after bufferging.
1452                                                 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
1453                                                         (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
1454                                                         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
1455
1456                                                 if (MMPLAYER_IS_RTSP_STREAMING(player) && (MMPLAYER_IS_LIVE_STREAMING(player))) {
1457
1458                                                         LOGD("Current Buffering Percent = %d",player->streamer->buffering_percent);
1459                                                         if (player->streamer->buffering_percent < 100) {
1460
1461                                                                 MMMessageParamType msg_param = {0, };
1462                                                                 LOGW("Posting Buffering Completed Message to Application !!!");
1463
1464                                                                 msg_param.connection.buffering = 100;
1465                                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param );
1466                                                         }
1467                                                 }
1468                                         }
1469
1470                                         if (player->gapless.stream_changed) {
1471                                                 _mmplayer_update_content_attrs(player, ATTR_ALL);
1472                                                 player->gapless.stream_changed = FALSE;
1473                                         }
1474
1475                                         if (player->doing_seek && async_done) {
1476                                                 player->doing_seek = FALSE;
1477                                                 async_done = FALSE;
1478                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1479                                         }
1480                                 }
1481                                 break;
1482
1483                         default:
1484                                 break;
1485                         }
1486                 }
1487                 break;
1488
1489         case GST_MESSAGE_CLOCK_LOST:
1490                         {
1491                                 GstClock *clock = NULL;
1492                                 gboolean need_new_clock = FALSE;
1493
1494                                 gst_message_parse_clock_lost(msg, &clock);
1495                                 LOGD("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
1496
1497                                 if (!player->videodec_linked)
1498                                         need_new_clock = TRUE;
1499                                 else if (!player->ini.use_system_clock)
1500                                         need_new_clock = TRUE;
1501
1502                                 if (need_new_clock) {
1503                                         LOGD("Provide clock is TRUE, do pause->resume\n");
1504                                         __gst_pause(player, FALSE);
1505                                         __gst_resume(player, FALSE);
1506                                 }
1507                         }
1508                         break;
1509
1510         case GST_MESSAGE_NEW_CLOCK:
1511                         {
1512                                 GstClock *clock = NULL;
1513                                 gst_message_parse_new_clock(msg, &clock);
1514                                 LOGD("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
1515                         }
1516                         break;
1517
1518         case GST_MESSAGE_ELEMENT:
1519                         {
1520                                 const gchar *structure_name;
1521                                 gint count = 0;
1522                                 MMHandleType attrs = 0;
1523
1524                                 attrs = MMPLAYER_GET_ATTRS(player);
1525                                 if (!attrs) {
1526                                         LOGE("cannot get content attribute");
1527                                         ret = FALSE;
1528                                         break;
1529                                 }
1530
1531                                 if (gst_message_get_structure(msg) == NULL)
1532                                         break;
1533
1534                                 structure_name = gst_structure_get_name(gst_message_get_structure(msg));
1535                                 if (!structure_name)
1536                                         break;
1537
1538                                 if (!strcmp(structure_name, "prepare-decode-buffers")) {
1539                                         gint num_buffers = 0;
1540                                         gint extra_num_buffers = 0;
1541
1542                                         if (gst_structure_get_int(gst_message_get_structure(msg), "num_buffers", &num_buffers)) {
1543                                                 player->video_num_buffers = num_buffers;
1544                                                 LOGD("video_num_buffers : %d", player->video_num_buffers);
1545                                         }
1546
1547                                         if (gst_structure_get_int(gst_message_get_structure(msg), "extra_num_buffers", &extra_num_buffers)) {
1548                                                 player->video_extra_num_buffers = extra_num_buffers;
1549                                                 LOGD("num_of_vout_extra num buffers : %d", extra_num_buffers);
1550                                         }
1551                                         break;
1552                                 }
1553
1554                                 if (!strcmp(structure_name, "Language_list")) {
1555                                         const GValue *lang_list = NULL;
1556                                         lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
1557                                         if (lang_list != NULL) {
1558                                                 count = g_list_length((GList *)g_value_get_pointer(lang_list));
1559                                                 if (count > 1)
1560                                                         LOGD("Total audio tracks(from parser) = %d \n", count);
1561                                         }
1562                                 }
1563
1564                                 if (!strcmp(structure_name, "Ext_Sub_Language_List")) {
1565                                         const GValue *lang_list = NULL;
1566                                         MMPlayerLangStruct *temp = NULL;
1567
1568                                         lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
1569                                         if (lang_list != NULL) {
1570                                                 count = g_list_length((GList *)g_value_get_pointer(lang_list));
1571                                                 if (count) {
1572                                                         player->subtitle_language_list = (GList *)g_value_get_pointer(lang_list);
1573                                                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
1574                                                         if (mmf_attrs_commit(attrs))
1575                                                           LOGE("failed to commit.\n");
1576                                                         LOGD("Total subtitle tracks = %d \n", count);
1577                                                 }
1578                                                 while (count) {
1579                                                         temp = g_list_nth_data(player->subtitle_language_list, count - 1);
1580                                                         if (temp)
1581                                                                 LOGD("value of lang_key is %s and lang_code is %s",
1582                                                                                         temp->language_key, temp->language_code);
1583                                                         count--;
1584                                                 }
1585                                         }
1586                                 }
1587
1588                                 /* custom message */
1589                                 if (!strcmp(structure_name, "audio_codec_not_supported")) {
1590                                         MMMessageParamType msg_param = {0,};
1591                                         msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
1592                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
1593                                 }
1594
1595                                 /* custom message for RTSP attribute :
1596                                     RTSP case, buffer is not come from server before PLAYING state. However,we have to get attribute after PAUSE state chaged.
1597                                     sdp which has contents info is received when rtsp connection is opened.
1598                                     extract duration ,codec info , resolution from sdp and get it by GstMessage */
1599                                 if (!strcmp(structure_name, "rtspsrc_properties")) {
1600
1601                                         gchar           *audio_codec = NULL;
1602                                         gchar           *video_codec = NULL;
1603                                         gchar           *video_frame_size = NULL;
1604
1605                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_duration", G_TYPE_UINT64, &player->duration, NULL);
1606                                         LOGD("rtsp duration : %lld msec", GST_TIME_AS_MSECONDS(player->duration));
1607                                         __mmplayer_get_stream_service_type(player);
1608                                         mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(player->duration));
1609
1610                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_audio_codec", G_TYPE_STRING, &audio_codec, NULL);
1611                                         LOGD("rtsp_audio_codec : %s", audio_codec);
1612                                         if (audio_codec)
1613                                                 mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1614
1615                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_video_codec", G_TYPE_STRING, &video_codec, NULL);
1616                                         LOGD("rtsp_video_codec : %s", video_codec);
1617                                         if (video_codec)
1618                                                 mm_attrs_set_string_by_name(player->attrs, "content_video_codec", video_codec);
1619
1620                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_video_frame_size", G_TYPE_STRING, &video_frame_size, NULL);
1621                                         LOGD("rtsp_video_frame_size : %s", video_frame_size);
1622                                         if (video_frame_size) {
1623
1624                                                 char *seperator = strchr(video_frame_size, '-');
1625                                                 if (seperator) {
1626
1627                                                         char video_width[10]={0,};
1628                                                         int frame_size_len = strlen(video_frame_size);
1629                                                         int separtor_len = strlen(seperator);
1630
1631                                                         strncpy(video_width,video_frame_size,(frame_size_len-separtor_len));
1632                                                         mm_attrs_set_int_by_name(attrs, "content_video_width", atoi(video_width));
1633
1634                                                         seperator++;
1635                                                         mm_attrs_set_int_by_name(attrs, "content_video_height", atoi(seperator));
1636                                                 }
1637                                         }
1638
1639                                         if (mmf_attrs_commit(attrs))
1640                                                 LOGE("failed to commit.\n");
1641                                 }
1642                         }
1643                         break;
1644
1645         case GST_MESSAGE_DURATION_CHANGED:
1646                 {
1647                         LOGD("GST_MESSAGE_DURATION_CHANGED\n");
1648                         ret = __mmplayer_gst_handle_duration(player, msg);
1649                         if (!ret)
1650                                 LOGW("failed to update duration");
1651                 }
1652
1653                 break;
1654
1655         case GST_MESSAGE_ASYNC_START:
1656                         LOGD("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1657                 break;
1658
1659         case GST_MESSAGE_ASYNC_DONE:
1660                 {
1661                         LOGD("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1662
1663                         /* we only handle messages from pipeline */
1664                         if (msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst)
1665                                 break;
1666
1667                         if (player->doing_seek) {
1668                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
1669                                         player->doing_seek = FALSE;
1670                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1671                                 } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
1672                                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1673                                                 (player->streamer) &&
1674                                                 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
1675                                                 (player->streamer->is_buffering == FALSE)) {
1676                                                 GstQuery *query = NULL;
1677                                                 gboolean busy = FALSE;
1678                                                 gint percent = 0;
1679
1680                                                 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer) {
1681                                                         query = gst_query_new_buffering(GST_FORMAT_PERCENT);
1682                                                         if (gst_element_query(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query))
1683                                                                 gst_query_parse_buffering_percent(query, &busy, &percent);
1684                                                         gst_query_unref(query);
1685
1686                                                         LOGD("buffered percent(%s): %d\n",
1687                                                                 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
1688                                                 }
1689
1690                                                 if (percent >= 100) {
1691                                                         player->streamer->is_buffering = FALSE;
1692                                                         __mmplayer_handle_buffering_message(player);
1693                                                 }
1694                                         }
1695
1696                                         async_done = TRUE;
1697                                 }
1698                         }
1699                 }
1700                 break;
1701
1702         #if 0 /* delete unnecessary logs */
1703         case GST_MESSAGE_REQUEST_STATE:         LOGD("GST_MESSAGE_REQUEST_STATE\n"); break;
1704         case GST_MESSAGE_STEP_START:            LOGD("GST_MESSAGE_STEP_START\n"); break;
1705         case GST_MESSAGE_QOS:                           LOGD("GST_MESSAGE_QOS\n"); break;
1706         case GST_MESSAGE_PROGRESS:                      LOGD("GST_MESSAGE_PROGRESS\n"); break;
1707         case GST_MESSAGE_ANY:                           LOGD("GST_MESSAGE_ANY\n"); break;
1708         case GST_MESSAGE_INFO:                          LOGD("GST_MESSAGE_STATE_DIRTY\n"); break;
1709         case GST_MESSAGE_STATE_DIRTY:           LOGD("GST_MESSAGE_STATE_DIRTY\n"); break;
1710         case GST_MESSAGE_STEP_DONE:                     LOGD("GST_MESSAGE_STEP_DONE\n"); break;
1711         case GST_MESSAGE_CLOCK_PROVIDE:         LOGD("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
1712         case GST_MESSAGE_STRUCTURE_CHANGE:      LOGD("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
1713         case GST_MESSAGE_STREAM_STATUS:         LOGD("GST_MESSAGE_STREAM_STATUS\n"); break;
1714         case GST_MESSAGE_APPLICATION:           LOGD("GST_MESSAGE_APPLICATION\n"); break;
1715         case GST_MESSAGE_SEGMENT_START:         LOGD("GST_MESSAGE_SEGMENT_START\n"); break;
1716         case GST_MESSAGE_SEGMENT_DONE:          LOGD("GST_MESSAGE_SEGMENT_DONE\n"); break;
1717         case GST_MESSAGE_LATENCY:                               LOGD("GST_MESSAGE_LATENCY\n"); break;
1718         #endif
1719
1720         default:
1721                 break;
1722         }
1723
1724         /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
1725          * gst_element_post_message api takes ownership of the message.
1726          */
1727         //gst_message_unref(msg);
1728
1729         return ret;
1730 }
1731
1732 static gboolean
1733 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
1734 {
1735         gint64 bytes = 0;
1736
1737         MMPLAYER_FENTER();
1738
1739         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
1740         MMPLAYER_RETURN_VAL_IF_FAIL(msg, FALSE);
1741
1742         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1743                 (msg->src) && (msg->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst)) {
1744                 LOGD("msg src : [%s]", GST_ELEMENT_NAME(GST_ELEMENT_CAST(msg->src)));
1745
1746                 if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes)) {
1747                         LOGD("data total size of http content: %lld", bytes);
1748                         player->http_content_size = (bytes > 0) ? (bytes) : (0);
1749                 }
1750         } else
1751                 /* handling audio clip which has vbr. means duration is keep changing */
1752                 _mmplayer_update_content_attrs(player, ATTR_DURATION);
1753
1754         MMPLAYER_FLEAVE();
1755
1756         return TRUE;
1757 }
1758
1759
1760 static gboolean
1761 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg) // @
1762 {
1763
1764 /* macro for better code readability */
1765 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
1766 if (gst_tag_list_get_string(tag_list, gsttag, &string)) {\
1767         if (string != NULL) {\
1768                 SECURE_LOGD("update tag string : %s\n", string); \
1769                 mm_attrs_set_string_by_name(attribute, playertag, string); \
1770                 g_free(string);\
1771                 string = NULL;\
1772         } \
1773 }
1774
1775 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
1776 GstSample *sample = NULL;\
1777 if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample)) {\
1778         GstMapInfo info = GST_MAP_INFO_INIT;\
1779         buffer = gst_sample_get_buffer(sample);\
1780         if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) {\
1781                 LOGD("failed to get image data from tag");\
1782                 return FALSE;\
1783         } \
1784         SECURE_LOGD("update album cover data : %p, size : %d\n", info.data, info.size);\
1785         MMPLAYER_FREEIF(player->album_art);\
1786         player->album_art = (gchar *)g_malloc(info.size);\
1787         if (player->album_art) {\
1788                 memcpy(player->album_art, info.data, info.size);\
1789                 mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, info.size);\
1790                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {\
1791                         msg_param.data = (void *)player->album_art;\
1792                         msg_param.size = info.size;\
1793                         MMPLAYER_POST_MSG(player, MM_MESSAGE_IMAGE_BUFFER, &msg_param);\
1794                         SECURE_LOGD("post message image buffer data : %p, size : %d\n", info.data, info.size);\
1795                 } \
1796         } \
1797         gst_buffer_unmap(buffer, &info);\
1798 }
1799
1800 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
1801 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint)) {\
1802         if (v_uint) {\
1803                 if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) {\
1804                         if (player->updated_bitrate_count == 0) \
1805                                 mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
1806                         if (player->updated_bitrate_count < MM_PLAYER_STREAM_COUNT_MAX) {\
1807                                 player->bitrate[player->updated_bitrate_count] = v_uint;\
1808                                 player->total_bitrate += player->bitrate[player->updated_bitrate_count]; \
1809                                 player->updated_bitrate_count++; \
1810                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate);\
1811                                 SECURE_LOGD("update bitrate %d[bps] of stream #%d.\n", v_uint, player->updated_bitrate_count);\
1812                         } \
1813                 } \
1814                 else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) {\
1815                         if (player->updated_maximum_bitrate_count < MM_PLAYER_STREAM_COUNT_MAX) {\
1816                                 player->maximum_bitrate[player->updated_maximum_bitrate_count] = v_uint;\
1817                                 player->total_maximum_bitrate += player->maximum_bitrate[player->updated_maximum_bitrate_count]; \
1818                                 player->updated_maximum_bitrate_count++; \
1819                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate); \
1820                                 SECURE_LOGD("update maximum bitrate %d[bps] of stream #%d\n", v_uint, player->updated_maximum_bitrate_count);\
1821                         } \
1822                 } else\
1823                         mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
1824                 v_uint = 0;\
1825         } \
1826 }
1827
1828 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
1829 if (gst_tag_list_get_date(tag_list, gsttag, &date)) {\
1830         if (date != NULL) {\
1831                 string = g_strdup_printf("%d", g_date_get_year(date));\
1832                 mm_attrs_set_string_by_name(attribute, playertag, string);\
1833                 SECURE_LOGD("metainfo year : %s\n", string);\
1834                 MMPLAYER_FREEIF(string);\
1835                 g_date_free(date);\
1836         } \
1837 }
1838
1839 #define MMPLAYER_UPDATE_TAG_DATE_TIME(gsttag, attribute, playertag) \
1840 if (gst_tag_list_get_date_time(tag_list, gsttag, &datetime)) {\
1841         if (datetime != NULL) {\
1842                 string = g_strdup_printf("%d", gst_date_time_get_year(datetime));\
1843                 mm_attrs_set_string_by_name(attribute, playertag, string);\
1844                 SECURE_LOGD("metainfo year : %s\n", string);\
1845                 MMPLAYER_FREEIF(string);\
1846                 gst_date_time_unref(datetime);\
1847         } \
1848 }
1849
1850 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
1851 if (gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64)) {\
1852         if (v_uint64) {\
1853                 /* FIXIT : don't know how to store date */\
1854                 g_assert(1);\
1855                 v_uint64 = 0;\
1856         } \
1857 }
1858
1859 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
1860 if (gst_tag_list_get_double(tag_list, gsttag, &v_double)) {\
1861         if (v_double) {\
1862                 /* FIXIT : don't know how to store date */\
1863                 g_assert(1);\
1864                 v_double = 0;\
1865         } \
1866 }
1867
1868         /* function start */
1869         GstTagList* tag_list = NULL;
1870
1871         MMHandleType attrs = 0;
1872
1873         char *string = NULL;
1874         guint v_uint = 0;
1875         GDate *date = NULL;
1876         GstDateTime *datetime = NULL;
1877         /* album cover */
1878         GstBuffer *buffer = NULL;
1879         gint index = 0;
1880         MMMessageParamType msg_param = {0, };
1881
1882         /* currently not used. but those are needed for above macro */
1883         //guint64 v_uint64 = 0;
1884         //gdouble v_double = 0;
1885
1886         MMPLAYER_RETURN_VAL_IF_FAIL(player && msg, FALSE);
1887
1888         attrs = MMPLAYER_GET_ATTRS(player);
1889
1890         MMPLAYER_RETURN_VAL_IF_FAIL(attrs, FALSE);
1891
1892         /* get tag list from gst message */
1893         gst_message_parse_tag(msg, &tag_list);
1894
1895         /* store tags to player attributes */
1896         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
1897         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
1898         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
1899         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
1900         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
1901         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
1902         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
1903         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
1904         MMPLAYER_UPDATE_TAG_DATE_TIME(GST_TAG_DATE_TIME, attrs, "tag_date");
1905         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
1906         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
1907         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
1908         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
1909         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
1910         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
1911         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
1912         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
1913         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
1914         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
1915         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
1916         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
1917         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
1918         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
1919         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
1920         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
1921         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
1922         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
1923         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
1924         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
1925         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
1926         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
1927         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
1928         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
1929         MMPLAYER_UPDATE_TAG_LOCK(player);
1930         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
1931         MMPLAYER_UPDATE_TAG_UNLOCK(player);
1932         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
1933         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
1934         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
1935         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
1936         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
1937         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
1938         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
1939         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
1940         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
1941         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
1942         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
1943         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
1944         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, attrs, "content_video_orientation");
1945
1946         if (mmf_attrs_commit(attrs))
1947                 LOGE("failed to commit.\n");
1948
1949         gst_tag_list_free(tag_list);
1950
1951         return TRUE;
1952 }
1953
1954 static void
1955 __mmplayer_gst_rtp_no_more_pads(GstElement *element,  gpointer data)  // @
1956 {
1957         mm_player_t* player = (mm_player_t*) data;
1958
1959         MMPLAYER_FENTER();
1960
1961         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
1962           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
1963           * num_dynamic_pad. and this is no-more-pad situation which means mo more pad will be added.
1964           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
1965
1966           * [1] audio and video will be dumped with filesink.
1967           * [2] autoplugging is done by just using pad caps.
1968           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
1969           * and the video will be dumped via filesink.
1970           */
1971         if (player->num_dynamic_pad == 0) {
1972                 LOGD("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
1973
1974                 if (!__mmplayer_gst_remove_fakesink(player,
1975                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]))
1976                         /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
1977                          * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
1978                          * source element are not same. To overcome this situation, this function will called
1979                          * several places and several times. Therefore, this is not an error case.
1980                          */
1981                         return;
1982         }
1983
1984         /* create dot before error-return. for debugging */
1985         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-no-more-pad");
1986
1987         player->no_more_pad = TRUE;
1988
1989         MMPLAYER_FLEAVE();
1990 }
1991
1992 static gboolean
1993 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink) // @
1994 {
1995         GstElement* parent = NULL;
1996
1997         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
1998
1999         /* if we have no fakesink. this meas we are using decodebin which doesn'
2000         t need to add extra fakesink */
2001         MMPLAYER_RETURN_VAL_IF_FAIL(fakesink, TRUE);
2002
2003         /* lock */
2004         MMPLAYER_FSINK_LOCK(player);
2005
2006         if (!fakesink->gst)
2007                 goto ERROR;
2008
2009         /* get parent of fakesink */
2010         parent = (GstElement*)gst_object_get_parent((GstObject*)fakesink->gst);
2011         if (!parent) {
2012                 LOGD("fakesink already removed\n");
2013                 goto ERROR;
2014         }
2015
2016         gst_element_set_locked_state(fakesink->gst, TRUE);
2017
2018         /* setting the state to NULL never returns async
2019          * so no need to wait for completion of state transiton
2020          */
2021         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(fakesink->gst, GST_STATE_NULL))
2022                 LOGE("fakesink state change failure!\n");
2023                 /* FIXIT : should I return here? or try to proceed to next? */
2024                 /* return FALSE; */
2025
2026         /* remove fakesink from it's parent */
2027         if (!gst_bin_remove(GST_BIN(parent), fakesink->gst)) {
2028                 LOGE("failed to remove fakesink\n");
2029
2030                 gst_object_unref(parent);
2031
2032                 goto ERROR;
2033         }
2034
2035         gst_object_unref(parent);
2036
2037         LOGD("state-holder removed\n");
2038
2039         gst_element_set_locked_state(fakesink->gst, FALSE);
2040
2041         MMPLAYER_FSINK_UNLOCK(player);
2042         return TRUE;
2043
2044 ERROR:
2045         if (fakesink->gst)
2046                 gst_element_set_locked_state(fakesink->gst, FALSE);
2047
2048         MMPLAYER_FSINK_UNLOCK(player);
2049         return FALSE;
2050 }
2051
2052
2053 static void
2054 __mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data) // @
2055 {
2056         GstPad *sinkpad = NULL;
2057         GstCaps* caps = NULL;
2058         GstElement* new_element = NULL;
2059         GstStructure* str = NULL;
2060         const gchar* name = NULL;
2061
2062         mm_player_t* player = (mm_player_t*) data;
2063
2064         MMPLAYER_FENTER();
2065
2066         MMPLAYER_RETURN_IF_FAIL(element && pad);
2067         MMPLAYER_RETURN_IF_FAIL(player &&
2068                                         player->pipeline &&
2069                                         player->pipeline->mainbin);
2070
2071
2072         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2073          * num_dynamic_pad will decreased after creating a sinkbin.
2074          */
2075         player->num_dynamic_pad++;
2076         LOGD("stream count inc : %d\n", player->num_dynamic_pad);
2077
2078         caps = gst_pad_query_caps(pad, NULL);
2079
2080         MMPLAYER_CHECK_NULL(caps);
2081
2082         /* clear  previous result*/
2083         player->have_dynamic_pad = FALSE;
2084
2085         str = gst_caps_get_structure(caps, 0);
2086
2087         if (!str) {
2088                 LOGE("cannot get structure from caps.\n");
2089                 goto ERROR;
2090         }
2091
2092         name = gst_structure_get_name(str);
2093         if (!name) {
2094                 LOGE("cannot get mimetype from structure.\n");
2095                 goto ERROR;
2096         }
2097
2098         if (strstr(name, "video")) {
2099                 gint stype = 0;
2100                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
2101
2102                 if (stype == MM_DISPLAY_SURFACE_NULL || stype == MM_DISPLAY_SURFACE_REMOTE) {
2103                         if (player->v_stream_caps) {
2104                                 gst_caps_unref(player->v_stream_caps);
2105                                 player->v_stream_caps = NULL;
2106                         }
2107
2108                         new_element = gst_element_factory_make("fakesink", NULL);
2109                         player->num_dynamic_pad--;
2110                         goto NEW_ELEMENT;
2111                 }
2112         }
2113
2114         /* clear  previous result*/
2115         player->have_dynamic_pad = FALSE;
2116
2117         if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
2118                 LOGE("failed to autoplug for caps");
2119                 goto ERROR;
2120         }
2121
2122         /* check if there's dynamic pad*/
2123         if (player->have_dynamic_pad) {
2124                 LOGE("using pad caps assums there's no dynamic pad !\n");
2125                 goto ERROR;
2126         }
2127
2128         gst_caps_unref(caps);
2129         caps = NULL;
2130
2131 NEW_ELEMENT:
2132
2133         /* excute new_element if created*/
2134         if (new_element) {
2135                 LOGD("adding new element to pipeline\n");
2136
2137                 /* set state to READY before add to bin */
2138                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_READY);
2139
2140                 /* add new element to the pipeline */
2141                 if (FALSE == gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)) {
2142                         LOGE("failed to add autoplug element to bin\n");
2143                         goto ERROR;
2144                 }
2145
2146                 /* get pad from element */
2147                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(new_element), "sink");
2148                 if (!sinkpad) {
2149                         LOGE("failed to get sinkpad from autoplug element\n");
2150                         goto ERROR;
2151                 }
2152
2153                 /* link it */
2154                 if (GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad)) {
2155                         LOGE("failed to link autoplug element\n");
2156                         goto ERROR;
2157                 }
2158
2159                 gst_object_unref(sinkpad);
2160                 sinkpad = NULL;
2161
2162                 /* run. setting PLAYING here since streamming source is live source */
2163                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_PLAYING);
2164         }
2165
2166         MMPLAYER_FLEAVE();
2167
2168         return;
2169
2170 STATE_CHANGE_FAILED:
2171 ERROR:
2172         /* FIXIT : take care if new_element has already added to pipeline */
2173         if (new_element)
2174                 gst_object_unref(GST_OBJECT(new_element));
2175
2176         if (sinkpad)
2177                 gst_object_unref(GST_OBJECT(sinkpad));
2178
2179         if (caps)
2180                 gst_object_unref(GST_OBJECT(caps));
2181
2182         /* FIXIT : how to inform this error to MSL ????? */
2183         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2184          * then post an error to application
2185          */
2186 }
2187
2188
2189
2190 /* FIXIT : check indent */
2191 #if 0
2192 static void
2193 __mmplayer_gst_wfd_dynamic_pad(GstElement *element, GstPad *pad, gpointer data) // @
2194 {
2195         GstPad *sinkpad = NULL;
2196         GstCaps* caps = NULL;
2197         GstElement* new_element = NULL;
2198         enum MainElementID element_id = MMPLAYER_M_NUM;
2199
2200         mm_player_t* player = (mm_player_t*) data;
2201
2202         MMPLAYER_FENTER();
2203
2204         MMPLAYER_RETURN_IF_FAIL(element && pad);
2205         MMPLAYER_RETURN_IF_FAIL(player &&
2206                 player->pipeline &&
2207                 player->pipeline->mainbin);
2208
2209         LOGD("stream count inc : %d\n", player->num_dynamic_pad);
2210
2211         {
2212                 LOGD("using pad caps to autopluging instead of doing typefind\n");
2213                 caps = gst_pad_query_caps(pad);
2214                 MMPLAYER_CHECK_NULL(caps);
2215                 /* clear  previous result*/
2216                 player->have_dynamic_pad = FALSE;
2217                 new_element = gst_element_factory_make("rtpmp2tdepay", "wfd_rtp_depay");
2218                 if (!new_element) {
2219                         LOGE("failed to create wfd rtp depay element\n");
2220                         goto ERROR;
2221                 }
2222                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_READY);
2223                 /* add new element to the pipeline */
2224                 if (FALSE == gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)) {
2225                         LOGD("failed to add autoplug element to bin\n");
2226                         goto ERROR;
2227                 }
2228                 /* get pad from element */
2229                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(new_element), "sink");
2230                 if (!sinkpad) {
2231                         LOGD("failed to get sinkpad from autoplug element\n");
2232                         goto ERROR;
2233                 }
2234                 /* link it */
2235                 if (GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad)) {
2236                         LOGD("failed to link autoplug element\n");
2237                         goto ERROR;
2238                 }
2239                 gst_object_unref(sinkpad);
2240                 sinkpad = NULL;
2241                 pad = gst_element_get_static_pad(GST_ELEMENT(new_element), "src");
2242                 caps = gst_pad_query_caps(pad);
2243                 MMPLAYER_CHECK_NULL(caps);
2244                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_PLAYING);
2245                 /* create typefind */
2246                 new_element = gst_element_factory_make("typefind", NULL);
2247                 if (!new_element) {
2248                         LOGD("failed to create typefind\n");
2249                         goto ERROR;
2250                 }
2251
2252                 MMPLAYER_SIGNAL_CONNECT(player,
2253                         G_OBJECT(new_element),
2254                         MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2255                         "have-type",
2256                         G_CALLBACK(__mmplayer_typefind_have_type),
2257                         (gpointer)player);
2258
2259                 player->have_dynamic_pad = FALSE;
2260         }
2261
2262         /* excute new_element if created*/
2263         if (new_element) {
2264                 LOGD("adding new element to pipeline\n");
2265
2266                 /* set state to READY before add to bin */
2267                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_READY);
2268
2269                 /* add new element to the pipeline */
2270                 if (FALSE == gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)) {
2271                         LOGD("failed to add autoplug element to bin\n");
2272                         goto ERROR;
2273                 }
2274
2275                 /* get pad from element */
2276                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(new_element), "sink");
2277                 if (!sinkpad) {
2278                         LOGD("failed to get sinkpad from autoplug element\n");
2279                         goto ERROR;
2280                 }
2281
2282                 /* link it */
2283                 if (GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad)) {
2284                         LOGD("failed to link autoplug element\n");
2285                         goto ERROR;
2286                 }
2287
2288                 gst_object_unref(sinkpad);
2289                 sinkpad = NULL;
2290
2291                 /* run. setting PLAYING here since streamming source is live source */
2292                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_PLAYING);
2293         }
2294
2295         /* store handle to futher manipulation */
2296         player->pipeline->mainbin[element_id].id = element_id;
2297         player->pipeline->mainbin[element_id].gst = new_element;
2298
2299         MMPLAYER_FLEAVE();
2300
2301         return;
2302
2303 STATE_CHANGE_FAILED:
2304 ERROR:
2305         /* FIXIT : take care if new_element has already added to pipeline */
2306         if (new_element)
2307                 gst_object_unref(GST_OBJECT(new_element));
2308
2309         if (sinkpad)
2310                 gst_object_unref(GST_OBJECT(sinkpad));
2311
2312         if (caps)
2313                 gst_object_unref(GST_OBJECT(caps));
2314
2315         /* FIXIT : how to inform this error to MSL ????? */
2316         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2317          * then post an error to application
2318          */
2319 }
2320 #endif
2321
2322 static GstPadProbeReturn
2323 __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
2324 {
2325         LOGD("pad(%s:%s) is blocked", GST_DEBUG_PAD_NAME(pad));
2326         return GST_PAD_PROBE_OK;
2327 }
2328
2329 static GstPadProbeReturn
2330 __mmplayer_gst_selector_event_probe(GstPad * pad, GstPadProbeInfo * info, gpointer data)
2331 {
2332         GstPadProbeReturn ret = GST_PAD_PROBE_OK;
2333         GstEvent *event = GST_PAD_PROBE_INFO_DATA(info);
2334         mm_player_t* player = (mm_player_t*)data;
2335         GstCaps* caps = NULL;
2336         GstStructure* str = NULL;
2337         const gchar* name = NULL;
2338         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2339
2340
2341         if (GST_EVENT_IS_DOWNSTREAM(event)) {
2342                 if (GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START &&
2343                         GST_EVENT_TYPE(event) != GST_EVENT_FLUSH_STOP &&
2344                         GST_EVENT_TYPE(event) != GST_EVENT_SEGMENT &&
2345                         GST_EVENT_TYPE(event) != GST_EVENT_EOS)
2346                         return ret;
2347         } else if (GST_EVENT_IS_UPSTREAM(event)) {
2348                 if (GST_EVENT_TYPE(event) != GST_EVENT_QOS)
2349                         return ret;
2350         }
2351
2352         caps = gst_pad_query_caps(pad, NULL);
2353         if (!caps) {
2354                 LOGE("failed to get caps from pad[%s:%s]", GST_DEBUG_PAD_NAME(pad));
2355                 goto ERROR;
2356         }
2357
2358         str = gst_caps_get_structure(caps, 0);
2359         if (!str) {
2360                 LOGE("failed to get structure from caps");
2361                 goto ERROR;
2362         }
2363
2364         name = gst_structure_get_name(str);
2365         if (!name) {
2366                 LOGE("failed to get name from str");
2367                 goto ERROR;
2368         }
2369
2370         if (strstr(name, "audio")) {
2371                 stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2372         } else if (strstr(name, "video")) {
2373                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2374         } else {
2375                 /* text track is not supportable */
2376                 LOGE("invalid name %s", name);
2377                 goto ERROR;
2378         }
2379
2380         switch (GST_EVENT_TYPE(event)) {
2381         case GST_EVENT_EOS:
2382                 {
2383                         /* in case of gapless, drop eos event not to send it to sink */
2384                         if (player->gapless.reconfigure && !player->msg_posted) {
2385                                 LOGD("[%d] %s:%s EOS received but will be drop", stream_type, GST_DEBUG_PAD_NAME(pad));
2386                                 ret = GST_PAD_PROBE_DROP;
2387                         }
2388                         break;
2389                 }
2390         case GST_EVENT_STREAM_START:
2391                 {
2392                         gint64 stop_running_time = 0;
2393                         gint64 position_running_time = 0;
2394                         gint64 position = 0;
2395                         gint idx = 0;
2396
2397                         for (idx = MM_PLAYER_TRACK_TYPE_AUDIO; idx < MM_PLAYER_TRACK_TYPE_TEXT; idx++) {
2398                                 if ((player->gapless.update_segment[idx] == TRUE) ||
2399                                         !(player->selector[idx].event_probe_id)) {
2400                                         /* LOGW("[%d] skip", idx); */
2401                                         continue;
2402                                 }
2403
2404                                 if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].stop)) {
2405                                         stop_running_time =
2406                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2407                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].stop);
2408                                 } else if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].duration)) {
2409                                         stop_running_time =
2410                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2411                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].duration);
2412                                 } else {
2413                                         LOGD("duration: %"GST_TIME_FORMAT, GST_TIME_ARGS(player->duration));
2414                                         stop_running_time =
2415                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2416                                                                 GST_FORMAT_TIME, player->duration);
2417                                 }
2418
2419                                 position_running_time =
2420                                         gst_segment_to_running_time(&player->gapless.segment[idx],
2421                                         GST_FORMAT_TIME, player->gapless.segment[idx].position);
2422
2423                                 LOGD("[type:%d] time info %" GST_TIME_FORMAT " , %"
2424                                         GST_TIME_FORMAT" , %" GST_TIME_FORMAT,
2425                                         idx,
2426                                         GST_TIME_ARGS(stop_running_time),
2427                                         GST_TIME_ARGS(position_running_time),
2428                                         GST_TIME_ARGS(gst_segment_to_running_time(&player->gapless.segment[idx],
2429                                         GST_FORMAT_TIME, player->gapless.segment[idx].start)));
2430
2431                                 position_running_time = MAX(position_running_time, stop_running_time);
2432                                 position_running_time -= gst_segment_to_running_time(&player->gapless.segment[idx],
2433                                                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].start);
2434                                 position_running_time = MAX(0, position_running_time);
2435                                 position = MAX(position, position_running_time);
2436                         }
2437
2438                         if (position != 0) {
2439                                 LOGD("[%d]GST_EVENT_STREAM_START: start_time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
2440                                         stream_type, GST_TIME_ARGS(player->gapless.start_time[stream_type]),
2441                                         GST_TIME_ARGS(player->gapless.start_time[stream_type] + position));
2442
2443                                 player->gapless.start_time[stream_type] += position;
2444                         }
2445                         break;
2446                 }
2447         case GST_EVENT_FLUSH_STOP:
2448                 {
2449                         LOGD("[%d] GST_EVENT_FLUSH_STOP", stream_type);
2450                         gst_segment_init(&player->gapless.segment[stream_type], GST_FORMAT_UNDEFINED);
2451                         player->gapless.start_time[stream_type] = 0;
2452                         break;
2453                 }
2454         case GST_EVENT_SEGMENT:
2455                 {
2456                         GstSegment segment;
2457                         GstEvent *tmpev;
2458
2459                         LOGD("[%d] GST_EVENT_SEGMENT", stream_type);
2460                         gst_event_copy_segment(event, &segment);
2461
2462                         if (segment.format == GST_FORMAT_TIME) {
2463                                 LOGD("segment base:%" GST_TIME_FORMAT ", offset:%" GST_TIME_FORMAT
2464                                          ", start:%" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT
2465                                          ", time: %" GST_TIME_FORMAT ", pos: %" GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT,
2466                                         GST_TIME_ARGS(segment.base), GST_TIME_ARGS(segment.offset),
2467                                         GST_TIME_ARGS(segment.start), GST_TIME_ARGS(segment.stop),
2468                                         GST_TIME_ARGS(segment.time), GST_TIME_ARGS(segment.position), GST_TIME_ARGS(segment.duration));
2469
2470                                 /* keep the all the segment ev to cover the seeking */
2471                                 gst_segment_copy_into(&segment, &player->gapless.segment[stream_type]);
2472                                 player->gapless.update_segment[stream_type] = TRUE;
2473
2474                                 if (!player->gapless.running)
2475                                         break;
2476
2477                                 player->gapless.segment[stream_type].base = player->gapless.start_time[stream_type];
2478
2479                                 LOGD("[%d] new base: %" GST_TIME_FORMAT, stream_type, GST_TIME_ARGS(player->gapless.segment[stream_type].base));
2480
2481                                 tmpev = gst_event_new_segment(&player->gapless.segment[stream_type]);
2482                                 gst_event_set_seqnum(tmpev, gst_event_get_seqnum(event));
2483                                 gst_event_unref(event);
2484                                 GST_PAD_PROBE_INFO_DATA(info) = tmpev;
2485                         }
2486                         break;
2487                 }
2488         case GST_EVENT_QOS:
2489                 {
2490                         gdouble proportion = 0.0;
2491                         GstClockTimeDiff diff = 0;
2492                         GstClockTime timestamp = 0;
2493                         gint64 running_time_diff = -1;
2494                         GstQOSType type = 0;
2495                         GstEvent *tmpev = NULL;
2496
2497                         running_time_diff = player->gapless.segment[stream_type].base;
2498
2499                         if (running_time_diff <= 0) /* don't need to adjust */
2500                                 break;
2501
2502                         gst_event_parse_qos(event, &type, &proportion, &diff, &timestamp);
2503                         gst_event_unref(event);
2504
2505                         if (timestamp < running_time_diff) {
2506                                 LOGW("QOS event from previous group");
2507                                 ret = GST_PAD_PROBE_DROP;
2508                                 break;
2509                         }
2510
2511                         LOGD("[%d] Adjusting QOS event: %" GST_TIME_FORMAT
2512                                  " - %" GST_TIME_FORMAT " = %" GST_TIME_FORMAT,
2513                                                 stream_type, GST_TIME_ARGS(timestamp),
2514                                                 GST_TIME_ARGS(running_time_diff),
2515                                                 GST_TIME_ARGS(timestamp - running_time_diff));
2516
2517                         timestamp -= running_time_diff;
2518
2519                         /* That case is invalid for QoS events */
2520                         if (diff < 0 && -diff > timestamp) {
2521                                 LOGW("QOS event from previous group");
2522                                 ret = GST_PAD_PROBE_DROP;
2523                                 break;
2524                         }
2525
2526                         tmpev = gst_event_new_qos(GST_QOS_TYPE_UNDERFLOW, proportion, diff, timestamp);
2527                         GST_PAD_PROBE_INFO_DATA(info) = tmpev;
2528
2529                         break;
2530                 }
2531         default:
2532                 break;
2533         }
2534
2535 ERROR:
2536         if (caps)
2537                 gst_caps_unref(caps);
2538         return ret;
2539 }
2540
2541 static void
2542 __mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
2543 {
2544         mm_player_t* player = NULL;
2545         GstElement* pipeline = NULL;
2546         GstElement* selector = NULL;
2547         GstElement* fakesink = NULL;
2548         GstCaps* caps = NULL;
2549         GstStructure* str = NULL;
2550         const gchar* name = NULL;
2551         GstPad* sinkpad = NULL;
2552         GstPad* srcpad = NULL;
2553         gboolean first_track = FALSE;
2554
2555         enum MainElementID elemId = MMPLAYER_M_NUM;
2556         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2557
2558         /* check handles */
2559         player = (mm_player_t*)data;
2560
2561         MMPLAYER_RETURN_IF_FAIL(elem && pad);
2562         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2563
2564         //LOGD("pad-added signal handling\n");
2565
2566         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
2567
2568         /* get mimetype from caps */
2569         caps = gst_pad_query_caps(pad, NULL);
2570         if (!caps) {
2571                 LOGE("cannot get caps from pad.\n");
2572                 goto ERROR;
2573         }
2574
2575         str = gst_caps_get_structure(caps, 0);
2576         if (!str) {
2577                 LOGE("cannot get structure from caps.\n");
2578                 goto ERROR;
2579         }
2580
2581         name = gst_structure_get_name(str);
2582         if (!name) {
2583                 LOGE("cannot get mimetype from structure.\n");
2584                 goto ERROR;
2585         }
2586
2587         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
2588         //LOGD("detected mimetype : %s\n", name);
2589
2590         if (strstr(name, "video")) {
2591                 gint stype = 0;
2592
2593                 mm_attrs_set_int_by_name(player->attrs, "content_video_found", TRUE);
2594                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
2595
2596                 /* don't make video because of not required, and not support multiple track */
2597                 if (stype == MM_DISPLAY_SURFACE_NULL) {
2598                         LOGD("no video sink by null surface");
2599                         MMPlayerResourceState resource_state = RESOURCE_STATE_NONE;
2600                         if (_mmplayer_resource_manager_get_state(&player->resource_manager, &resource_state)
2601                                         == MM_ERROR_NONE) {
2602                                 /* acquire resources for video playing */
2603                                 if (resource_state == RESOURCE_STATE_PREPARED) {
2604                                         if (_mmplayer_resource_manager_acquire(&player->resource_manager)
2605                                                         != MM_ERROR_NONE) {
2606                                                 LOGE("could not acquire resources for video playing\n");
2607                                                 _mmplayer_resource_manager_unprepare(&player->resource_manager);
2608                                                 goto ERROR;
2609                                         }
2610                                 }
2611                         }
2612
2613                         gchar *caps_str = gst_caps_to_string(caps);
2614                         if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12")))
2615                                 player->set_mode.video_zc = TRUE;
2616
2617                         MMPLAYER_FREEIF(caps_str);
2618
2619                         if (player->v_stream_caps) {
2620                                 gst_caps_unref(player->v_stream_caps);
2621                                 player->v_stream_caps = NULL;
2622                         }
2623
2624                         LOGD("create fakesink instead of videobin");
2625
2626                         /* fake sink */
2627                         fakesink = gst_element_factory_make("fakesink", NULL);
2628                         if (fakesink == NULL) {
2629                                 LOGE("ERROR : fakesink create error\n");
2630                                 goto ERROR;
2631                         }
2632
2633                         if (player->ini.set_dump_element_flag)
2634                                 __mmplayer_add_dump_buffer_probe(player, fakesink);
2635
2636                         player->video_fakesink = fakesink;
2637
2638                         /* store it as it's sink element */
2639                         __mmplayer_add_sink(player, player->video_fakesink);
2640
2641                         gst_bin_add(GST_BIN(pipeline), fakesink);
2642
2643                         // link
2644                         sinkpad = gst_element_get_static_pad(fakesink, "sink");
2645
2646                         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2647                                 LOGW("failed to link fakesink\n");
2648                                 gst_object_unref(GST_OBJECT(fakesink));
2649                                 goto ERROR;
2650                         }
2651
2652                         if (stype == MM_DISPLAY_SURFACE_REMOTE) {
2653                                 MMPLAYER_SIGNAL_CONNECT(player, sinkpad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2654                                                 "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
2655                         }
2656
2657                         if (player->set_mode.media_packet_video_stream) {
2658                                 g_object_set(G_OBJECT(fakesink), "signal-handoffs", TRUE, NULL);
2659
2660                                 MMPLAYER_SIGNAL_CONNECT(player,
2661                                                                                 G_OBJECT(fakesink),
2662                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2663                                                                                 "handoff",
2664                                                                                 G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
2665                                                                                 (gpointer)player);
2666
2667                                 MMPLAYER_SIGNAL_CONNECT(player,
2668                                                                                 G_OBJECT(fakesink),
2669                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2670                                                                                 "preroll-handoff",
2671                                                                                 G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
2672                                                                                 (gpointer)player);
2673                         }
2674
2675                         g_object_set(G_OBJECT(fakesink), "async", TRUE, "sync", TRUE, NULL);
2676                         gst_element_set_state(fakesink, GST_STATE_PAUSED);
2677                         goto DONE;
2678                 }
2679
2680                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
2681                         __mmplayer_gst_decode_callback(elem, pad, player);
2682                         return;
2683                 }
2684
2685                 LOGD("video selector \n");
2686                 elemId = MMPLAYER_M_V_INPUT_SELECTOR;
2687                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2688         } else {
2689                 if (strstr(name, "audio")) {
2690                         gint samplerate = 0;
2691                         gint channels = 0;
2692
2693                         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
2694                                 __mmplayer_gst_decode_callback(elem, pad, player);
2695                                 return;
2696                         }
2697
2698                         LOGD("audio selector \n");
2699                         elemId = MMPLAYER_M_A_INPUT_SELECTOR;
2700                         stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2701
2702                         gst_structure_get_int(str, "rate", &samplerate);
2703                         gst_structure_get_int(str, "channels", &channels);
2704
2705                         if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
2706                                 /* fake sink */
2707                                 fakesink = gst_element_factory_make("fakesink", NULL);
2708                                 if (fakesink == NULL) {
2709                                         LOGE("ERROR : fakesink create error\n");
2710                                         goto ERROR;
2711                                 }
2712
2713                                 gst_bin_add(GST_BIN(pipeline), fakesink);
2714
2715                                 /* link */
2716                                 sinkpad = gst_element_get_static_pad(fakesink, "sink");
2717
2718                                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2719                                         LOGW("failed to link fakesink\n");
2720                                         gst_object_unref(GST_OBJECT(fakesink));
2721                                         goto ERROR;
2722                                 }
2723
2724                                 g_object_set(G_OBJECT(fakesink), "async", TRUE, NULL);
2725                                 g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL);
2726                                 gst_element_set_state(fakesink, GST_STATE_PAUSED);
2727
2728                                 goto DONE;
2729                         }
2730                 } else if (strstr(name, "text")) {
2731                         LOGD("text selector \n");
2732                         elemId = MMPLAYER_M_T_INPUT_SELECTOR;
2733                         stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
2734                 } else {
2735                         LOGE("wrong elem id \n");
2736                         goto ERROR;
2737                 }
2738         }
2739
2740         selector = player->pipeline->mainbin[elemId].gst;
2741         if (selector == NULL) {
2742                 selector = gst_element_factory_make("input-selector", NULL);
2743                 LOGD("Creating input-selector\n");
2744                 if (selector == NULL) {
2745                         LOGE("ERROR : input-selector create error\n");
2746                         goto ERROR;
2747                 }
2748                 g_object_set(selector, "sync-streams", TRUE, NULL);
2749
2750                 player->pipeline->mainbin[elemId].id = elemId;
2751                 player->pipeline->mainbin[elemId].gst = selector;
2752
2753                 first_track = TRUE;
2754                 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK;      // default
2755
2756                 srcpad = gst_element_get_static_pad(selector, "src");
2757
2758                 LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
2759                 player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
2760                         __mmplayer_gst_selector_blocked, NULL, NULL);
2761                 player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
2762                         __mmplayer_gst_selector_event_probe, player, NULL);
2763
2764                 gst_element_set_state(selector, GST_STATE_PAUSED);
2765                 gst_bin_add(GST_BIN(pipeline), selector);
2766         } else
2767                 LOGD("input-selector is already created.\n");
2768
2769         // link
2770         LOGD("Calling request pad with selector %p \n", selector);
2771         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
2772
2773         LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(sinkpad));
2774
2775         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2776                 LOGW("failed to link selector\n");
2777                 gst_object_unref(GST_OBJECT(selector));
2778                 goto ERROR;
2779         }
2780
2781         if (first_track) {
2782                 LOGD("this is first track --> active track \n");
2783                 g_object_set(selector, "active-pad", sinkpad, NULL);
2784         }
2785
2786         _mmplayer_track_update_info(player, stream_type, sinkpad);
2787
2788
2789 DONE:
2790 ERROR:
2791
2792         if (caps)
2793                 gst_caps_unref(caps);
2794
2795         if (sinkpad) {
2796                 gst_object_unref(GST_OBJECT(sinkpad));
2797                 sinkpad = NULL;
2798         }
2799
2800         if (srcpad) {
2801                 gst_object_unref(GST_OBJECT(srcpad));
2802                 srcpad = NULL;
2803         }
2804
2805         return;
2806 }
2807
2808 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
2809 {
2810         GstPad* srcpad = NULL;
2811         MMHandleType attrs = 0;
2812         gint active_index = 0;
2813
2814         // [link] input-selector :: textbin
2815         srcpad = gst_element_get_static_pad(text_selector, "src");
2816         if (!srcpad) {
2817                 LOGE("failed to get srcpad from selector\n");
2818                 return;
2819         }
2820
2821         LOGD("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
2822
2823         active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
2824         if ((active_index != DEFAULT_TRACK) &&
2825                 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE)) {
2826                 LOGW("failed to change text track\n");
2827                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
2828         }
2829
2830         player->no_more_pad = TRUE;
2831         __mmplayer_gst_decode_callback(text_selector, srcpad, player);
2832
2833         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
2834         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id) {
2835                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id);
2836                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id = 0;
2837         }
2838
2839         LOGD("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
2840
2841         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
2842                 player->has_closed_caption = TRUE;
2843
2844         attrs = MMPLAYER_GET_ATTRS(player);
2845         if (attrs) {
2846                 mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
2847                 if (mmf_attrs_commit(attrs))
2848                         LOGE("failed to commit.\n");
2849         } else
2850                 LOGE("cannot get content attribute");
2851
2852         if (srcpad) {
2853                 gst_object_unref(GST_OBJECT(srcpad));
2854                 srcpad = NULL;
2855         }
2856 }
2857
2858 int _mmplayer_gst_set_audio_channel(MMHandleType hplayer, MMPlayerAudioChannel ch_idx)
2859 {
2860         int result = MM_ERROR_NONE;
2861
2862         mm_player_t* player = (mm_player_t*)hplayer;
2863         MMPlayerGstElement* mainbin = NULL;
2864         gchar* change_pad_name = NULL;
2865         GstPad* sinkpad = NULL;
2866         GstCaps* caps = NULL;
2867
2868         MMPLAYER_FENTER();
2869
2870         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
2871
2872         LOGD("Change Audio mode to %d\n", ch_idx);
2873         player->use_deinterleave = TRUE;
2874
2875         if ((!player->pipeline) || (!player->pipeline->mainbin)) {
2876                 LOGD("pre setting : %d\n", ch_idx);
2877
2878                 player->audio_mode.active_pad_index = ch_idx;
2879                 return result;
2880         }
2881
2882         mainbin = player->pipeline->mainbin;
2883
2884         if (mainbin[MMPLAYER_M_A_SELECTOR].gst == NULL) {
2885                 if (player->max_audio_channels < 2) {
2886                         LOGD("mono channel track only\n");
2887                         return result;
2888                 }
2889
2890                 LOGW("selector doesn't exist\n");
2891                 return result;  /* keep playing */
2892         }
2893
2894         LOGD("total_ch_num : %d\n", player->audio_mode.total_track_num);
2895
2896         if (player->audio_mode.total_track_num < 2) {
2897                 LOGW("there is no another audio path\n");
2898                 return result;  /* keep playing */
2899         }
2900
2901         if ((ch_idx < 0) || (ch_idx >= player->audio_mode.total_track_num)) {
2902                 LOGW("Not a proper ch_idx : %d \n", ch_idx);
2903                 return result;  /* keep playing */
2904         }
2905
2906         /*To get the new pad from the selector*/
2907         change_pad_name = g_strdup_printf("sink%d", ch_idx);
2908         if (change_pad_name == NULL) {
2909                 LOGW("Pad does not exists\n");
2910                 goto ERROR;     /* keep playing */
2911         }
2912
2913         LOGD("new active pad name: %s\n", change_pad_name);
2914
2915         sinkpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_SELECTOR].gst, change_pad_name);
2916         if (sinkpad == NULL)
2917                 //result = MM_ERROR_PLAYER_INTERNAL;
2918                 goto ERROR;     /* keep playing */
2919
2920         LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
2921         g_object_set(mainbin[MMPLAYER_M_A_SELECTOR].gst, "active-pad", sinkpad, NULL);
2922
2923         caps = gst_pad_get_current_caps(sinkpad);
2924         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
2925
2926         __mmplayer_set_audio_attrs(player, caps);
2927         player->audio_mode.active_pad_index = ch_idx;
2928
2929 ERROR:
2930
2931         if (sinkpad)
2932                 gst_object_unref(sinkpad);
2933
2934         MMPLAYER_FREEIF(change_pad_name);
2935
2936         MMPLAYER_FLEAVE();
2937         return result;
2938 }
2939
2940
2941
2942 static void
2943 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
2944 {
2945         mm_player_t* player = (mm_player_t*)data;
2946         GstElement* selector = NULL;
2947         GstElement* queue = NULL;
2948
2949         GstPad* srcpad = NULL;
2950         GstPad* sinkpad = NULL;
2951         gchar* caps_str = NULL;
2952
2953         MMPLAYER_FENTER();
2954         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2955
2956         caps_str = gst_caps_to_string(gst_pad_get_current_caps(pad));
2957         LOGD("deinterleave new caps : %s\n", caps_str);
2958         MMPLAYER_FREEIF(caps_str);
2959
2960         if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL) {
2961                 LOGE("ERROR : queue create error\n");
2962                 goto ERROR;
2963         }
2964
2965         g_object_set(G_OBJECT(queue),
2966                                 "max-size-buffers", 10,
2967                                 "max-size-bytes", 0,
2968                                 "max-size-time", (guint64)0,
2969                                 NULL);
2970
2971         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
2972
2973         if (!selector) {
2974                 LOGE("there is no audio channel selector.\n");
2975                 goto ERROR;
2976         }
2977
2978         srcpad = gst_element_get_static_pad(queue, "src");
2979         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
2980
2981         LOGD("link(%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
2982
2983         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
2984                 LOGW("failed to link deinterleave - selector\n");
2985                 goto ERROR;
2986         }
2987
2988         gst_element_set_state(queue, GST_STATE_PAUSED);
2989         player->audio_mode.total_track_num++;
2990
2991 ERROR:
2992
2993         if (srcpad) {
2994                 gst_object_unref(GST_OBJECT(srcpad));
2995                 srcpad = NULL;
2996         }
2997
2998         if (sinkpad) {
2999                 gst_object_unref(GST_OBJECT(sinkpad));
3000                 sinkpad = NULL;
3001         }
3002
3003         MMPLAYER_FLEAVE();
3004         return;
3005 }
3006
3007 static void
3008 __mmplayer_gst_deinterleave_no_more_pads(GstElement *elem, gpointer data)
3009 {
3010         mm_player_t* player = NULL;
3011         GstElement* selector = NULL;
3012         GstPad* sinkpad = NULL;
3013         gint active_index = 0;
3014         gchar* change_pad_name = NULL;
3015         GstCaps* caps = NULL;   // no need to unref
3016         gint default_audio_ch = 0;
3017
3018         MMPLAYER_FENTER();
3019         player = (mm_player_t*) data;
3020
3021         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3022
3023         if (!selector) {
3024                 LOGE("there is no audio channel selector.\n");
3025                 goto ERROR;
3026         }
3027
3028         active_index = player->audio_mode.active_pad_index;
3029
3030         if (active_index != default_audio_ch) {
3031                 gint audio_ch = default_audio_ch;
3032
3033                 /*To get the new pad from the selector*/
3034                 change_pad_name = g_strdup_printf("sink%d", active_index);
3035                 if (change_pad_name != NULL) {
3036                         sinkpad = gst_element_get_static_pad(selector, change_pad_name);
3037                         if (sinkpad != NULL) {
3038                                 LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3039                                 g_object_set(selector, "active-pad", sinkpad, NULL);
3040
3041                                 audio_ch = active_index;
3042
3043                                 caps = gst_pad_get_current_caps(sinkpad);
3044                                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3045
3046                                 __mmplayer_set_audio_attrs(player, caps);
3047                         }
3048                         MMPLAYER_FREEIF(change_pad_name);
3049                 }
3050
3051                 player->audio_mode.active_pad_index = audio_ch;
3052                 LOGD("audio LR info(0:stereo) = %d\n", player->audio_mode.active_pad_index);
3053         }
3054
3055 ERROR:
3056
3057         if (sinkpad)
3058                 gst_object_unref(sinkpad);
3059
3060         MMPLAYER_FLEAVE();
3061         return;
3062 }
3063
3064 static void
3065 __mmplayer_gst_build_deinterleave_path(GstElement *elem, GstPad *pad, gpointer data)
3066 {
3067         mm_player_t* player = NULL;
3068         MMPlayerGstElement *mainbin = NULL;
3069
3070         GstElement* tee = NULL;
3071         GstElement* stereo_queue = NULL;
3072         GstElement* mono_queue = NULL;
3073         GstElement* conv = NULL;
3074         GstElement* filter = NULL;
3075         GstElement* deinterleave = NULL;
3076         GstElement* selector = NULL;
3077
3078         GstPad* srcpad = NULL;
3079         GstPad* selector_srcpad = NULL;
3080         GstPad* sinkpad = NULL;
3081         GstCaps* caps = NULL;
3082         gulong block_id = 0;
3083
3084         MMPLAYER_FENTER();
3085
3086         /* check handles */
3087         player = (mm_player_t*) data;
3088
3089         MMPLAYER_RETURN_IF_FAIL(elem && pad);
3090         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
3091
3092         mainbin = player->pipeline->mainbin;
3093
3094         /* tee */
3095         if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL) {
3096                 LOGE("ERROR : tee create error\n");
3097                 goto ERROR;
3098         }
3099
3100         mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
3101         mainbin[MMPLAYER_M_A_TEE].gst = tee;
3102
3103         gst_element_set_state(tee, GST_STATE_PAUSED);
3104
3105         /* queue */
3106         srcpad = gst_element_get_request_pad(tee, "src_%u");
3107         if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL) {
3108                 LOGE("ERROR : stereo queue create error\n");
3109                 goto ERROR;
3110         }
3111
3112         g_object_set(G_OBJECT(stereo_queue),
3113                                 "max-size-buffers", 10,
3114                                 "max-size-bytes", 0,
3115                                 "max-size-time", (guint64)0,
3116                                 NULL);
3117
3118         player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
3119         player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
3120
3121         if (srcpad) {
3122                 gst_object_unref(GST_OBJECT(srcpad));
3123                 srcpad = NULL;
3124         }
3125
3126         srcpad = gst_element_get_request_pad(tee, "src_%u");
3127
3128         if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL) {
3129                 LOGE("ERROR : mono queue create error\n");
3130                 goto ERROR;
3131         }
3132
3133         g_object_set(G_OBJECT(mono_queue),
3134                                 "max-size-buffers", 10,
3135                                 "max-size-bytes", 0,
3136                                 "max-size-time", (guint64)0,
3137                                 NULL);
3138
3139         player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3140         player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3141
3142         gst_element_set_state(stereo_queue, GST_STATE_PAUSED);
3143         gst_element_set_state(mono_queue, GST_STATE_PAUSED);
3144
3145         /* audioconvert */
3146         srcpad = gst_element_get_static_pad(mono_queue, "src");
3147         if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL) {
3148                 LOGE("ERROR : audioconvert create error\n");
3149                 goto ERROR;
3150         }
3151
3152         player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3153         player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3154
3155         /* caps filter */
3156         if (srcpad) {
3157                 gst_object_unref(GST_OBJECT(srcpad));
3158                 srcpad = NULL;
3159         }
3160         srcpad = gst_element_get_static_pad(conv, "src");
3161
3162         if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL) {
3163                 LOGE("ERROR : capsfilter create error\n");
3164                 goto ERROR;
3165         }
3166
3167         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3168         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3169
3170         caps = gst_caps_from_string("audio/x-raw-int, "
3171                                 "width = (int) 16, "
3172                                 "depth = (int) 16, "
3173                                 "channels = (int) 2");
3174
3175         g_object_set(GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL);
3176         gst_caps_unref(caps);
3177
3178         gst_element_set_state(conv, GST_STATE_PAUSED);
3179         gst_element_set_state(filter, GST_STATE_PAUSED);
3180
3181         /* deinterleave */
3182         if (srcpad) {
3183                 gst_object_unref(GST_OBJECT(srcpad));
3184                 srcpad = NULL;
3185         }
3186         srcpad = gst_element_get_static_pad(filter, "src");
3187
3188         if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL) {
3189                 LOGE("ERROR : deinterleave create error\n");
3190                 goto ERROR;
3191         }
3192
3193         g_object_set(deinterleave, "keep-positions", TRUE, NULL);
3194
3195         MMPLAYER_SIGNAL_CONNECT(player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3196                                                         G_CALLBACK(__mmplayer_gst_deinterleave_pad_added), player);
3197
3198         MMPLAYER_SIGNAL_CONNECT(player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3199                                                         G_CALLBACK(__mmplayer_gst_deinterleave_no_more_pads), player);
3200
3201         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3202         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3203
3204         /* selector */
3205         selector = gst_element_factory_make("input-selector", "audio-channel-selector");
3206         if (selector == NULL) {
3207                 LOGE("ERROR : audio-selector create error\n");
3208                 goto ERROR;
3209         }
3210
3211         g_object_set(selector, "sync-streams", TRUE, NULL);
3212         gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3213
3214         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3215         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3216
3217         selector_srcpad = gst_element_get_static_pad(selector, "src");
3218
3219         LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3220         block_id =
3221                 gst_pad_add_probe(selector_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3222                         __mmplayer_gst_selector_blocked, NULL, NULL);
3223
3224         if (srcpad) {
3225                 gst_object_unref(GST_OBJECT(srcpad));
3226                 srcpad = NULL;
3227         }
3228
3229         srcpad = gst_element_get_static_pad(stereo_queue, "src");
3230         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
3231
3232         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
3233                 LOGW("failed to link queue_stereo - selector\n");
3234                 goto ERROR;
3235         }
3236
3237         player->audio_mode.total_track_num++;
3238
3239         g_object_set(selector, "active-pad", sinkpad, NULL);
3240         gst_element_set_state(deinterleave, GST_STATE_PAUSED);
3241         gst_element_set_state(selector, GST_STATE_PAUSED);
3242
3243         __mmplayer_gst_decode_callback(selector, selector_srcpad, player);
3244
3245 ERROR:
3246
3247         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3248         if (block_id != 0) {
3249                 gst_pad_remove_probe(selector_srcpad, block_id);
3250                 block_id = 0;
3251         }
3252
3253         if (sinkpad) {
3254                 gst_object_unref(GST_OBJECT(sinkpad));
3255                 sinkpad = NULL;
3256         }
3257
3258         if (srcpad) {
3259                 gst_object_unref(GST_OBJECT(srcpad));
3260                 srcpad = NULL;
3261         }
3262
3263         if (selector_srcpad) {
3264                 gst_object_unref(GST_OBJECT(selector_srcpad));
3265                 selector_srcpad = NULL;
3266         }
3267
3268         MMPLAYER_FLEAVE();
3269         return;
3270 }
3271
3272 static void
3273 __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
3274 {
3275         mm_player_t* player = NULL;
3276         GstPad* srcpad = NULL;
3277         GstElement* video_selector = NULL;
3278         GstElement* audio_selector = NULL;
3279         GstElement* text_selector = NULL;
3280         MMHandleType attrs = 0;
3281         gint active_index = 0;
3282         gint64 dur_bytes = 0L;
3283
3284         player = (mm_player_t*) data;
3285
3286         LOGD("no-more-pad signal handling\n");
3287
3288         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3289                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE)) {
3290                 LOGW("no need to go more");
3291
3292                 if (player->gapless.reconfigure) {
3293                         player->gapless.reconfigure = FALSE;
3294                         MMPLAYER_PLAYBACK_UNLOCK(player);
3295                 }
3296
3297                 return;
3298         }
3299
3300         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3301                 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3302                 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3303                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
3304                 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
3305
3306                 if (NULL == player->streamer) {
3307                         LOGW("invalid state for buffering");
3308                         goto ERROR;
3309                 }
3310
3311                 gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
3312                 guint buffer_bytes = init_buffering_time * ESTIMATED_BUFFER_UNIT;
3313
3314                 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
3315                 LOGD("[Decodebin2] set use-buffering on Q2(pre buffer time: %d sec, buffer size : %d)\n", (gint)init_buffering_time, buffer_bytes);
3316
3317                 init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
3318
3319                 if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
3320                         LOGE("fail to get duration.\n");
3321
3322                 // enable use-buffering on queue2 instead of multiqueue(ex)audio only streaming
3323                 // use file information was already set on Q2 when it was created.
3324                 __mm_player_streaming_set_queue2(player->streamer,
3325                                                 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
3326                                                 TRUE,                                                           // use_buffering
3327                                                 buffer_bytes,
3328                                                 init_buffering_time,
3329                                                 1.0,                                                            // low percent
3330                                                 player->ini.http_buffering_limit,       // high percent
3331                                                 MUXED_BUFFER_TYPE_MEM_QUEUE,
3332                                                 NULL,
3333                                                 ((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
3334         }
3335
3336         video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
3337         audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
3338         text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3339         if (video_selector) {
3340                 // [link] input-selector :: videobin
3341                 srcpad = gst_element_get_static_pad(video_selector, "src");
3342                 if (!srcpad) {
3343                         LOGE("failed to get srcpad from video selector\n");
3344                         goto ERROR;
3345                 }
3346
3347                 LOGD("got pad %s:%s from video selector\n", GST_DEBUG_PAD_NAME(srcpad));
3348                 if (!text_selector && !audio_selector)
3349                         player->no_more_pad = TRUE;
3350
3351                 __mmplayer_gst_decode_callback(video_selector, srcpad, player);
3352
3353                 LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3354                 if (player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id) {
3355                         gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id);
3356                         player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id = 0;
3357                 }
3358         }
3359
3360         if (audio_selector) {
3361                 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
3362                 if ((active_index != DEFAULT_TRACK) &&
3363                         (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE)) {
3364                         LOGW("failed to change audio track\n");
3365                         player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
3366                 }
3367
3368                 // [link] input-selector :: audiobin
3369                 srcpad = gst_element_get_static_pad(audio_selector, "src");
3370                 if (!srcpad) {
3371                         LOGE("failed to get srcpad from selector\n");
3372                         goto ERROR;
3373                 }
3374
3375                 LOGD("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3376                 if (!text_selector)
3377                         player->no_more_pad = TRUE;
3378
3379                 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2)) {
3380                         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3381                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id) {
3382                                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3383                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3384                         }
3385
3386                         __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
3387                 } else {
3388                         __mmplayer_gst_decode_callback(audio_selector, srcpad, player);
3389
3390                         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3391                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id) {
3392                                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3393                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3394                         }
3395                 }
3396
3397                 LOGD("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3398
3399                 attrs = MMPLAYER_GET_ATTRS(player);
3400                 if (attrs) {
3401                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", (gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3402                         if (mmf_attrs_commit(attrs))
3403                                 LOGE("failed to commit.\n");
3404                 } else
3405                         LOGE("cannot get content attribute");
3406         } else {
3407                 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst)) {
3408                         LOGD("There is no audio track : remove audiobin");
3409
3410                         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
3411                         __mmplayer_del_sink(player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
3412
3413                         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->audiobin, MMPLAYER_A_BIN);
3414                         MMPLAYER_FREEIF(player->pipeline->audiobin)
3415                 }
3416
3417                 if (player->num_dynamic_pad == 0)
3418                         __mmplayer_pipeline_complete(NULL, player);
3419         }
3420
3421         if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
3422                 if (text_selector)
3423                         __mmplayer_handle_text_decode_path(player, text_selector);
3424         }
3425
3426         MMPLAYER_FLEAVE();
3427
3428 ERROR:
3429         if (srcpad) {
3430                 gst_object_unref(GST_OBJECT(srcpad));
3431                 srcpad = NULL;
3432         }
3433
3434         if (player->gapless.reconfigure) {
3435                 player->gapless.reconfigure = FALSE;
3436                 MMPLAYER_PLAYBACK_UNLOCK(player);
3437         }
3438 }
3439
3440 static void
3441 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // @
3442 {
3443         mm_player_t* player = NULL;
3444         MMHandleType attrs = 0;
3445         GstElement* pipeline = NULL;
3446         GstCaps* caps = NULL;
3447         gchar* caps_str = NULL;
3448         GstStructure* str = NULL;
3449         const gchar* name = NULL;
3450         GstPad* sinkpad = NULL;
3451         GstElement* sinkbin = NULL;
3452         gboolean reusing = FALSE;
3453         GstElement *text_selector = NULL;
3454         MMPlayerResourceState resource_state = RESOURCE_STATE_NONE;
3455
3456         /* check handles */
3457         player = (mm_player_t*) data;
3458
3459         MMPLAYER_RETURN_IF_FAIL(elem && pad);
3460         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
3461
3462         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3463
3464         attrs = MMPLAYER_GET_ATTRS(player);
3465         if (!attrs) {
3466                 LOGE("cannot get content attribute\n");
3467                 goto ERROR;
3468         }
3469
3470         /* get mimetype from caps */
3471         caps = gst_pad_query_caps(pad, NULL);
3472         if (!caps) {
3473                 LOGE("cannot get caps from pad.\n");
3474                 goto ERROR;
3475         }
3476         caps_str = gst_caps_to_string(caps);
3477
3478         str = gst_caps_get_structure(caps, 0);
3479         if (!str) {
3480                 LOGE("cannot get structure from caps.\n");
3481                 goto ERROR;
3482         }
3483
3484         name = gst_structure_get_name(str);
3485         if (!name) {
3486                 LOGE("cannot get mimetype from structure.\n");
3487                 goto ERROR;
3488         }
3489
3490         //LOGD("detected mimetype : %s\n", name);
3491
3492         if (strstr(name, "audio")) {
3493                 if (player->pipeline->audiobin == NULL) {
3494                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player)) {
3495                                 LOGE("failed to create audiobin. continuing without audio\n");
3496                                 goto ERROR;
3497                         }
3498
3499                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3500                         LOGD("creating audiosink bin success\n");
3501                 } else {
3502                         reusing = TRUE;
3503                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3504                         LOGD("reusing audiobin\n");
3505                         _mmplayer_update_content_attrs(player, ATTR_AUDIO);
3506                 }
3507
3508                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
3509                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
3510
3511                 player->audiosink_linked  = 1;
3512
3513                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
3514                 if (!sinkpad) {
3515                         LOGE("failed to get pad from sinkbin\n");
3516                         goto ERROR;
3517                 }
3518         } else if (strstr(name, "video")) {
3519                 if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12")))
3520                         player->set_mode.video_zc = TRUE;
3521
3522                 if (player->pipeline->videobin == NULL) {
3523                         /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
3524                         /* get video surface type */
3525                         int surface_type = 0;
3526                         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
3527                         LOGD("display_surface_type(%d)\n", surface_type);
3528
3529                         if (surface_type == MM_DISPLAY_SURFACE_NULL) {
3530                                 LOGD("not make videobin because it dose not want\n");
3531                                 goto ERROR;
3532                         }
3533
3534                         if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
3535                                 if (_mmplayer_resource_manager_get_state(&player->resource_manager, &resource_state) == MM_ERROR_NONE) {
3536                                         /* prepare resource manager for video overlay */
3537                                         if (resource_state >= RESOURCE_STATE_INITIALIZED) {
3538                                                 if (_mmplayer_resource_manager_prepare(&player->resource_manager, RESOURCE_TYPE_VIDEO_OVERLAY)
3539                                                         != MM_ERROR_NONE) {
3540                                                         LOGE("could not prepare for video_overlay resource\n");
3541                                                         goto ERROR;
3542                                                 }
3543                                         }
3544                                 }
3545                         }
3546
3547                         if (_mmplayer_resource_manager_get_state(&player->resource_manager, &resource_state)
3548                                 == MM_ERROR_NONE) {
3549                                 /* acquire resources for video playing */
3550                                 if (resource_state == RESOURCE_STATE_PREPARED) {
3551                                         if (_mmplayer_resource_manager_acquire(&player->resource_manager)
3552                                                 != MM_ERROR_NONE) {
3553                                                 LOGE("could not acquire resources for video playing\n");
3554                                                 _mmplayer_resource_manager_unprepare(&player->resource_manager);
3555                                                 goto ERROR;
3556                                         }
3557                                 }
3558                         }
3559
3560                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type)) {
3561                                 LOGE("failed to create videobin. continuing without video\n");
3562                                 goto ERROR;
3563                         }
3564
3565                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3566                         LOGD("creating videosink bin success\n");
3567                 } else {
3568                         reusing = TRUE;
3569                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3570                         LOGD("re-using videobin\n");
3571                         _mmplayer_update_content_attrs(player, ATTR_VIDEO);
3572                 }
3573
3574                 /* FIXIT : track number shouldn't be hardcoded */
3575                 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 1);
3576                 player->videosink_linked  = 1;
3577
3578                 /* NOTE : intermediate code before doing H/W subtitle compositon */
3579                 if (player->use_textoverlay && player->play_subtitle) {
3580                         LOGD("using textoverlay for external subtitle");
3581                         /* check text bin has created well */
3582                         if (player->pipeline && player->pipeline->textbin) {
3583                                 /* get sinkpad from textoverlay */
3584                                 sinkpad = gst_element_get_static_pad(
3585                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
3586                                         "video_sink");
3587                                 if (!sinkpad) {
3588                                         LOGE("failed to get sink pad from textoverlay");
3589                                         goto ERROR;
3590                                 }
3591
3592                                 /* link new pad with textoverlay first */
3593                                 if (GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad)) {
3594                                         LOGE("failed to get pad from sinkbin\n");
3595                                         goto ERROR;
3596                                 }
3597
3598                                 gst_object_unref(sinkpad);
3599                                 sinkpad = NULL;
3600
3601                                 /* alright, override pad to textbin.src for futher link */
3602                                 pad = gst_element_get_static_pad(
3603                                         GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
3604                                         "src");
3605                                 if (!pad) {
3606                                         LOGE("failed to get sink pad from textoverlay");
3607                                         goto ERROR;
3608                                 }
3609                         } else {
3610                                 LOGE("should not reach here.");
3611                                 goto ERROR;
3612                         }
3613                 }
3614
3615                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
3616                 if (!sinkpad) {
3617                         LOGE("failed to get pad from sinkbin\n");
3618                         goto ERROR;
3619                 }
3620         } else if (strstr(name, "text")) {
3621                 if (player->pipeline->textbin == NULL) {
3622                         MMPlayerGstElement* mainbin = NULL;
3623
3624                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player)) {
3625                                 LOGE("failed to create textbin. continuing without text\n");
3626                                 goto ERROR;
3627                         }
3628
3629                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3630                         LOGD("creating textsink bin success\n");
3631
3632                         /* FIXIT : track number shouldn't be hardcoded */
3633                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
3634
3635                         player->textsink_linked  = 1;
3636                         LOGI("player->textsink_linked set to 1\n");
3637
3638                         sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "text_sink");
3639                         if (!sinkpad) {
3640                                 LOGE("failed to get pad from sinkbin\n");
3641                                 goto ERROR;
3642                         }
3643
3644                         mainbin = player->pipeline->mainbin;
3645
3646                         if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst) {
3647                                 /* input selector */
3648                                 text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
3649                                 if (!text_selector) {
3650                                         LOGE("failed to create subtitle input selector element\n");
3651                                         goto ERROR;
3652                                 }
3653                                 g_object_set(text_selector, "sync-streams", TRUE, NULL);
3654
3655                                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
3656                                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
3657
3658                                 /* warm up */
3659                                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_READY)) {
3660                                         LOGE("failed to set state(READY) to sinkbin\n");
3661                                         goto ERROR;
3662                                 }
3663
3664                                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector)) {
3665                                         LOGW("failed to add subtitle input selector\n");
3666                                         goto ERROR;
3667                                 }
3668
3669                                 LOGD("created element input-selector");
3670
3671                         } else {
3672                                 LOGD("already having subtitle input selector");
3673                                 text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3674                         }
3675                 } else {
3676                         if (!player->textsink_linked) {
3677                                 LOGD("re-using textbin\n");
3678
3679                                 reusing = TRUE;
3680                                 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3681
3682                                 player->textsink_linked  = 1;
3683                                 LOGI("player->textsink_linked set to 1\n");
3684                         } else
3685                                 LOGD("ignoring internal subtutle since external subtitle is available");
3686                 }
3687         } else {
3688                 LOGW("unknown type of elementary stream!ignoring it...\n");
3689                 goto ERROR;
3690         }
3691
3692         if (sinkbin) {
3693                 if (!reusing) {
3694                         /* warm up */
3695                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_READY)) {
3696                                 LOGE("failed to set state(READY) to sinkbin\n");
3697                                 goto ERROR;
3698                         }
3699
3700                         /* Added for multi audio support to avoid adding audio bin again*/
3701                         /* add */
3702                         if (FALSE == gst_bin_add(GST_BIN(pipeline), sinkbin)) {
3703                                 LOGE("failed to add sinkbin to pipeline\n");
3704                                 goto ERROR;
3705                         }
3706                 }
3707
3708                 /* link */
3709                 if (GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad)) {
3710                         LOGE("failed to get pad from sinkbin\n");
3711                         goto ERROR;
3712                 }
3713
3714                 if (!reusing) {
3715                         /* run */
3716                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_PAUSED)) {
3717                                 LOGE("failed to set state(PAUSED) to sinkbin\n");
3718                                 goto ERROR;
3719                         }
3720
3721                         if (text_selector) {
3722                                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_PAUSED)) {
3723                                         LOGE("failed to set state(PAUSED) to sinkbin\n");
3724                                         goto ERROR;
3725                                 }
3726                         }
3727                 }
3728
3729                 gst_object_unref(sinkpad);
3730                 sinkpad = NULL;
3731         }
3732
3733         LOGD("linking sink bin success\n");
3734
3735         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
3736          * streaming task. if the task blocked, then buffer will not flow to the next element
3737          *(autoplugging element). so this is special hack for streaming. please try to remove it
3738          */
3739         /* dec stream count. we can remove fakesink if it's zero */
3740         if (player->num_dynamic_pad)
3741                 player->num_dynamic_pad--;
3742
3743         LOGD("no more pads: %d stream count dec : %d(num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
3744
3745         if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
3746                 __mmplayer_pipeline_complete(NULL, player);
3747
3748         /* FIXIT : please leave a note why this code is needed */
3749         if (MMPLAYER_IS_WFD_STREAMING(player))
3750                 player->no_more_pad = TRUE;
3751
3752 ERROR:
3753
3754         MMPLAYER_FREEIF(caps_str);
3755
3756         if (caps)
3757                 gst_caps_unref(caps);
3758
3759         if (sinkpad)
3760                 gst_object_unref(GST_OBJECT(sinkpad));
3761
3762         /* flusing out new attributes */
3763         if (mmf_attrs_commit(attrs))
3764                 LOGE("failed to comit attributes\n");
3765
3766         return;
3767 }
3768
3769 static gboolean
3770 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
3771 {
3772         int pro_value = 0; // in the case of expection, default will be returned.
3773         int dest_angle = rotation_angle;
3774         int rotation_type = -1;
3775
3776         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
3777         MMPLAYER_RETURN_VAL_IF_FAIL(value, FALSE);
3778         MMPLAYER_RETURN_VAL_IF_FAIL(rotation_angle >= 0, FALSE);
3779
3780         if (rotation_angle >= 360)
3781                 dest_angle = rotation_angle - 360;
3782
3783         /* chech if supported or not */
3784         if (dest_angle % 90) {
3785                 LOGD("not supported rotation angle = %d", rotation_angle);
3786                 return FALSE;
3787         }
3788
3789         /*
3790           * waylandsink (A)
3791           * custom_convert - none (B)
3792           * videoflip - none (C)
3793           */
3794         if (player->set_mode.video_zc) {
3795                 if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
3796                         rotation_type = ROTATION_USING_CUSTOM;
3797                 else // A
3798                         rotation_type = ROTATION_USING_SINK;
3799         } else {
3800                 int surface_type = 0;
3801                 rotation_type = ROTATION_USING_FLIP;
3802
3803                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
3804                 LOGD("check display surface type attribute: %d", surface_type);
3805
3806                 if (surface_type == MM_DISPLAY_SURFACE_OVERLAY)
3807                         rotation_type = ROTATION_USING_SINK;
3808                 else
3809                         rotation_type = ROTATION_USING_FLIP; //C
3810
3811                 LOGD("using %d type for rotation", rotation_type);
3812         }
3813
3814         /* get property value for setting */
3815         switch (rotation_type) {
3816         case ROTATION_USING_SINK: // waylandsink
3817                 {
3818                         switch (dest_angle) {
3819                         case 0:
3820                                 break;
3821                         case 90:
3822                                 pro_value = 3; // clockwise 90
3823                                 break;
3824                         case 180:
3825                                 pro_value = 2;
3826                                 break;
3827                         case 270:
3828                                 pro_value = 1; // counter-clockwise 90
3829                                 break;
3830                         }
3831                 }
3832                 break;
3833         case ROTATION_USING_CUSTOM:
3834                 {
3835                         gchar *ename = NULL;
3836                         ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
3837
3838                         if (g_strrstr(ename, "fimcconvert")) {
3839                                 switch (dest_angle) {
3840                                 case 0:
3841                                         break;
3842                                 case 90:
3843                                         pro_value = 90; // clockwise 90
3844                                         break;
3845                                 case 180:
3846                                         pro_value = 180;
3847                                         break;
3848                                 case 270:
3849                                         pro_value = 270; // counter-clockwise 90
3850                                         break;
3851                                 }
3852                         }
3853                 }
3854                 break;
3855         case ROTATION_USING_FLIP: // videoflip
3856                 {
3857                                 switch (dest_angle) {
3858                                 case 0:
3859                                         break;
3860                                 case 90:
3861                                         pro_value = 1; // clockwise 90
3862                                         break;
3863                                 case 180:
3864                                         pro_value = 2;
3865                                         break;
3866                                 case 270:
3867                                         pro_value = 3; // counter-clockwise 90
3868                                         break;
3869                                 }
3870                 }
3871                 break;
3872         }
3873
3874         LOGD("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
3875
3876         *value = pro_value;
3877
3878         return TRUE;
3879 }
3880
3881 int
3882 __mmplayer_video_param_check_video_sink_bin(mm_player_t* player)
3883 {
3884         /* check video sinkbin is created */
3885         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
3886                 player->pipeline &&
3887                 player->pipeline->videobin &&
3888                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
3889                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
3890                 MM_ERROR_PLAYER_NOT_INITIALIZED);
3891
3892         return MM_ERROR_NONE;
3893 }
3894
3895 void
3896 __mmplayer_video_param_set_display_rotation(mm_player_t* player)
3897 {
3898         int rotation_value = 0;
3899         int org_angle = 0; // current supported angle values are 0, 90, 180, 270
3900         int user_angle = 0;
3901         MMPLAYER_FENTER();
3902
3903         /* check video sinkbin is created */
3904         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3905                 return;
3906
3907         __mmplayer_get_video_angle(player, &user_angle, &org_angle);
3908
3909         /* get rotation value to set */
3910         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
3911         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "rotate", rotation_value, NULL);
3912         LOGD("set video param : rotate %d", rotation_value);
3913 }
3914
3915 void
3916 __mmplayer_video_param_set_display_visible(mm_player_t* player)
3917 {
3918         MMHandleType attrs = 0;
3919         int visible = 0;
3920         MMPLAYER_FENTER();
3921
3922         /* check video sinkbin is created */
3923         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3924                 return;
3925
3926         attrs = MMPLAYER_GET_ATTRS(player);
3927         MMPLAYER_RETURN_IF_FAIL(attrs);
3928
3929         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
3930         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "visible", visible, NULL);
3931         LOGD("set video param : visible %d", visible);
3932 }
3933
3934 void
3935 __mmplayer_video_param_set_display_method(mm_player_t* player)
3936 {
3937         MMHandleType attrs = 0;
3938         int display_method = 0;
3939         MMPLAYER_FENTER();
3940
3941         /* check video sinkbin is created */
3942         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3943                 return;
3944
3945         attrs = MMPLAYER_GET_ATTRS(player);
3946         MMPLAYER_RETURN_IF_FAIL(attrs);
3947
3948         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
3949         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "display-geometry-method", display_method, NULL);
3950         LOGD("set video param : method %d", display_method);
3951 }
3952
3953 void
3954 __mmplayer_video_param_set_render_rectangle(mm_player_t* player)
3955 {
3956         MMHandleType attrs = 0;
3957         int display_method = 0;
3958         void *handle = NULL;
3959         /*set wl_display*/
3960         int wl_window_x = 0;
3961         int wl_window_y = 0;
3962         int wl_window_width = 0;
3963         int wl_window_height = 0;
3964         MMPLAYER_FENTER();
3965
3966         /* check video sinkbin is created */
3967         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3968                 return;
3969
3970         attrs = MMPLAYER_GET_ATTRS(player);
3971         MMPLAYER_RETURN_IF_FAIL(attrs);
3972
3973         /* check roi mode is set */
3974         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
3975         if (display_method != PLAYER_DISPLAY_MODE_DST_ROI) {
3976                 LOGE("must be set display-geometry-method to DISP_GEO_METHOD_CUSTOM_ROI before setting render rectangle");
3977                 return;
3978         }
3979         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
3980
3981         if (handle) {
3982                 /*It should be set after setting window*/
3983                 mm_attrs_get_int_by_name(attrs, "wl_window_render_x", &wl_window_x);
3984                 mm_attrs_get_int_by_name(attrs, "wl_window_render_y", &wl_window_y);
3985                 mm_attrs_get_int_by_name(attrs, "wl_window_render_width", &wl_window_width);
3986                 mm_attrs_get_int_by_name(attrs, "wl_window_render_height", &wl_window_height);
3987
3988                 /* After setting window handle, set render      rectangle */
3989                 gst_video_overlay_set_render_rectangle(
3990                          GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
3991                          wl_window_x, wl_window_y, wl_window_width, wl_window_height);
3992                 LOGD("set video param : render rectangle : x(%d) y(%d) width(%d) height(%d)",
3993                         wl_window_x, wl_window_y, wl_window_width, wl_window_height);
3994
3995         }
3996 }
3997 void
3998 __mmplayer_video_param_set_display_overlay(mm_player_t* player)
3999 {
4000         MMHandleType attrs = 0;
4001         void *handle = NULL;
4002         /*use wl_surface*/
4003         gboolean use_wl_surface = 0;
4004         void * wl_display = NULL;
4005         GstContext *context = NULL;
4006
4007         /* check video sinkbin is created */
4008         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
4009                 return;
4010
4011         attrs = MMPLAYER_GET_ATTRS(player);
4012         MMPLAYER_RETURN_IF_FAIL(attrs);
4013
4014         /* common case if using overlay surface */
4015         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
4016         mm_attrs_get_int_by_name(attrs, "use_wl_surface", &use_wl_surface);
4017
4018         if (handle && !use_wl_surface) {
4019                 /* default is using wl_surface_id */
4020                 unsigned int wl_surface_id      = 0;
4021                 wl_surface_id = *(int*)handle;
4022                 LOGD("set video param : wl_surface_id %d %p", wl_surface_id, *(int*)handle);
4023                 gst_video_overlay_set_wl_window_wl_surface_id(
4024                                 GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
4025                                 *(int*)handle);
4026         } else if (handle && use_wl_surface) {
4027                 /* use wl_surface for legacy_player_test */
4028                 mm_attrs_get_data_by_name(attrs, "wl_display", &wl_display);
4029                 if (wl_display)
4030                         context = gst_wayland_display_handle_context_new(wl_display);
4031                 if (context)
4032                         gst_element_set_context(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), context);
4033
4034                 guintptr wl_surface = (guintptr)handle;
4035                 LOGD("[use wl_surface for legacy_player_test] set video param : wayland surface %p", handle);
4036                 gst_video_overlay_set_window_handle(
4037                                 GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
4038                                 wl_surface);
4039         } else
4040                 /* FIXIT : is it error case? */
4041                 LOGW("still we don't have a window handle on player attribute. create it's own surface.");
4042 }
4043
4044
4045 int
4046 __mmplayer_update_wayland_videosink_video_param(mm_player_t* player, char *param_name)
4047 {
4048         bool update_all_param = FALSE;
4049         MMPLAYER_FENTER();
4050
4051         /* check video sinkbin is created */
4052         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
4053                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
4054
4055         if (strcmp(player->ini.videosink_element_overlay, "waylandsink")) {
4056                 LOGE("can not find waylandsink");
4057                 return MM_ERROR_PLAYER_INTERNAL;
4058         }
4059
4060         LOGD("param_name : %s", param_name);
4061         if (!g_strcmp0(param_name, "update_all_param"))
4062                 update_all_param = TRUE;
4063
4064         if (update_all_param || !g_strcmp0(param_name, "display_overlay"))
4065                 __mmplayer_video_param_set_display_overlay(player);
4066         if (update_all_param || !g_strcmp0(param_name, "display_method"))
4067                 __mmplayer_video_param_set_display_method(player);
4068         if (update_all_param || !g_strcmp0(param_name, "wl_window_render_x"))
4069                 __mmplayer_video_param_set_render_rectangle(player);
4070         if (update_all_param || !g_strcmp0(param_name, "display_visible"))
4071                 __mmplayer_video_param_set_display_visible(player);
4072         if (update_all_param || !g_strcmp0(param_name, "display_rotation"))
4073                 __mmplayer_video_param_set_display_rotation(player);
4074
4075         return MM_ERROR_NONE;
4076 }
4077
4078 int
4079 _mmplayer_update_video_param(mm_player_t* player, char *param_name) // @
4080 {
4081         MMHandleType attrs = 0;
4082         int surface_type = 0;
4083         int ret = MM_ERROR_NONE;
4084
4085         MMPLAYER_FENTER();
4086
4087         /* check video sinkbin is created */
4088         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
4089                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
4090
4091         attrs = MMPLAYER_GET_ATTRS(player);
4092         if (!attrs) {
4093                 LOGE("cannot get content attribute");
4094                 return MM_ERROR_PLAYER_INTERNAL;
4095         }
4096         LOGD("param_name : %s", param_name);
4097
4098         /* update display surface */
4099         mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
4100         LOGD("check display surface type attribute: %d", surface_type);
4101
4102         /* configuring display */
4103         switch (surface_type) {
4104         case MM_DISPLAY_SURFACE_OVERLAY:
4105                 {
4106                         ret = __mmplayer_update_wayland_videosink_video_param(player, param_name);
4107                         if (ret != MM_ERROR_NONE)
4108                                 return ret;
4109                 }
4110                 break;
4111         }
4112
4113         MMPLAYER_FLEAVE();
4114
4115         return MM_ERROR_NONE;
4116 }
4117
4118 static int
4119 __mmplayer_gst_element_link_bucket(GList* element_bucket) // @
4120 {
4121         GList* bucket = element_bucket;
4122         MMPlayerGstElement* element = NULL;
4123         MMPlayerGstElement* prv_element = NULL;
4124         gint successful_link_count = 0;
4125
4126         MMPLAYER_FENTER();
4127
4128         MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, -1);
4129
4130         prv_element = (MMPlayerGstElement*)bucket->data;
4131         bucket = bucket->next;
4132
4133         for (; bucket; bucket = bucket->next) {
4134                 element = (MMPlayerGstElement*)bucket->data;
4135
4136                 if (element && element->gst) {
4137                         /* If next element is audio appsrc then make a separate audio pipeline */
4138                         if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "audio_appsrc") ||
4139                                 !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "subtitle_appsrc")) {
4140                                 prv_element = element;
4141                                 continue;
4142                         }
4143
4144                         if (prv_element && prv_element->gst) {
4145                                 if (GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst))) {
4146                                         LOGD("linking [%s] to [%s] success\n",
4147                                                 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4148                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
4149                                         successful_link_count++;
4150                                 } else {
4151                                         LOGD("linking [%s] to [%s] failed\n",
4152                                                 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4153                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
4154                                         return -1;
4155                                 }
4156                         }
4157                 }
4158
4159                 prv_element = element;
4160         }
4161
4162         MMPLAYER_FLEAVE();
4163
4164         return successful_link_count;
4165 }
4166
4167 static int
4168 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket) // @
4169 {
4170         GList* bucket = element_bucket;
4171         MMPlayerGstElement* element = NULL;
4172         int successful_add_count = 0;
4173
4174         MMPLAYER_FENTER();
4175
4176         MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, 0);
4177         MMPLAYER_RETURN_VAL_IF_FAIL(bin, 0);
4178
4179         for (; bucket; bucket = bucket->next) {
4180                 element = (MMPlayerGstElement*)bucket->data;
4181
4182                 if (element && element->gst) {
4183                         if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
4184                                 LOGD("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
4185                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
4186                                         GST_ELEMENT_NAME(GST_ELEMENT(bin)));
4187                                 return 0;
4188                         }
4189                         successful_add_count++;
4190                 }
4191         }
4192
4193         MMPLAYER_FLEAVE();
4194
4195         return successful_add_count;
4196 }
4197
4198 static void __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data)
4199 {
4200         mm_player_t* player = (mm_player_t*) data;
4201         GstCaps *caps = NULL;
4202         GstStructure *str = NULL;
4203         const char *name;
4204
4205         MMPLAYER_FENTER();
4206
4207         MMPLAYER_RETURN_IF_FAIL(pad)
4208         MMPLAYER_RETURN_IF_FAIL(unused)
4209         MMPLAYER_RETURN_IF_FAIL(data)
4210
4211         caps = gst_pad_get_current_caps(pad);
4212         if (!caps)
4213                 return;
4214
4215         str = gst_caps_get_structure(caps, 0);
4216         if (!str)
4217                 goto ERROR;
4218
4219         name = gst_structure_get_name(str);
4220         if (!name)
4221                 goto ERROR;
4222
4223         LOGD("name = %s\n", name);
4224
4225         if (strstr(name, "audio")) {
4226                 _mmplayer_update_content_attrs(player, ATTR_AUDIO);
4227
4228                 if (player->audio_stream_changed_cb) {
4229                         LOGE("call the audio stream changed cb\n");
4230                         player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
4231                 }
4232         } else if (strstr(name, "video")) {
4233                 _mmplayer_update_content_attrs(player, ATTR_VIDEO);
4234
4235                 if (player->video_stream_changed_cb) {
4236                         LOGE("call the video stream changed cb\n");
4237                         player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
4238                 }
4239         } else
4240                 goto ERROR;
4241
4242 ERROR:
4243
4244         gst_caps_unref(caps);
4245
4246         MMPLAYER_FLEAVE();
4247
4248         return;
4249 }
4250
4251
4252
4253 /**
4254  * This function is to create audio pipeline for playing.
4255  *
4256  * @param       player          [in]    handle of player
4257  *
4258  * @return      This function returns zero on success.
4259  * @remark
4260  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
4261  */
4262 #define MMPLAYER_CREATEONLY_ELEMENT(x_bin, x_id, x_factory, x_name) \
4263 x_bin[x_id].id = x_id;\
4264 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4265 if (!x_bin[x_id].gst) {\
4266         LOGE("failed to create %s \n", x_factory);\
4267         goto ERROR;\
4268 } \
4269
4270 #define MMPLAYER_CREATE_ELEMENT_ADD_BIN(x_bin, x_id, x_factory, x_name, y_bin, x_player) \
4271 x_bin[x_id].id = x_id;\
4272 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4273 if (!x_bin[x_id].gst) {\
4274         LOGE("failed to create %s \n", x_factory);\
4275         goto ERROR;\
4276 } else {\
4277         if (x_player->ini.set_dump_element_flag)\
4278                 __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
4279 } \
4280 if (!gst_bin_add(GST_BIN(y_bin), GST_ELEMENT(x_bin[x_id].gst))) { \
4281         LOGD("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",\
4282                 GST_ELEMENT_NAME(GST_ELEMENT(x_bin[x_id].gst)),\
4283                 GST_ELEMENT_NAME(GST_ELEMENT(y_bin)));\
4284         goto ERROR;\
4285 } \
4286
4287 /* macro for code readability. just for sinkbin-creation functions */
4288 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
4289 do {\
4290         x_bin[x_id].id = x_id;\
4291         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4292         if (!x_bin[x_id].gst) {\
4293                 LOGE("failed to create %s \n", x_factory);\
4294                 goto ERROR;\
4295         } else {\
4296                 if (x_player->ini.set_dump_element_flag)\
4297                         __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
4298         } \
4299         if (x_add_bucket)\
4300                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
4301 } while (0);
4302
4303 static void
4304 __mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all)
4305 {
4306         GList *l = NULL;
4307
4308         MMPLAYER_FENTER();
4309         MMPLAYER_RETURN_IF_FAIL(player);
4310
4311         if (player->audio_stream_buff_list) {
4312                 for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
4313                         mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
4314                         if (tmp) {
4315                                 if (send_all) {
4316                                         LOGD("[%lld] send remained data.", tmp->channel_mask);
4317                                         __mmplayer_audio_stream_send_data(player, tmp);
4318                                 }
4319                                 if (tmp->pcm_data)
4320                                         g_free(tmp->pcm_data);
4321                                 g_free(tmp);
4322                         }
4323                 }
4324                 g_list_free(player->audio_stream_buff_list);
4325                 player->audio_stream_buff_list = NULL;
4326         }
4327
4328         MMPLAYER_FLEAVE();
4329 }
4330
4331 static void
4332 __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer)
4333 {
4334         MMPlayerAudioStreamDataType audio_stream = { 0, };
4335
4336         MMPLAYER_FENTER();
4337         MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
4338
4339         audio_stream.bitrate = a_buffer->bitrate;
4340         audio_stream.channel = a_buffer->channel;
4341         audio_stream.depth = a_buffer->depth;
4342         audio_stream.is_little_endian = a_buffer->is_little_endian;
4343         audio_stream.channel_mask = a_buffer->channel_mask;
4344         audio_stream.data_size = a_buffer->data_size;
4345         audio_stream.data = a_buffer->pcm_data;
4346
4347         /* LOGD("[%lld] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_stream_cb_user_param); */
4348         player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param);
4349
4350         MMPLAYER_FLEAVE();
4351 }
4352
4353 static void
4354 __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
4355 {
4356         mm_player_t* player = (mm_player_t*) data;
4357
4358         gint channel = 0;
4359         gint rate = 0;
4360         gint depth = 0;
4361         gint endianness = 0;
4362         guint64 channel_mask = 0;
4363         void *a_data = NULL;
4364         gint a_size = 0;
4365         mm_player_audio_stream_buff_t *a_buffer = NULL;
4366         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
4367         GList *l = NULL;
4368
4369         MMPLAYER_FENTER();
4370         MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
4371
4372         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
4373         a_data = mapinfo.data;
4374         a_size = mapinfo.size;
4375
4376         GstCaps *caps = gst_pad_get_current_caps(pad);
4377         GstStructure *structure = gst_caps_get_structure(caps, 0);
4378
4379         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
4380         gst_structure_get_int(structure, "rate", &rate);
4381         gst_structure_get_int(structure, "channels", &channel);
4382         gst_structure_get_int(structure, "depth", &depth);
4383         gst_structure_get_int(structure, "endianness", &endianness);
4384         gst_structure_get(structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
4385         gst_caps_unref(GST_CAPS(caps));
4386
4387         /* In case of the sync is false, use buffer list.              *
4388          * The num of buffer list depends on the num of audio channels */
4389         if (player->audio_stream_buff_list) {
4390                 for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
4391                         mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
4392                         if (tmp) {
4393                                 if (channel_mask == tmp->channel_mask) {
4394                                         /* LOGD("[%lld] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size); */
4395                                         if (tmp->data_size + a_size < tmp->buff_size) {
4396                                                 memcpy(tmp->pcm_data + tmp->data_size, a_data, a_size);
4397                                                 tmp->data_size += a_size;
4398                                         } else {
4399                                                 /* send data to client */
4400                                                 __mmplayer_audio_stream_send_data(player, tmp);
4401
4402                                                 if (a_size > tmp->buff_size) {
4403                                                         LOGD("[%lld] adj buffer size %d -> %d", channel_mask, tmp->buff_size, a_size);
4404                                                         tmp->pcm_data = g_realloc(tmp->pcm_data, a_size);
4405                                                         if (tmp->pcm_data == NULL) {
4406                                                                 LOGE("failed to realloc data.");
4407                                                                 goto DONE;
4408                                                         }
4409                                                         tmp->buff_size = a_size;
4410                                                 }
4411                                                 memset(tmp->pcm_data, 0x00, tmp->buff_size);
4412                                                 memcpy(tmp->pcm_data, a_data, a_size);
4413                                                 tmp->data_size = a_size;
4414                                         }
4415                                         goto DONE;
4416                                 }
4417                         } else {
4418                                 LOGE("data is empty in list.");
4419                                 goto DONE;
4420                         }
4421                 }
4422         }
4423
4424         /* create new audio stream data */
4425         a_buffer = (mm_player_audio_stream_buff_t*)g_malloc0(sizeof(mm_player_audio_stream_buff_t));
4426         if (a_buffer == NULL) {
4427                 LOGE("failed to alloc data.");
4428                 goto DONE;
4429         }
4430         a_buffer->bitrate = rate;
4431         a_buffer->channel = channel;
4432         a_buffer->depth = depth;
4433         a_buffer->is_little_endian = (endianness == 1234 ? 1 : 0);
4434         a_buffer->channel_mask = channel_mask;
4435         a_buffer->data_size = a_size;
4436
4437         if (!player->audio_stream_sink_sync) {
4438                 /* If sync is FALSE, use buffer list to reduce the IPC. */
4439                 a_buffer->buff_size = (a_size > player->ini.pcm_buffer_size) ? (a_size) : (player->ini.pcm_buffer_size);
4440                 a_buffer->pcm_data = g_malloc(a_buffer->buff_size);
4441                 if (a_buffer->pcm_data == NULL) {
4442                         LOGE("failed to alloc data.");
4443                         g_free(a_buffer);
4444                         goto DONE;
4445                 }
4446                 memcpy(a_buffer->pcm_data, a_data, a_size);
4447                 /* LOGD("new [%lld] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size); */
4448                 player->audio_stream_buff_list = g_list_append(player->audio_stream_buff_list, a_buffer);
4449         } else {
4450                 /* If sync is TRUE, send data directly. */
4451                 a_buffer->pcm_data = a_data;
4452                 __mmplayer_audio_stream_send_data(player, a_buffer);
4453                 g_free(a_buffer);
4454         }
4455
4456 DONE:
4457         gst_buffer_unmap(buffer, &mapinfo);
4458         MMPLAYER_FLEAVE();
4459 }
4460
4461 static void
4462 __mmplayer_gst_audio_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
4463 {
4464         mm_player_t* player = (mm_player_t*)data;
4465         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
4466         GstPad* sinkpad = NULL;
4467         GstElement *queue = NULL, *sink = NULL;
4468
4469         MMPLAYER_FENTER();
4470         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
4471
4472         queue = gst_element_factory_make("queue", NULL);
4473         if (queue == NULL) {
4474                 LOGD("fail make queue\n");
4475                 goto ERROR;
4476         }
4477
4478         sink = gst_element_factory_make("fakesink", NULL);
4479         if (sink == NULL) {
4480                 LOGD("fail make fakesink\n");
4481                 goto ERROR;
4482         }
4483
4484         gst_bin_add_many(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
4485
4486         if (!gst_element_link_pads_full(queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING)) {
4487                 LOGW("failed to link queue & sink\n");
4488                 goto ERROR;
4489         }
4490
4491         sinkpad = gst_element_get_static_pad(queue, "sink");
4492
4493         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
4494                 LOGW("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
4495                 goto ERROR;
4496         }
4497
4498         LOGE("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
4499
4500         gst_object_unref(sinkpad);
4501         g_object_set(sink, "sync", player->audio_stream_sink_sync, NULL);
4502         g_object_set(sink, "signal-handoffs", TRUE, NULL);
4503
4504         gst_element_set_state(sink, GST_STATE_PAUSED);
4505         gst_element_set_state(queue, GST_STATE_PAUSED);
4506
4507         MMPLAYER_SIGNAL_CONNECT(player,
4508                 G_OBJECT(sink),
4509                 MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4510                 "handoff",
4511                 G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
4512                 (gpointer)player);
4513
4514         MMPLAYER_FLEAVE();
4515         return ;
4516
4517 ERROR:
4518         LOGE("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
4519         if (queue) {
4520                 gst_object_unref(GST_OBJECT(queue));
4521                 queue = NULL;
4522         }
4523         if (sink) {
4524                 gst_object_unref(GST_OBJECT(sink));
4525                 sink = NULL;
4526         }
4527         if (sinkpad) {
4528                 gst_object_unref(GST_OBJECT(sinkpad));
4529                 sinkpad = NULL;
4530         }
4531
4532         return;
4533 }
4534
4535 void __mmplayer_gst_set_audiosink_property(mm_player_t* player, MMHandleType attrs)
4536 {
4537         #define MAX_PROPS_LEN 128
4538         gint latency_mode = 0;
4539         gchar *stream_type = NULL;
4540         gchar *latency = NULL;
4541         gint stream_id = 0;
4542         gchar stream_props[MAX_PROPS_LEN] = {0,};
4543         GstStructure *props = NULL;
4544
4545         /* set volume table
4546          * It should be set after player creation through attribute.
4547          * But, it can not be changed during playing.
4548          */
4549         MMPLAYER_FENTER();
4550         mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
4551         mm_attrs_get_string_by_name(attrs, "sound_stream_type", &stream_type);
4552
4553         if (!stream_type) {
4554                 LOGE("stream_type is null.\n");
4555         } else {
4556                 if (player->sound_focus.focus_id)
4557                         snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d, media.focus_id=%d",
4558                                         stream_type, stream_id, player->sound_focus.focus_id);
4559                 else
4560                         snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d",
4561                                         stream_type, stream_id);
4562                 props = gst_structure_from_string(stream_props, NULL);
4563                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
4564                 LOGI("stream_type[%s], stream_id[%d], focus_id[%d], result[%s].\n", stream_type, stream_id, player->sound_focus.focus_id, stream_props);
4565         }
4566
4567         mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
4568
4569         switch (latency_mode) {
4570         case AUDIO_LATENCY_MODE_LOW:
4571                 latency = g_strndup("low", 3);
4572                 break;
4573         case AUDIO_LATENCY_MODE_MID:
4574                 latency = g_strndup("mid", 3);
4575                 break;
4576         case AUDIO_LATENCY_MODE_HIGH:
4577                 latency = g_strndup("high", 4);
4578                 break;
4579         };
4580
4581 #if 0 //need to check
4582         if (player->sound_focus.user_route_policy != 0)
4583                 route_path = player->sound_focus.user_route_policy;
4584
4585         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
4586                         "latency", latency_mode,
4587                         NULL);
4588
4589         LOGD("audiosink property status...volume type:%d, user-route=%d, latency=%d \n",
4590                 volume_type, route_path, latency_mode);
4591         MMPLAYER_FLEAVE();
4592
4593 #endif
4594
4595         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
4596                         "latency", latency,
4597                         NULL);
4598
4599         LOGD("audiosink property - latency=%s \n", latency);
4600
4601         g_free(latency);
4602
4603         MMPLAYER_FLEAVE();
4604 }
4605
4606 static int
4607 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
4608 {
4609         MMPlayerGstElement* first_element = NULL;
4610         MMPlayerGstElement* audiobin = NULL;
4611         MMHandleType attrs = 0;
4612         GstPad *pad = NULL;
4613         GstPad *ghostpad = NULL;
4614         GList* element_bucket = NULL;
4615         gboolean link_audio_sink_now = TRUE;
4616         int i = 0;
4617
4618         MMPLAYER_FENTER();
4619
4620         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4621
4622         /* alloc handles */
4623         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
4624         if (!audiobin) {
4625                 LOGE("failed to allocate memory for audiobin\n");
4626                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
4627         }
4628
4629         attrs = MMPLAYER_GET_ATTRS(player);
4630
4631         /* create bin */
4632         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
4633         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
4634         if (!audiobin[MMPLAYER_A_BIN].gst) {
4635                 LOGE("failed to create audiobin\n");
4636                 goto ERROR;
4637         }
4638
4639         /* take it */
4640         player->pipeline->audiobin = audiobin;
4641
4642         player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
4643
4644         /* Adding audiotp plugin for reverse trickplay feature */
4645 //      MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
4646
4647         /* converter */
4648         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
4649
4650         /* resampler */
4651         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER,  player->ini.audioresampler_element, "audio resampler", TRUE, player);
4652
4653         if (player->set_mode.pcm_extraction) {
4654                 // pcm extraction only and no sound output
4655                 if (player->audio_stream_render_cb_ex) {
4656                         char *caps_str = NULL;
4657                         GstCaps* caps = NULL;
4658                         gchar *format = NULL;
4659
4660                         /* capsfilter */
4661                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4662
4663                         mm_attrs_get_string_by_name(player->attrs, "pcm_audioformat", &format);
4664
4665                         LOGD("contents : format: %s samplerate : %d pcm_channel: %d", format, player->pcm_samplerate, player->pcm_channel);
4666
4667                         caps = gst_caps_new_simple("audio/x-raw",
4668                                         "format", G_TYPE_STRING, format,
4669                                         "rate", G_TYPE_INT, player->pcm_samplerate,
4670                                         "channels", G_TYPE_INT, player->pcm_channel,
4671                                         NULL);
4672                         caps_str = gst_caps_to_string(caps);
4673                         LOGD("new caps : %s\n", caps_str);
4674
4675                         g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4676
4677                         /* clean */
4678                         gst_caps_unref(caps);
4679                         MMPLAYER_FREEIF(caps_str);
4680
4681                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
4682
4683                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
4684                         /* raw pad handling signal */
4685                         MMPLAYER_SIGNAL_CONNECT(player,
4686                                 (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
4687                                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
4688                                                                                                 G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
4689                 } else {
4690                         int dst_samplerate = 0;
4691                         int dst_channels = 0;
4692                         int dst_depth = 0;
4693                         char *caps_str = NULL;
4694                         GstCaps* caps = NULL;
4695
4696                         /* get conf. values */
4697                         mm_attrs_multiple_get(player->attrs,
4698                                                 NULL,
4699                                                 "pcm_extraction_samplerate", &dst_samplerate,
4700                                                 "pcm_extraction_channels", &dst_channels,
4701                                                 "pcm_extraction_depth", &dst_depth,
4702                                                 NULL);
4703
4704                         /* capsfilter */
4705                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4706                         caps = gst_caps_new_simple("audio/x-raw",
4707                                         "rate", G_TYPE_INT, dst_samplerate,
4708                                         "channels", G_TYPE_INT, dst_channels,
4709                                         "depth", G_TYPE_INT, dst_depth,
4710                                         NULL);
4711                         caps_str = gst_caps_to_string(caps);
4712                         LOGD("new caps : %s\n", caps_str);
4713
4714                         g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4715
4716                         /* clean */
4717                         gst_caps_unref(caps);
4718                         MMPLAYER_FREEIF(caps_str);
4719
4720                         /* fake sink */
4721                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
4722
4723                         /* set sync */
4724                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
4725                 }
4726         } else {
4727                 // normal playback
4728                 //GstCaps* caps = NULL;
4729                 gint channels = 0;
4730
4731                 /* for logical volume control */
4732                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
4733                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
4734
4735                 if (player->sound.mute) {
4736                         LOGD("mute enabled\n");
4737                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
4738                 }
4739
4740 #if 0
4741                 /*capsfilter */
4742                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
4743                 caps = gst_caps_from_string("audio/x-raw-int, "
4744                                         "endianness = (int) LITTLE_ENDIAN, "
4745                                         "signed = (boolean) true, "
4746                                         "width = (int) 16, "
4747                                         "depth = (int) 16");
4748                 g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4749                 gst_caps_unref(caps);
4750 #endif
4751
4752                 /* chech if multi-chennels */
4753                 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) {
4754                         GstPad *srcpad = NULL;
4755                         GstCaps *caps = NULL;
4756
4757                         if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src"))) {
4758                                 if ((caps = gst_pad_query_caps(srcpad, NULL))) {
4759                                         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
4760                                         GstStructure *str = gst_caps_get_structure(caps, 0);
4761                                         if (str)
4762                                                 gst_structure_get_int(str, "channels", &channels);
4763                                         gst_caps_unref(caps);
4764                                 }
4765                                 gst_object_unref(srcpad);
4766                         }
4767                 }
4768
4769                 /* audio effect element. if audio effect is enabled */
4770                 if ((strcmp(player->ini.audioeffect_element, ""))
4771                         && (channels <= 2)
4772                         && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
4773                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.audioeffect_element, "audio effect filter", TRUE, player);
4774
4775                         LOGD("audio effect config. bypass = %d, effect type  = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
4776
4777                         if ((!player->bypass_audio_effect)
4778                                 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
4779                                 if (MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type) {
4780                                         if (!_mmplayer_audio_effect_custom_apply(player))
4781                                                 LOGI("apply audio effect(custom) setting success\n");
4782                                 }
4783                         }
4784
4785                         if ((strcmp(player->ini.audioeffect_element_custom, ""))
4786                                 && (player->set_mode.rich_audio))
4787                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.audioeffect_element_custom, "audio effect filter custom", TRUE, player);
4788                 }
4789
4790                 /* create audio sink */
4791                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", link_audio_sink_now, player);
4792
4793                 /* qos on */
4794                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);       /* qos on */
4795                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
4796
4797
4798                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) ||
4799                         (player->videodec_linked && player->ini.use_system_clock)) {
4800                         LOGD("system clock will be used.\n");
4801                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE,  NULL);
4802                 }
4803
4804                 if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
4805                         __mmplayer_gst_set_audiosink_property(player, attrs);
4806         }
4807
4808         if (audiobin[MMPLAYER_A_SINK].gst) {
4809                 GstPad *sink_pad = NULL;
4810                 sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
4811                 MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4812                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
4813                 gst_object_unref(GST_OBJECT(sink_pad));
4814         }
4815
4816         __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
4817
4818         /* adding created elements to bin */
4819         LOGD("adding created elements to bin\n");
4820         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket)) {
4821                 LOGE("failed to add elements\n");
4822                 goto ERROR;
4823         }
4824
4825         /* linking elements in the bucket by added order. */
4826         LOGD("Linking elements in the bucket by added order.\n");
4827         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
4828                 LOGE("failed to link elements\n");
4829                 goto ERROR;
4830         }
4831
4832         /* get first element's sinkpad for creating ghostpad */
4833         first_element = (MMPlayerGstElement *)element_bucket->data;
4834         if (!first_element) {
4835                 LOGE("failed to get first elem\n");
4836                 goto ERROR;
4837         }
4838
4839         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
4840         if (!pad) {
4841                 LOGE("failed to get pad from first element of audiobin\n");
4842                 goto ERROR;
4843         }
4844
4845         ghostpad = gst_ghost_pad_new("sink", pad);
4846         if (!ghostpad) {
4847                 LOGE("failed to create ghostpad\n");
4848                 goto ERROR;
4849         }
4850
4851         if (FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad)) {
4852                 LOGE("failed to add ghostpad to audiobin\n");
4853                 goto ERROR;
4854         }
4855
4856         gst_object_unref(pad);
4857
4858         g_list_free(element_bucket);
4859
4860         mm_attrs_set_int_by_name(attrs, "content_audio_found", TRUE);
4861
4862         MMPLAYER_FLEAVE();
4863
4864         return MM_ERROR_NONE;
4865
4866 ERROR:
4867
4868         LOGD("ERROR : releasing audiobin\n");
4869
4870         if (pad)
4871                 gst_object_unref(GST_OBJECT(pad));
4872
4873         if (ghostpad)
4874                 gst_object_unref(GST_OBJECT(ghostpad));
4875
4876         if (element_bucket)
4877                 g_list_free(element_bucket);
4878
4879         /* release element which are not added to bin */
4880         for (i = 1; i < MMPLAYER_A_NUM; i++) {
4881                 /* NOTE : skip bin */
4882                 if (audiobin[i].gst) {
4883                         GstObject* parent = NULL;
4884                         parent = gst_element_get_parent(audiobin[i].gst);
4885
4886                         if (!parent) {
4887                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
4888                                 audiobin[i].gst = NULL;
4889                         } else
4890                                 gst_object_unref(GST_OBJECT(parent));
4891                 }
4892         }
4893
4894         /* release audiobin with it's childs */
4895         if (audiobin[MMPLAYER_A_BIN].gst)
4896                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
4897
4898         MMPLAYER_FREEIF(audiobin);
4899
4900         player->pipeline->audiobin = NULL;
4901
4902         return MM_ERROR_PLAYER_INTERNAL;
4903 }
4904
4905 static GstPadProbeReturn
4906 __mmplayer_audio_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
4907 {
4908         mm_player_t* player = (mm_player_t*) u_data;
4909         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
4910         GstMapInfo probe_info = GST_MAP_INFO_INIT;
4911
4912         gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
4913
4914         if (player->audio_stream_cb && probe_info.size && probe_info.data)
4915                 player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
4916
4917         return GST_PAD_PROBE_OK;
4918 }
4919
4920 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
4921 {
4922         return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
4923 }
4924
4925 int _mmplayer_video_stream_release_bo(mm_player_t* player, void* bo)
4926 {
4927         int ret = MM_ERROR_NONE;
4928         GList *l = NULL;
4929         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4930         MMPLAYER_RETURN_VAL_IF_FAIL(bo, MM_ERROR_INVALID_ARGUMENT);
4931
4932         MMPLAYER_VIDEO_BO_LOCK(player);
4933
4934         if (player->video_bo_list) {
4935                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4936                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4937                         if (tmp && tmp->bo == bo) {
4938                                 tmp->using = FALSE;
4939                                 LOGD("release bo %p", bo);
4940                                 MMPLAYER_VIDEO_BO_UNLOCK(player);
4941                                 MMPLAYER_VIDEO_BO_SIGNAL(player);
4942                                 return ret;
4943                         }
4944                 }
4945         } else {
4946                 /* hw codec is running or the list was reset for DRC. */
4947                 LOGW("there is no bo list.");
4948         }
4949         MMPLAYER_VIDEO_BO_UNLOCK(player);
4950
4951         LOGW("failed to find bo %p", bo);
4952         return ret;
4953 }
4954
4955 static void
4956 __mmplayer_video_stream_destroy_bo_list(mm_player_t* player)
4957 {
4958         GList *l = NULL;
4959
4960         MMPLAYER_FENTER();
4961         MMPLAYER_RETURN_IF_FAIL(player);
4962
4963         MMPLAYER_VIDEO_BO_LOCK(player);
4964         if (player->video_bo_list) {
4965                 LOGD("destroy video_bo_list : %d", g_list_length(player->video_bo_list));
4966                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4967                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4968                         if (tmp) {
4969                                 if (tmp->bo)
4970                                         tbm_bo_unref(tmp->bo);
4971                                 g_free(tmp);
4972                         }
4973                 }
4974                 g_list_free(player->video_bo_list);
4975                 player->video_bo_list = NULL;
4976         }
4977         player->video_bo_size = 0;
4978         MMPLAYER_VIDEO_BO_UNLOCK(player);
4979
4980         MMPLAYER_FLEAVE();
4981         return;
4982 }
4983
4984 static void*
4985 __mmplayer_video_stream_get_bo(mm_player_t* player, int size)
4986 {
4987         GList *l = NULL;
4988         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
4989         gboolean ret = TRUE;
4990
4991         /* check DRC, if it is, destroy the prev bo list to create again */
4992         if (player->video_bo_size != size) {
4993                 LOGD("video size is changed: %d -> %d", player->video_bo_size, size);
4994                 __mmplayer_video_stream_destroy_bo_list(player);
4995                 player->video_bo_size = size;
4996         }
4997
4998         MMPLAYER_VIDEO_BO_LOCK(player);
4999
5000         if ((!player->video_bo_list) ||
5001                 (g_list_length(player->video_bo_list) < player->ini.num_of_video_bo)) {
5002
5003                 /* create bo list */
5004                 int idx = 0;
5005                 LOGD("Create bo list for decoded video stream(num:%d)", player->ini.num_of_video_bo);
5006
5007                 if (player->video_bo_list) {
5008                         /* if bo list did not created all, try it again. */
5009                         idx = g_list_length(player->video_bo_list);
5010                         LOGD("bo list exist(len: %d)", idx);
5011                 }
5012
5013                 for (; idx < player->ini.num_of_video_bo; idx++) {
5014                         mm_player_video_bo_info_t* bo_info = g_new(mm_player_video_bo_info_t, 1);
5015                         if (!bo_info) {
5016                                 LOGE("Fail to alloc bo_info.");
5017                                 break;
5018                         }
5019                         bo_info->bo = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
5020                         if (!bo_info->bo) {
5021                                 LOGE("Fail to tbm_bo_alloc.");
5022                                 g_free(bo_info);
5023                                 break;
5024                         }
5025                         bo_info->using = FALSE;
5026                         player->video_bo_list = g_list_append(player->video_bo_list, bo_info);
5027                 }
5028
5029                 /* update video num buffers */
5030                 player->video_num_buffers = idx;
5031                 if (idx == player->ini.num_of_video_bo)
5032                         player->video_extra_num_buffers = player->ini.num_of_video_bo/2;
5033
5034                 if (idx == 0) {
5035                         MMPLAYER_VIDEO_BO_UNLOCK(player);
5036                         return NULL;
5037                 }
5038
5039                 LOGD("Num of video buffers(%d/%d)", player->video_num_buffers, player->video_extra_num_buffers);
5040         }
5041
5042         while (TRUE) {
5043                 /* get bo from list*/
5044                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
5045                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
5046                         if (tmp && (tmp->using == FALSE)) {
5047                                 LOGD("found bo %p to use", tmp->bo);
5048                                 tmp->using = TRUE;
5049                                 MMPLAYER_VIDEO_BO_UNLOCK(player);
5050                                 return tmp->bo;
5051                         }
5052                 }
5053                 if (!ret) {
5054                         LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
5055                         MMPLAYER_VIDEO_BO_UNLOCK(player);
5056                         return NULL;
5057                 }
5058
5059                 if (player->ini.video_bo_timeout <= 0) {
5060                         MMPLAYER_VIDEO_BO_WAIT(player);
5061                 } else {
5062                         gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout*G_TIME_SPAN_SECOND;
5063                         ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, timeout);
5064                 }
5065                 continue;
5066         }
5067 }
5068
5069 static void
5070 __mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5071 {
5072         mm_player_t* player = (mm_player_t*)data;
5073         MMPLAYER_FENTER();
5074         MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
5075
5076         /* send prerolled pkt */
5077         player->video_stream_prerolled = FALSE;
5078
5079         __mmplayer_video_stream_decoded_render_cb(object, buffer, pad, data);
5080
5081         /* not to send prerolled pkt again */
5082         player->video_stream_prerolled = TRUE;
5083 }
5084
5085 static void
5086 __mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5087 {
5088         mm_player_t* player = (mm_player_t*)data;
5089         GstCaps *caps = NULL;
5090         MMPlayerVideoStreamDataType stream;
5091         MMVideoBuffer *video_buffer = NULL;
5092         GstMemory *dataBlock = NULL;
5093         GstMemory *metaBlock = NULL;
5094         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5095         GstStructure *structure = NULL;
5096         const gchar *string_format = NULL;
5097         unsigned int fourcc = 0;
5098
5099         MMPLAYER_FENTER();
5100         MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
5101
5102         if (player->video_stream_prerolled) {
5103                 player->video_stream_prerolled = FALSE;
5104                 LOGD("skip the prerolled pkt not to send it again");
5105                 return;
5106         }
5107
5108         caps = gst_pad_get_current_caps(pad);
5109         if (caps == NULL) {
5110                 LOGE("Caps is NULL.");
5111                 return;
5112         }
5113
5114         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
5115
5116         /* clear stream data structure */
5117         memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
5118
5119         structure = gst_caps_get_structure(caps, 0);
5120         gst_structure_get_int(structure, "width", & (stream.width));
5121         gst_structure_get_int(structure, "height", & (stream.height));
5122         string_format = gst_structure_get_string(structure, "format");
5123         if (string_format)
5124                 fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
5125         stream.format = util_get_pixtype(fourcc);
5126         gst_caps_unref(caps);
5127         caps = NULL;
5128
5129     /*
5130         LOGD("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
5131                 GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format);
5132     */
5133
5134         if (stream.width == 0 || stream.height == 0 || stream.format == MM_PIXEL_FORMAT_INVALID) {
5135                 LOGE("Wrong condition!!");
5136                 return;
5137         }
5138
5139         /* set size and timestamp */
5140         dataBlock = gst_buffer_peek_memory(buffer, 0);
5141         stream.length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
5142         stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano sec -> mili sec */
5143
5144         /* check zero-copy */
5145         if (player->set_mode.video_zc &&
5146                 player->set_mode.media_packet_video_stream &&
5147                 gst_buffer_n_memory(buffer) > 1) {
5148                 metaBlock = gst_buffer_peek_memory(buffer, 1);
5149                 gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
5150                 video_buffer = (MMVideoBuffer *)mapinfo.data;
5151         }
5152
5153         if (video_buffer) { /* hw codec */
5154                 /* set tbm bo */
5155                 if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
5156                         /* copy pointer of tbm bo, stride, elevation */
5157                         memcpy(stream.bo, video_buffer->handle.bo,
5158                                         sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
5159                 } else if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
5160                         /* FIXME: need to check this path */
5161                         memcpy(stream.data, video_buffer->data,
5162                                         sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
5163                 }
5164                 memcpy(stream.stride, video_buffer->stride_width,
5165                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5166                 memcpy(stream.elevation, video_buffer->stride_height,
5167                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5168                 /* set gst buffer */
5169                 stream.internal_buffer = buffer;
5170         } else { /* sw codec */
5171                 tbm_bo_handle thandle;
5172                 int stride = GST_ROUND_UP_4(stream.width);
5173                 int elevation = stream.height;
5174                 int size = 0;
5175
5176                 gboolean gst_ret;
5177                 gst_ret = gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
5178                 if (!gst_ret) {
5179                         LOGE("fail to gst_memory_map");
5180                         return;
5181                 }
5182
5183                 stream.stride[0] = stride;
5184                 stream.elevation[0] = elevation;
5185                 if (stream.format == MM_PIXEL_FORMAT_I420) {
5186                         stream.stride[1] = stream.stride[2] = GST_ROUND_UP_4(GST_ROUND_UP_2(stream.width) / 2);
5187                         stream.elevation[1] = stream.elevation[2] = stream.height / 2;
5188                         size = stream.stride[0] * stream.elevation[0] + stream.stride[1] * stream.elevation[1] + stream.stride[2] * stream.elevation[2];
5189                 } else if (stream.format == MM_PIXEL_FORMAT_RGBA) {
5190                         stream.stride[0] = stream.width * 4;
5191                         size = stream.stride[0] * stream.height;
5192                 } else {
5193                         LOGE("Not support format %d", stream.format);
5194                         gst_memory_unmap(dataBlock, &mapinfo);
5195                         return;
5196                 }
5197                 stream.bo[0] = __mmplayer_video_stream_get_bo(player, size);
5198                 if (!stream.bo[0]) {
5199                         LOGE("Fail to tbm_bo_alloc!!");
5200                         gst_memory_unmap(dataBlock, &mapinfo);
5201                         return;
5202                 }
5203                 thandle = tbm_bo_map(stream.bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
5204                 if (thandle.ptr && mapinfo.data)
5205                         memcpy(thandle.ptr, mapinfo.data, size);
5206                 else
5207                         LOGE("data pointer is wrong. dest : %p, src : %p",
5208                                         thandle.ptr, mapinfo.data);
5209                 tbm_bo_unmap(stream.bo[0]);
5210         }
5211
5212         if (player->video_stream_cb)
5213                 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
5214
5215         if (metaBlock)
5216                 gst_memory_unmap(metaBlock, &mapinfo);
5217         else
5218                 gst_memory_unmap(dataBlock, &mapinfo);
5219
5220         return;
5221 }
5222
5223 static int
5224 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket)
5225 {
5226         MMDisplaySurfaceType surface_type = MM_DISPLAY_SURFACE_NULL;
5227         gchar* video_csc = "videoconvert"; // default colorspace converter
5228         GList* element_bucket = *bucket;
5229
5230         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5231
5232         MMPLAYER_FENTER();
5233
5234         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", (int *)&surface_type);
5235
5236         if (player->set_mode.video_zc) {
5237                 video_csc = ""; /* videosinks don't use videoconvert normally */
5238         } else {
5239                 /* sw codec, if player use libav, waylandsink need videoconvert to render shm wl-buffer which support RGB only */
5240                 if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY) && (!strncmp(player->ini.videosink_element_overlay, "waylandsink", strlen(player->ini.videosink_element_overlay))))
5241                         video_csc = "videoconvert";
5242         }
5243         if (video_csc && (strcmp(video_csc, ""))) {
5244                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5245                 LOGD("using video converter: %s", video_csc);
5246         }
5247
5248         /* set video rotator */
5249         if (!player->set_mode.video_zc)
5250                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5251
5252         *bucket = element_bucket;
5253         MMPLAYER_FLEAVE();
5254         return MM_ERROR_NONE;
5255
5256 ERROR:
5257         *bucket = NULL;
5258         MMPLAYER_FLEAVE();
5259         return MM_ERROR_PLAYER_INTERNAL;
5260 }
5261
5262 /**
5263  * This function is to create video pipeline.
5264  *
5265  * @param       player          [in]    handle of player
5266  *              caps            [in]    src caps of decoder
5267  *              surface_type    [in]    surface type for video rendering
5268  *
5269  * @return      This function returns zero on success.
5270  * @remark
5271  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5272  */
5273 /**
5274   * VIDEO PIPELINE
5275   * - video overlay surface(arm/x86) : waylandsink
5276   */
5277 static int
5278 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5279 {
5280         GstPad *pad = NULL;
5281         MMHandleType attrs;
5282         GList*element_bucket = NULL;
5283         MMPlayerGstElement* first_element = NULL;
5284         MMPlayerGstElement* videobin = NULL;
5285         gchar *videosink_element = NULL;
5286
5287         MMPLAYER_FENTER();
5288
5289         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5290
5291         /* alloc handles */
5292         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5293         if (!videobin)
5294                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5295
5296         player->pipeline->videobin = videobin;
5297
5298         attrs = MMPLAYER_GET_ATTRS(player);
5299         if (!attrs) {
5300                 LOGE("cannot get content attribute");
5301                 return MM_ERROR_PLAYER_INTERNAL;
5302         }
5303
5304         /* create bin */
5305         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
5306         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
5307         if (!videobin[MMPLAYER_V_BIN].gst) {
5308                 LOGE("failed to create videobin");
5309                 goto ERROR;
5310         }
5311
5312         int enable_video_decoded_cb = 0;
5313         mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable_video_decoded_cb);
5314
5315         /* set video sink */
5316         switch (surface_type) {
5317         case MM_DISPLAY_SURFACE_OVERLAY:
5318                 if (__mmplayer_gst_create_video_filters(player, &element_bucket) != MM_ERROR_NONE)
5319                         goto ERROR;
5320                 if (strlen(player->ini.videosink_element_overlay) > 0)
5321                         videosink_element = player->ini.videosink_element_overlay;
5322                 else
5323                         goto ERROR;
5324                 break;
5325         case MM_DISPLAY_SURFACE_NULL:
5326                 if (strlen(player->ini.videosink_element_fake) > 0)
5327                         videosink_element = player->ini.videosink_element_fake;
5328                 else
5329                         goto ERROR;
5330                 break;
5331         case MM_DISPLAY_SURFACE_REMOTE:
5332                 if (strlen(player->ini.videosink_element_fake) > 0)
5333                         videosink_element = player->ini.videosink_element_fake;
5334                 else
5335                         goto ERROR;
5336                 break;
5337         default:
5338                 LOGE("unidentified surface type");
5339                 goto ERROR;
5340         }
5341         LOGD("selected videosink name: %s", videosink_element);
5342
5343         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, videosink_element, TRUE, player);
5344
5345         /* additional setting for sink plug-in */
5346         switch (surface_type) {
5347         case MM_DISPLAY_SURFACE_OVERLAY:
5348         {
5349                 bool use_tbm = player->set_mode.video_zc;
5350                 if (!use_tbm) {
5351                         LOGD("selected videosink name: %s", videosink_element);
5352
5353                         /* support shard memory with S/W codec on HawkP */
5354                         if (strncmp(videosink_element, "waylandsink", strlen(videosink_element)) == 0) {
5355                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5356                                         "use-tbm", use_tbm, NULL);
5357                         }
5358                 } else {
5359                         if (attrs) {
5360                                 int gapless = 0;
5361
5362                                 mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
5363
5364                                 if (gapless > 0) {
5365                                         LOGD("disable last-sample");
5366                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
5367                                 }
5368                         }
5369                 }
5370                 if (player->set_mode.media_packet_video_stream) {
5371                         int enable = 0;
5372                         mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable);
5373                         if (enable)
5374                                 g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "signal-handoffs", TRUE, NULL);
5375
5376                         MMPLAYER_SIGNAL_CONNECT(player,
5377                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5378                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5379                                                                         "handoff",
5380                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
5381                                                                         (gpointer)player);
5382
5383                         MMPLAYER_SIGNAL_CONNECT(player,
5384                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5385                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5386                                                                         "preroll-handoff",
5387                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
5388                                                                         (gpointer)player);
5389                 }
5390                 break;
5391         }
5392         case MM_DISPLAY_SURFACE_REMOTE:
5393         {
5394                 if (player->set_mode.media_packet_video_stream) {
5395                         LOGE("add data probe at videosink");
5396                         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5397                                                                                         "sync", TRUE, "signal-handoffs", TRUE, NULL);
5398
5399                         MMPLAYER_SIGNAL_CONNECT(player,
5400                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5401                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5402                                                                         "handoff",
5403                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
5404                                                                         (gpointer)player);
5405
5406                         MMPLAYER_SIGNAL_CONNECT(player,
5407                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5408                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5409                                                                         "preroll-handoff",
5410                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
5411                                                                         (gpointer)player);
5412                 }
5413                 break;
5414         }
5415         default:
5416                 break;
5417         }
5418
5419         if (_mmplayer_update_video_param(player, "update_all_param") != MM_ERROR_NONE)
5420                 goto ERROR;
5421
5422         if (videobin[MMPLAYER_V_SINK].gst) {
5423                 GstPad *sink_pad = NULL;
5424                 sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
5425                 if (sink_pad) {
5426                         MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5427                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
5428                         gst_object_unref(GST_OBJECT(sink_pad));
5429                 } else
5430                         LOGW("failed to get sink pad from videosink\n");
5431         }
5432
5433         /* store it as it's sink element */
5434         __mmplayer_add_sink(player, videobin[MMPLAYER_V_SINK].gst);
5435
5436         /* adding created elements to bin */
5437         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket)) {
5438                 LOGE("failed to add elements\n");
5439                 goto ERROR;
5440         }
5441
5442         /* Linking elements in the bucket by added order */
5443         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
5444                 LOGE("failed to link elements\n");
5445                 goto ERROR;
5446         }
5447
5448         /* get first element's sinkpad for creating ghostpad */
5449         if (element_bucket)
5450                 first_element = (MMPlayerGstElement *)element_bucket->data;
5451         if (!first_element) {
5452                 LOGE("failed to get first element from bucket\n");
5453                 goto ERROR;
5454         }
5455
5456         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5457         if (!pad) {
5458                 LOGE("failed to get pad from first element\n");
5459                 goto ERROR;
5460         }
5461
5462         /* create ghostpad */
5463         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
5464         if (FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
5465                 LOGE("failed to add ghostpad to videobin\n");
5466                 goto ERROR;
5467         }
5468         gst_object_unref(pad);
5469
5470         /* done. free allocated variables */
5471         if (element_bucket)
5472                 g_list_free(element_bucket);
5473
5474         MMPLAYER_FLEAVE();
5475
5476         return MM_ERROR_NONE;
5477
5478 ERROR:
5479         LOGE("ERROR : releasing videobin\n");
5480
5481         g_list_free(element_bucket);
5482
5483         if (pad)
5484                 gst_object_unref(GST_OBJECT(pad));
5485
5486         /* release videobin with it's childs */
5487         if (videobin[MMPLAYER_V_BIN].gst)
5488                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
5489
5490
5491         MMPLAYER_FREEIF(videobin);
5492
5493         player->pipeline->videobin = NULL;
5494
5495         return MM_ERROR_PLAYER_INTERNAL;
5496 }
5497
5498 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
5499 {
5500         GList *element_bucket = NULL;
5501         MMPlayerGstElement *textbin = player->pipeline->textbin;
5502
5503         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", TRUE, player);
5504         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", TRUE, player);
5505         g_object_set(G_OBJECT(textbin[MMPLAYER_T_IDENTITY].gst),
5506                                                         "signal-handoffs", FALSE,
5507                                                         NULL);
5508
5509         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
5510         MMPLAYER_SIGNAL_CONNECT(player,
5511                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
5512                                                         MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
5513                                                         "handoff",
5514                                                         G_CALLBACK(__mmplayer_update_subtitle),
5515                                                         (gpointer)player);
5516
5517         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
5518         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
5519         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
5520
5521         if (!player->play_subtitle) {
5522                 LOGD("add textbin sink as sink element of whole pipeline.\n");
5523                 __mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
5524         }
5525
5526         /* adding created elements to bin */
5527         LOGD("adding created elements to bin\n");
5528         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) {
5529                 LOGE("failed to add elements\n");
5530                 goto ERROR;
5531         }
5532
5533         /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
5534         GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
5535         GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
5536
5537         /* linking elements in the bucket by added order. */
5538         LOGD("Linking elements in the bucket by added order.\n");
5539         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
5540                 LOGE("failed to link elements\n");
5541                 goto ERROR;
5542         }
5543
5544         /* done. free allocated variables */
5545         g_list_free(element_bucket);
5546
5547         if (textbin[MMPLAYER_T_QUEUE].gst) {
5548                 GstPad *pad = NULL;
5549                 GstPad *ghostpad = NULL;
5550
5551                 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_QUEUE].gst), "sink");
5552                 if (!pad) {
5553                         LOGE("failed to get video pad of textbin\n");
5554                         return MM_ERROR_PLAYER_INTERNAL;
5555                 }
5556
5557                 ghostpad = gst_ghost_pad_new("text_sink", pad);
5558                 gst_object_unref(pad);
5559
5560                 if (!ghostpad) {
5561                         LOGE("failed to create ghostpad of textbin\n");
5562                         goto ERROR;
5563                 }
5564
5565                 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad)) {
5566                         LOGE("failed to add ghostpad to textbin\n");
5567                         goto ERROR;
5568                 }
5569         }
5570
5571         return MM_ERROR_NONE;
5572
5573 ERROR:
5574         g_list_free(element_bucket);
5575
5576         return MM_ERROR_PLAYER_INTERNAL;
5577 }
5578
5579 static int __mmplayer_gst_create_text_pipeline(mm_player_t* player)
5580 {
5581         MMPlayerGstElement *textbin = NULL;
5582         GList *element_bucket = NULL;
5583         gint i = 0;
5584
5585         MMPLAYER_FENTER();
5586
5587         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5588
5589         /* alloc handles */
5590         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
5591         if (!textbin) {
5592                 LOGE("failed to allocate memory for textbin\n");
5593                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5594         }
5595
5596         /* create bin */
5597         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
5598         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
5599         if (!textbin[MMPLAYER_T_BIN].gst) {
5600                 LOGE("failed to create textbin\n");
5601                 goto ERROR;
5602         }
5603
5604         /* take it */
5605         player->pipeline->textbin = textbin;
5606
5607         /* fakesink */
5608         if (player->use_textoverlay) {
5609                 LOGD("use textoverlay for displaying \n");
5610
5611                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_QUEUE, "queue", "text_t_queue", textbin[MMPLAYER_T_BIN].gst, player);
5612
5613                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_QUEUE, "queue", "text_v_queue", textbin[MMPLAYER_T_BIN].gst, player);
5614
5615                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_CONVERTER, "fimcconvert", "text_v_converter", textbin[MMPLAYER_T_BIN].gst, player);
5616
5617                 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_OVERLAY, "textoverlay", "text_overlay", textbin[MMPLAYER_T_BIN].gst, player);
5618
5619                 if (!gst_element_link_pads(textbin[MMPLAYER_T_VIDEO_QUEUE].gst, "src", textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "sink")) {
5620                         LOGE("failed to link queue and converter\n");
5621                         goto ERROR;
5622                 }
5623
5624                 if (!gst_element_link_pads(textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "video_sink")) {
5625                         LOGE("failed to link queue and textoverlay\n");
5626                         goto ERROR;
5627                 }
5628
5629                 if (!gst_element_link_pads(textbin[MMPLAYER_T_QUEUE].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "text_sink")) {
5630                         LOGE("failed to link queue and textoverlay\n");
5631                         goto ERROR;
5632                 }
5633         } else {
5634                 int surface_type = 0;
5635
5636                 LOGD("use subtitle message for displaying \n");
5637
5638                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
5639
5640                 switch (surface_type) {
5641                 case MM_DISPLAY_SURFACE_OVERLAY:
5642                 case MM_DISPLAY_SURFACE_NULL:
5643                 case MM_DISPLAY_SURFACE_REMOTE:
5644                         if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE) {
5645                                 LOGE("failed to make plain text elements\n");
5646                                 goto ERROR;
5647                         }
5648                         break;
5649
5650                 default:
5651                         break;
5652                 }
5653         }
5654
5655         MMPLAYER_FLEAVE();
5656
5657         return MM_ERROR_NONE;
5658
5659 ERROR:
5660
5661         LOGD("ERROR : releasing textbin\n");
5662
5663         g_list_free(element_bucket);
5664
5665         /* release element which are not added to bin */
5666         for (i = 1; i < MMPLAYER_T_NUM; i++) {
5667                 /* NOTE : skip bin */
5668                 if (textbin[i].gst) {
5669                         GstObject* parent = NULL;
5670                         parent = gst_element_get_parent(textbin[i].gst);
5671
5672                         if (!parent) {
5673                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
5674                                 textbin[i].gst = NULL;
5675                         } else
5676                                 gst_object_unref(GST_OBJECT(parent));
5677                 }
5678         }
5679
5680         /* release textbin with it's childs */
5681         if (textbin[MMPLAYER_T_BIN].gst)
5682                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
5683
5684         MMPLAYER_FREEIF(textbin);
5685
5686         player->pipeline->textbin = NULL;
5687
5688         return MM_ERROR_PLAYER_INTERNAL;
5689 }
5690
5691
5692 static int
5693 __mmplayer_gst_create_subtitle_src(mm_player_t* player)
5694 {
5695         MMPlayerGstElement* mainbin = NULL;
5696         MMHandleType attrs = 0;
5697         GstElement *subsrc = NULL;
5698         GstElement *subparse = NULL;
5699         gchar *subtitle_uri = NULL;
5700         const gchar *charset = NULL;
5701         GstPad *pad = NULL;
5702
5703         MMPLAYER_FENTER();
5704
5705         /* get mainbin */
5706         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5707
5708         mainbin = player->pipeline->mainbin;
5709
5710         attrs = MMPLAYER_GET_ATTRS(player);
5711         if (!attrs) {
5712                 LOGE("cannot get content attribute\n");
5713                 return MM_ERROR_PLAYER_INTERNAL;
5714         }
5715
5716         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
5717         if (!subtitle_uri || strlen(subtitle_uri) < 1) {
5718                 LOGE("subtitle uri is not proper filepath.\n");
5719                 return MM_ERROR_PLAYER_INVALID_URI;
5720         }
5721
5722         if (!util_get_storage_info(subtitle_uri, &player->storage_info[MMPLAYER_PATH_TEXT])) {
5723                 LOGE("failed to get storage info of subtitle path");
5724                 return MM_ERROR_PLAYER_INVALID_URI;
5725         }
5726
5727         LOGD("subtitle file path is [%s].\n", subtitle_uri);
5728
5729         /* create the subtitle source */
5730         subsrc = gst_element_factory_make("filesrc", "subtitle_source");
5731         if (!subsrc) {
5732                 LOGE("failed to create filesrc element\n");
5733                 goto ERROR;
5734         }
5735         g_object_set(G_OBJECT(subsrc), "location", subtitle_uri, NULL);
5736
5737         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
5738         mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
5739
5740         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc)) {
5741                 LOGW("failed to add queue\n");
5742                 goto ERROR;
5743         }
5744
5745         /* subparse */
5746         subparse = gst_element_factory_make("subparse", "subtitle_parser");
5747         if (!subparse) {
5748                 LOGE("failed to create subparse element\n");
5749                 goto ERROR;
5750         }
5751
5752         charset = util_get_charset(subtitle_uri);
5753         if (charset) {
5754                 LOGD("detected charset is %s\n", charset);
5755                 g_object_set(G_OBJECT(subparse), "subtitle-encoding", charset, NULL);
5756         }
5757
5758         mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE;
5759         mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
5760
5761         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse)) {
5762                 LOGW("failed to add subparse\n");
5763                 goto ERROR;
5764         }
5765
5766         if (!gst_element_link_pads(subsrc, "src", subparse, "sink")) {
5767                 LOGW("failed to link subsrc and subparse\n");
5768                 goto ERROR;
5769         }
5770
5771         player->play_subtitle = TRUE;
5772         player->adjust_subtitle_pos = 0;
5773
5774         LOGD("play subtitle using subtitle file\n");
5775
5776         if (player->pipeline->textbin == NULL) {
5777                 if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player)) {
5778                         LOGE("failed to create textbin. continuing without text\n");
5779                         goto ERROR;
5780                 }
5781
5782                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst))) {
5783                         LOGW("failed to add textbin\n");
5784                         goto ERROR;
5785                 }
5786
5787                 LOGD("link text input selector and textbin ghost pad");
5788
5789                 player->textsink_linked = 1;
5790                 player->external_text_idx = 0;
5791                 LOGI("player->textsink_linked set to 1\n");
5792         } else {
5793                 LOGD("text bin has been created. reuse it.");
5794                 player->external_text_idx = 1;
5795         }
5796
5797         if (!gst_element_link_pads(subparse, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink")) {
5798                 LOGW("failed to link subparse and textbin\n");
5799                 goto ERROR;
5800         }
5801
5802         pad = gst_element_get_static_pad(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
5803
5804         if (!pad) {
5805                 LOGE("failed to get sink pad from textsink to probe data");
5806                 return MM_ERROR_PLAYER_INTERNAL;
5807         }
5808
5809         gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
5810                                 __mmplayer_subtitle_adjust_position_probe, player, NULL);
5811
5812         gst_object_unref(pad);
5813         pad = NULL;
5814
5815         /* create dot. for debugging */
5816         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-with-subtitle");
5817         MMPLAYER_FLEAVE();
5818
5819         return MM_ERROR_NONE;
5820
5821 ERROR:
5822         player->textsink_linked = 0;
5823         return MM_ERROR_PLAYER_INTERNAL;
5824 }
5825
5826 gboolean
5827 __mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5828 {
5829         mm_player_t* player = (mm_player_t*) data;
5830         MMMessageParamType msg = {0, };
5831         GstClockTime duration = 0;
5832         gpointer text = NULL;
5833         guint text_size = 0;
5834         gboolean ret = TRUE;
5835         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5836
5837         MMPLAYER_FENTER();
5838
5839         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
5840         MMPLAYER_RETURN_VAL_IF_FAIL(buffer, FALSE);
5841
5842         if (player->is_subtitle_force_drop)
5843         {
5844                 LOGW("subtitle is dropped forcedly.");
5845                 return ret;
5846         }
5847
5848         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
5849         text = mapinfo.data;
5850         text_size = mapinfo.size;
5851         duration = GST_BUFFER_DURATION(buffer);
5852
5853         if (player->set_mode.subtitle_off) {
5854                 LOGD("subtitle is OFF.\n");
5855                 return TRUE;
5856         }
5857
5858         if (!text || (text_size == 0)) {
5859                 LOGD("There is no subtitle to be displayed.\n");
5860                 return TRUE;
5861         }
5862
5863         msg.data = (void *) text;
5864         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
5865
5866         LOGD("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data);
5867
5868         MMPLAYER_POST_MSG(player, MM_MESSAGE_UPDATE_SUBTITLE, &msg);
5869         gst_buffer_unmap(buffer, &mapinfo);
5870
5871         MMPLAYER_FLEAVE();
5872
5873         return ret;
5874 }
5875
5876 static GstPadProbeReturn
5877 __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
5878
5879 {
5880         mm_player_t *player = (mm_player_t *) u_data;
5881         GstClockTime cur_timestamp = 0;
5882         gint64 adjusted_timestamp = 0;
5883         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
5884
5885         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
5886
5887         if (player->set_mode.subtitle_off) {
5888                 LOGD("subtitle is OFF.\n");
5889                 return TRUE;
5890         }
5891
5892         if (player->adjust_subtitle_pos == 0) {
5893                 LOGD("nothing to do");
5894                 return TRUE;
5895         }
5896
5897         cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
5898         adjusted_timestamp = (gint64) cur_timestamp +((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
5899
5900         if (adjusted_timestamp < 0) {
5901                 LOGD("adjusted_timestamp under zero");
5902                 MMPLAYER_FLEAVE();
5903                 return FALSE;
5904         }
5905
5906         GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
5907         LOGD("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
5908                                 GST_TIME_ARGS(cur_timestamp),
5909                                 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
5910
5911         return GST_PAD_PROBE_OK;
5912 }
5913 static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
5914 {
5915         MMPLAYER_FENTER();
5916
5917         /* check player and subtitlebin are created */
5918         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5919         MMPLAYER_RETURN_VAL_IF_FAIL(player->play_subtitle, MM_ERROR_NOT_SUPPORT_API);
5920
5921         if (position == 0) {
5922                 LOGD("nothing to do\n");
5923                 MMPLAYER_FLEAVE();
5924                 return MM_ERROR_NONE;
5925         }
5926
5927         switch (format) {
5928         case MM_PLAYER_POS_FORMAT_TIME:
5929                 {
5930                         /* check current postion */
5931                         player->adjust_subtitle_pos = position;
5932
5933                         LOGD("save adjust_subtitle_pos in player") ;
5934                 }
5935                 break;
5936
5937         default:
5938                 {
5939                         LOGW("invalid format.\n");
5940                         MMPLAYER_FLEAVE();
5941                         return MM_ERROR_INVALID_ARGUMENT;
5942                 }
5943         }
5944
5945         MMPLAYER_FLEAVE();
5946
5947         return MM_ERROR_NONE;
5948 }
5949 static int __gst_adjust_video_position(mm_player_t* player, int offset)
5950 {
5951         MMPLAYER_FENTER();
5952         LOGD("adjusting video_pos in player") ;
5953         int current_pos = 0;
5954         /* check player and videobin are created */
5955         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5956         if (!player->pipeline->videobin ||
5957                         !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
5958                 LOGD("no video pipeline or sink is there");
5959                 return MM_ERROR_PLAYER_INVALID_STATE ;
5960         }
5961         if (offset == 0) {
5962                 LOGD("nothing to do\n");
5963                 MMPLAYER_FLEAVE();
5964                 return MM_ERROR_NONE;
5965         }
5966         if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, (unsigned long*)&current_pos) != MM_ERROR_NONE) {
5967                 LOGD("failed to get current position");
5968                 return MM_ERROR_PLAYER_INTERNAL;
5969         }
5970         if ((current_pos - offset) < GST_TIME_AS_MSECONDS(player->duration)) {
5971                 LOGD("enter video delay is valid");
5972         } else {
5973                 LOGD("enter video delay is crossing content boundary");
5974                 return MM_ERROR_INVALID_ARGUMENT ;
5975         }
5976         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "ts-offset", ((gint64) offset * G_GINT64_CONSTANT(1000000)), NULL);
5977         LOGD("video delay has been done");
5978         MMPLAYER_FLEAVE();
5979
5980         return MM_ERROR_NONE;
5981 }
5982
5983 static void
5984 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data) // @
5985 {
5986         GstElement *appsrc = element;
5987         tBuffer *buf = (tBuffer *)user_data;
5988         GstBuffer *buffer = NULL;
5989         GstFlowReturn ret = GST_FLOW_OK;
5990         gint len = size;
5991
5992         MMPLAYER_RETURN_IF_FAIL(element);
5993         MMPLAYER_RETURN_IF_FAIL(buf);
5994
5995         buffer = gst_buffer_new();
5996
5997         if (buf->offset >= buf->len) {
5998                 LOGD("call eos appsrc\n");
5999                 g_signal_emit_by_name(appsrc, "end-of-stream", &ret);
6000                 return;
6001         }
6002
6003         if (buf->len - buf->offset < size)
6004                 len = buf->len - buf->offset + buf->offset;
6005
6006         gst_buffer_insert_memory(buffer, -1, gst_memory_new_wrapped(0, (guint8 *)(buf->buf + buf->offset), len, 0, len, (guint8*)(buf->buf + buf->offset), g_free));
6007         GST_BUFFER_OFFSET(buffer) = (guint64)buf->offset;
6008         GST_BUFFER_OFFSET_END(buffer) = (guint64)(buf->offset + len);
6009
6010         //LOGD("feed buffer %p, offset %u-%u length %u\n", buffer, buf->offset, buf->len,len);
6011         g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
6012
6013         buf->offset += len;
6014 }
6015
6016 static gboolean
6017 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data) // @
6018 {
6019         tBuffer *buf = (tBuffer *)user_data;
6020
6021         MMPLAYER_RETURN_VAL_IF_FAIL(buf, FALSE);
6022
6023         buf->offset  = (int)size;
6024
6025         return TRUE;
6026 }
6027
6028 static GstBusSyncReply
6029 __mmplayer_bus_sync_callback(GstBus * bus, GstMessage * message, gpointer data)
6030 {
6031         mm_player_t *player = (mm_player_t *)data;
6032         GstBusSyncReply reply = GST_BUS_DROP;
6033
6034         if (!(player->pipeline && player->pipeline->mainbin)) {
6035                 LOGE("player pipeline handle is null");
6036                 return GST_BUS_PASS;
6037         }
6038
6039         if (!__mmplayer_check_useful_message(player, message)) {
6040                 gst_message_unref(message);
6041                 return GST_BUS_DROP;
6042         }
6043
6044         switch (GST_MESSAGE_TYPE(message)) {
6045         case GST_MESSAGE_STATE_CHANGED:
6046                 /* post directly for fast launch */
6047                 if (player->sync_handler) {
6048                         __mmplayer_gst_callback(NULL, message, player);
6049                         reply = GST_BUS_DROP;
6050                 } else
6051                         reply = GST_BUS_PASS;
6052                 break;
6053         case GST_MESSAGE_TAG:
6054                 __mmplayer_gst_extract_tag_from_msg(player, message);
6055
6056                 #if 0 // debug
6057                 {
6058                         GstTagList *tags = NULL;
6059
6060                         gst_message_parse_tag(message, &tags);
6061                         if (tags) {
6062                                 LOGE("TAGS received from element \"%s\".\n",
6063                                 GST_STR_NULL(GST_ELEMENT_NAME(GST_MESSAGE_SRC(message))));
6064
6065                                 gst_tag_list_foreach(tags, print_tag, NULL);
6066                                 gst_tag_list_free(tags);
6067                                 tags = NULL;
6068                         }
6069                         break;
6070                 }
6071                 #endif
6072                 break;
6073
6074         case GST_MESSAGE_DURATION_CHANGED:
6075                 __mmplayer_gst_handle_duration(player, message);
6076                 break;
6077         case GST_MESSAGE_ASYNC_DONE:
6078                 /* NOTE:Don't call gst_callback directly
6079                  * because previous frame can be showed even though this message is received for seek.
6080                  */
6081         default:
6082                 reply = GST_BUS_PASS;
6083                 break;
6084         }
6085
6086         if (reply == GST_BUS_DROP)
6087                 gst_message_unref(message);
6088
6089         return reply;
6090 }
6091
6092 static gboolean
6093 __mmplayer_gst_create_decoder(mm_player_t *player,
6094                                                                 MMPlayerTrackType track,
6095                                                                 GstPad* srcpad,
6096                                                                 enum MainElementID elemId,
6097                                                                 const gchar* name)
6098 {
6099         gboolean ret = TRUE;
6100         GstPad *sinkpad = NULL;
6101
6102         MMPLAYER_FENTER();
6103
6104         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
6105                                                 player->pipeline &&
6106                                                 player->pipeline->mainbin, FALSE);
6107         MMPLAYER_RETURN_VAL_IF_FAIL((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE);
6108         MMPLAYER_RETURN_VAL_IF_FAIL(srcpad, FALSE);
6109         MMPLAYER_RETURN_VAL_IF_FAIL((player->pipeline->mainbin[elemId].gst == NULL), FALSE);
6110
6111         GstElement *decodebin = NULL;
6112         GstCaps *dec_caps = NULL;
6113
6114         /* create decodebin */
6115         decodebin = gst_element_factory_make("decodebin", name);
6116
6117         if (!decodebin) {
6118                 LOGE("error : fail to create decodebin for %d decoder\n", track);
6119                 ret = FALSE;
6120                 goto ERROR;
6121         }
6122
6123         /* raw pad handling signal */
6124         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6125                                                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
6126
6127         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
6128         before looking for any elements that can handle that stream.*/
6129         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
6130                                                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
6131
6132         /* This signal is emitted when a element is added to the bin.*/
6133         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
6134                                                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
6135
6136         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
6137                 LOGE("failed to add new decodebin\n");
6138                 ret = FALSE;
6139                 goto ERROR;
6140         }
6141
6142         dec_caps = gst_pad_query_caps(srcpad, NULL);
6143         if (dec_caps) {
6144                 //LOGD("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
6145                 g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
6146                 gst_caps_unref(dec_caps);
6147         }
6148
6149         player->pipeline->mainbin[elemId].id = elemId;
6150         player->pipeline->mainbin[elemId].gst = decodebin;
6151
6152         sinkpad = gst_element_get_static_pad(decodebin, "sink");
6153
6154         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
6155                 LOGW("failed to link [%s:%s] to decoder\n", GST_DEBUG_PAD_NAME(srcpad));
6156                 gst_object_unref(GST_OBJECT(decodebin));
6157         }
6158
6159         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin))
6160                 LOGE("failed to sync second level decodebin state with parent\n");
6161
6162         LOGD("Total num of %d tracks = %d \n", track, player->selector[track].total_track_num);
6163
6164 ERROR:
6165         if (sinkpad) {
6166                 gst_object_unref(GST_OBJECT(sinkpad));
6167                 sinkpad = NULL;
6168         }
6169         MMPLAYER_FLEAVE();
6170
6171         return ret;
6172 }
6173
6174 /**
6175  * This function is to create  audio or video pipeline for playing.
6176  *
6177  * @param       player          [in]    handle of player
6178  *
6179  * @return      This function returns zero on success.
6180  * @remark
6181  * @see
6182  */
6183 static int
6184 __mmplayer_gst_create_pipeline(mm_player_t* player) // @
6185 {
6186         GstBus  *bus = NULL;
6187         MMPlayerGstElement *mainbin = NULL;
6188         MMHandleType attrs = 0;
6189         GstElement* element = NULL;
6190         GstElement* elem_src_audio = NULL;
6191         GstElement* elem_src_subtitle = NULL;
6192         GstElement* es_video_queue = NULL;
6193         GstElement* es_audio_queue = NULL;
6194         GstElement* es_subtitle_queue = NULL;
6195         GList* element_bucket = NULL;
6196         gboolean need_state_holder = TRUE;
6197         gint i = 0;
6198 #ifdef SW_CODEC_ONLY
6199         int surface_type = 0;
6200 #endif
6201         MMPLAYER_FENTER();
6202
6203         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6204
6205         /* get profile attribute */
6206         attrs = MMPLAYER_GET_ATTRS(player);
6207         if (!attrs) {
6208                 LOGE("cannot get content attribute\n");
6209                 goto INIT_ERROR;
6210         }
6211
6212         /* create pipeline handles */
6213         if (player->pipeline) {
6214                 LOGW("pipeline should be released before create new one\n");
6215                 goto INIT_ERROR;
6216         }
6217
6218         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0(sizeof(MMPlayerGstPipelineInfo));
6219         if (player->pipeline == NULL)
6220                 goto INIT_ERROR;
6221
6222         memset(player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo));
6223
6224
6225         /* create mainbin */
6226         mainbin = (MMPlayerGstElement*) g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
6227         if (mainbin == NULL)
6228                 goto INIT_ERROR;
6229
6230         memset(mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
6231
6232         /* create pipeline */
6233         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
6234         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
6235         if (!mainbin[MMPLAYER_M_PIPE].gst) {
6236                 LOGE("failed to create pipeline\n");
6237                 goto INIT_ERROR;
6238         }
6239         player->demux_pad_index = 0;
6240         player->subtitle_language_list = NULL;
6241
6242         player->is_subtitle_force_drop = FALSE;
6243         player->last_multiwin_status = FALSE;
6244
6245         _mmplayer_track_initialize(player);
6246         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
6247
6248         /* create source element */
6249         switch (player->profile.uri_type) {
6250         /* rtsp streamming */
6251         case MM_PLAYER_URI_TYPE_URL_RTSP:
6252                 {
6253                         gint network_bandwidth;
6254                         gchar *user_agent, *wap_profile;
6255
6256                         element = gst_element_factory_make("rtspsrc", "rtsp source");
6257
6258                         if (!element) {
6259                                 LOGE("failed to create streaming source element\n");
6260                                 break;
6261                         }
6262
6263                         /* make it zero */
6264                         network_bandwidth = 0;
6265                         user_agent = wap_profile = NULL;
6266
6267                         /* get attribute */
6268                         mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
6269                         mm_attrs_get_string_by_name(attrs, "streaming_wap_profile", &wap_profile);
6270                         mm_attrs_get_int_by_name(attrs, "streaming_network_bandwidth", &network_bandwidth);
6271
6272                         SECURE_LOGD("user_agent : %s\n", user_agent);
6273                         SECURE_LOGD("wap_profile : %s\n", wap_profile);
6274
6275                         /* setting property to streaming source */
6276                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6277                         if (user_agent)
6278                                 g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6279                         if (wap_profile)
6280                                 g_object_set(G_OBJECT(element), "wap_profile", wap_profile, NULL);
6281
6282                         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6283                                 G_CALLBACK(__mmplayer_gst_rtp_dynamic_pad), player);
6284                         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
6285                                 G_CALLBACK(__mmplayer_gst_rtp_no_more_pads), player);
6286
6287                         player->use_decodebin = FALSE;
6288                 }
6289                 break;
6290
6291         /* http streaming*/
6292         case MM_PLAYER_URI_TYPE_URL_HTTP:
6293                 {
6294                         gchar *user_agent, *proxy, *cookies, **cookie_list;
6295                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6296                         user_agent = proxy = cookies = NULL;
6297                         cookie_list = NULL;
6298                         gint mode = MM_PLAYER_PD_MODE_NONE;
6299
6300                         mm_attrs_get_int_by_name(attrs, "pd_mode", &mode);
6301
6302                         player->pd_mode = mode;
6303
6304                         LOGD("http playback, PD mode : %d\n", player->pd_mode);
6305
6306                         if (!MMPLAYER_IS_HTTP_PD(player)) {
6307                                 element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
6308                                 if (!element) {
6309                                         LOGE("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
6310                                         break;
6311                                 }
6312                                 LOGD("using http streamming source [%s].\n", player->ini.httpsrc_element);
6313
6314                                 /* get attribute */
6315                                 mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
6316                                 mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
6317                                 mm_attrs_get_string_by_name(attrs, "streaming_proxy", &proxy);
6318                                 mm_attrs_get_int_by_name(attrs, "streaming_timeout", &http_timeout);
6319
6320                                 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
6321                                         (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT)) {
6322                                         LOGD("get timeout from ini\n");
6323                                         http_timeout = player->ini.http_timeout;
6324                                 }
6325
6326                                 /* get attribute */
6327                                 SECURE_LOGD("location : %s\n", player->profile.uri);
6328                                 SECURE_LOGD("cookies : %s\n", cookies);
6329                                 SECURE_LOGD("proxy : %s\n", proxy);
6330                                 SECURE_LOGD("user_agent :  %s\n",  user_agent);
6331                                 LOGD("timeout : %d\n",  http_timeout);
6332
6333                                 /* setting property to streaming source */
6334                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6335                                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6336                                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
6337
6338                                 /* check if prosy is vailid or not */
6339                                 if (util_check_valid_url(proxy))
6340                                         g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
6341                                 /* parsing cookies */
6342                                 if ((cookie_list = util_get_cookie_list((const char*)cookies)))
6343                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
6344                                 if (user_agent)
6345                                         g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6346
6347                                 if (MMPLAYER_URL_HAS_DASH_SUFFIX(player))
6348                                         LOGW("it's dash. and it's still experimental feature.");
6349                         } else {
6350                                 // progressive download
6351                                 gchar* location = NULL;
6352
6353                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI) {
6354                                         gchar *path = NULL;
6355
6356                                         mm_attrs_get_string_by_name(attrs, "pd_location", &path);
6357
6358                                         MMPLAYER_FREEIF(player->pd_file_save_path);
6359
6360                                         LOGD("PD Location : %s\n", path);
6361
6362                                         if (path) {
6363                                                 if (!util_get_storage_info(path, &player->storage_info[MMPLAYER_PATH_VOD])) {
6364                                                         LOGE("failed to get storage info");
6365                                                         break;
6366                                                 }
6367                                                 player->pd_file_save_path = g_strdup(path);
6368                                         } else {
6369                                                 LOGE("can't find pd location so, it should be set \n");
6370                                                 break;
6371                                         }
6372                                 }
6373
6374                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
6375                                 if (!element) {
6376                                         LOGE("failed to create PD push source element[%s].\n", "pdpushsrc");
6377                                         break;
6378                                 }
6379
6380                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
6381                                         g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
6382                                 else
6383                                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6384                                 g_object_get(element, "location", &location, NULL);
6385                                 LOGD("PD_LOCATION [%s].\n", location);
6386                                 if(location)
6387                                         g_free(location);
6388                         }
6389                 }
6390                 break;
6391
6392         /* file source */
6393         case MM_PLAYER_URI_TYPE_FILE:
6394                 {
6395                         LOGD("using filesrc for 'file://' handler.\n");
6396                         if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
6397                                 LOGE("failed to get storage info");
6398                                 break;
6399                         }
6400
6401                         element = gst_element_factory_make("filesrc", "source");
6402                         if (!element) {
6403                                 LOGE("failed to create filesrc\n");
6404                                 break;
6405                         }
6406
6407                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
6408                 }
6409                 break;
6410
6411         case MM_PLAYER_URI_TYPE_SS:
6412                 {
6413                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6414                         element = gst_element_factory_make("souphttpsrc", "http streaming source");
6415                         if (!element) {
6416                                 LOGE("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
6417                                 break;
6418                         }
6419
6420                         mm_attrs_get_int_by_name(attrs, "streaming_timeout", &http_timeout);
6421
6422                         if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
6423                                 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT)) {
6424                                 LOGD("get timeout from ini\n");
6425                                 http_timeout = player->ini.http_timeout;
6426                         }
6427
6428                         /* setting property to streaming source */
6429                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6430                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6431                 }
6432                 break;
6433         case MM_PLAYER_URI_TYPE_MS_BUFF:
6434                 {
6435                         LOGD("MS buff src is selected\n");
6436
6437                         if (player->v_stream_caps) {
6438                                 element = gst_element_factory_make("appsrc", "video_appsrc");
6439                                 if (!element) {
6440                                         LOGF("failed to create video app source element[appsrc].\n");
6441                                         break;
6442                                 }
6443
6444                                 if (player->a_stream_caps) {
6445                                         elem_src_audio = gst_element_factory_make("appsrc", "audio_appsrc");
6446                                         if (!elem_src_audio) {
6447                                                 LOGF("failed to create audio app source element[appsrc].\n");
6448                                                 break;
6449                                         }
6450                                 }
6451                         } else if (player->a_stream_caps) {
6452                                 /* no video, only audio pipeline*/
6453                                 element = gst_element_factory_make("appsrc", "audio_appsrc");
6454                                 if (!element) {
6455                                         LOGF("failed to create audio app source element[appsrc].\n");
6456                                         break;
6457                                 }
6458                         }
6459
6460                         if (player->s_stream_caps) {
6461                                 elem_src_subtitle = gst_element_factory_make("appsrc", "subtitle_appsrc");
6462                                 if (!elem_src_subtitle) {
6463                                         LOGF("failed to create subtitle app source element[appsrc].\n");
6464                                         break;
6465                                 }
6466                         }
6467
6468                         LOGD("setting app sources properties.\n");
6469                         LOGD("location : %s\n", player->profile.uri);
6470
6471                         if (player->v_stream_caps && element) {
6472                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6473                                                                                             "blocksize", (guint)1048576,        /* size of many video frames are larger than default blocksize as 4096 */
6474                                                                                                 "caps", player->v_stream_caps, NULL);
6475
6476                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6477                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6478                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6479                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6480
6481                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6482                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6483                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6484                                                                                                                 G_CALLBACK(__gst_seek_video_data), player);
6485
6486                                 if (player->a_stream_caps && elem_src_audio) {
6487                                         g_object_set(G_OBJECT(elem_src_audio), "format", GST_FORMAT_TIME,
6488                                                                                                                         "caps", player->a_stream_caps, NULL);
6489
6490                                         if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6491                                                 g_object_set(G_OBJECT(elem_src_audio), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6492                                         if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6493                                                 g_object_set(G_OBJECT(elem_src_audio), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6494
6495                                         /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6496                                         gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_audio), GST_APP_STREAM_TYPE_SEEKABLE);
6497                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6498                                                                                                                 G_CALLBACK(__gst_seek_audio_data), player);
6499                                 }
6500                         } else if (player->a_stream_caps && element) {
6501                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6502                                                                                                 "caps", player->a_stream_caps, NULL);
6503
6504                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6505                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6506                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6507                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6508
6509                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6510                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6511                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6512                                                                                                                         G_CALLBACK(__gst_seek_audio_data), player);
6513                         }
6514
6515                         if (player->s_stream_caps && elem_src_subtitle) {
6516                                 g_object_set(G_OBJECT(elem_src_subtitle), "format", GST_FORMAT_TIME,
6517                                                                                                                  "caps", player->s_stream_caps, NULL);
6518
6519                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6520                                         g_object_set(G_OBJECT(elem_src_subtitle), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6521                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6522                                         g_object_set(G_OBJECT(elem_src_subtitle), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6523
6524                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_subtitle), GST_APP_STREAM_TYPE_SEEKABLE);
6525
6526                                 MMPLAYER_SIGNAL_CONNECT(player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6527                                                                                                                                 G_CALLBACK(__gst_seek_subtitle_data), player);
6528                         }
6529
6530                         if (player->v_stream_caps && element) {
6531                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6532                                                                                                                 G_CALLBACK(__gst_appsrc_feed_video_data), player);
6533                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6534                                                                                                                 G_CALLBACK(__gst_appsrc_enough_video_data), player);
6535
6536                                 if (player->a_stream_caps && elem_src_audio) {
6537                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6538                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6539                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6540                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6541                                 }
6542                         } else if (player->a_stream_caps && element) {
6543                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6544                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6545                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6546                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6547                         }
6548
6549                         if (player->s_stream_caps && elem_src_subtitle)
6550                                 MMPLAYER_SIGNAL_CONNECT(player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6551                                                                                                                 G_CALLBACK(__gst_appsrc_feed_subtitle_data), player);
6552
6553                         need_state_holder = FALSE;
6554
6555                         mm_attrs_set_int_by_name(attrs, "profile_prepare_async", TRUE);
6556                         if (mmf_attrs_commit(attrs)) /* return -1 if error */
6557                                 LOGE("failed to commit\n");
6558                 }
6559                 break;
6560         /* appsrc */
6561         case MM_PLAYER_URI_TYPE_MEM:
6562                 {
6563                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
6564
6565                         LOGD("mem src is selected\n");
6566
6567                         element = gst_element_factory_make("appsrc", "mem-source");
6568                         if (!element) {
6569                                 LOGE("failed to create appsrc element\n");
6570                                 break;
6571                         }
6572
6573                         g_object_set(element, "stream-type", stream_type, NULL);
6574                         g_object_set(element, "size", player->mem_buf.len, NULL);
6575                         g_object_set(element, "blocksize", (guint64)20480, NULL);
6576
6577                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6578                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->mem_buf);
6579                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6580                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->mem_buf);
6581                 }
6582                 break;
6583         case MM_PLAYER_URI_TYPE_URL:
6584                 break;
6585
6586         case MM_PLAYER_URI_TYPE_TEMP:
6587                 break;
6588
6589         case MM_PLAYER_URI_TYPE_NONE:
6590         default:
6591                 break;
6592         }
6593
6594         /* check source element is OK */
6595         if (!element) {
6596                 LOGE("no source element was created.\n");
6597                 goto INIT_ERROR;
6598         }
6599
6600         /* take source element */
6601         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
6602         mainbin[MMPLAYER_M_SRC].gst = element;
6603         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
6604
6605         if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL)) {
6606                 player->streamer = __mm_player_streaming_create();
6607                 __mm_player_streaming_initialize(player->streamer);
6608         }
6609
6610         if (MMPLAYER_IS_HTTP_PD(player)) {
6611                 gdouble pre_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
6612
6613                 LOGD("Picked queue2 element(pre buffer : %d sec)....\n", pre_buffering_time);
6614                 element = gst_element_factory_make("queue2", "queue2");
6615                 if (!element) {
6616                         LOGE("failed to create http streaming buffer element\n");
6617                         goto INIT_ERROR;
6618                 }
6619
6620                 /* take it */
6621                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
6622                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
6623                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
6624
6625                 pre_buffering_time = (pre_buffering_time > 0) ? (pre_buffering_time) : (player->ini.http_buffering_time);
6626
6627                 __mm_player_streaming_set_queue2(player->streamer,
6628                                 element,
6629                                 TRUE,
6630                                 player->ini.http_max_size_bytes,
6631                                 pre_buffering_time,
6632                                 1.0,
6633                                 player->ini.http_buffering_limit,
6634                                 MUXED_BUFFER_TYPE_MEM_QUEUE,
6635                                 NULL,
6636                                 0);
6637         }
6638         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
6639                 if (player->v_stream_caps) {
6640                         es_video_queue = gst_element_factory_make("queue2", "video_queue");
6641                         if (!es_video_queue) {
6642                                 LOGE("create es_video_queue for es player failed\n");
6643                                 goto INIT_ERROR;
6644                         }
6645                         g_object_set(G_OBJECT(es_video_queue), "max-size-buffers", 2, NULL);
6646                         mainbin[MMPLAYER_M_V_BUFFER].id = MMPLAYER_M_V_BUFFER;
6647                         mainbin[MMPLAYER_M_V_BUFFER].gst = es_video_queue;
6648                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_V_BUFFER]);
6649
6650                         /* Adding audio appsrc to bucket */
6651                         if (player->a_stream_caps && elem_src_audio) {
6652                                 mainbin[MMPLAYER_M_2ND_SRC].id = MMPLAYER_M_2ND_SRC;
6653                                 mainbin[MMPLAYER_M_2ND_SRC].gst = elem_src_audio;
6654                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_2ND_SRC]);
6655
6656                                 es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6657                                 if (!es_audio_queue) {
6658                                         LOGE("create es_audio_queue for es player failed\n");
6659                                         goto INIT_ERROR;
6660                                 }
6661                                 g_object_set(G_OBJECT(es_audio_queue), "max-size-buffers", 2, NULL);
6662
6663                                 mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6664                                 mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6665                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6666                         }
6667                 } else if (player->a_stream_caps) {
6668                         /* Only audio stream, no video */
6669                         es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6670                         if (!es_audio_queue) {
6671                                 LOGE("create es_audio_queue for es player failed\n");
6672                                 goto INIT_ERROR;
6673                         }
6674                         mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6675                         mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6676                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6677                 }
6678
6679                 if (player->s_stream_caps && elem_src_subtitle) {
6680                         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6681                         mainbin[MMPLAYER_M_SUBSRC].gst = elem_src_subtitle;
6682                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SUBSRC]);
6683
6684                         es_subtitle_queue = gst_element_factory_make("queue2", "subtitle_queue");
6685                         if (!es_subtitle_queue) {
6686                                 LOGE("create es_subtitle_queue for es player failed\n");
6687                                 goto INIT_ERROR;
6688                         }
6689                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_V_BUFFER;
6690                         mainbin[MMPLAYER_M_S_BUFFER].gst = es_subtitle_queue;
6691                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
6692                 }
6693         }
6694
6695         /* create autoplugging element if src element is not a rtsp src */
6696         if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
6697                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_WFD) &&
6698                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_MS_BUFF)) {
6699                 element = NULL;
6700                 enum MainElementID elemId = MMPLAYER_M_NUM;
6701
6702                 if ((player->use_decodebin) &&
6703                         ((MMPLAYER_IS_HTTP_PD(player)) ||
6704                         (!MMPLAYER_IS_HTTP_STREAMING(player)))) {
6705                         elemId = MMPLAYER_M_AUTOPLUG;
6706                         element = __mmplayer_create_decodebin(player);
6707                         if (element) {
6708                                 /* default size of mq in decodebin is 2M
6709                                  * but it can cause blocking issue during seeking depends on content. */
6710                                 g_object_set(G_OBJECT(element), "max-size-bytes", (5*1024*1024), NULL);
6711                         }
6712                         need_state_holder = FALSE;
6713                 } else {
6714                         elemId = MMPLAYER_M_TYPEFIND;
6715                         element = gst_element_factory_make("typefind", "typefinder");
6716                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
6717                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
6718                 }
6719
6720
6721                 /* check autoplug element is OK */
6722                 if (!element) {
6723                         LOGE("can not create element(%d)\n", elemId);
6724                         goto INIT_ERROR;
6725                 }
6726
6727                 mainbin[elemId].id = elemId;
6728                 mainbin[elemId].gst = element;
6729
6730                 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
6731         }
6732
6733         /* add elements to pipeline */
6734         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket)) {
6735                 LOGE("Failed to add elements to pipeline\n");
6736                 goto INIT_ERROR;
6737         }
6738
6739
6740         /* linking elements in the bucket by added order. */
6741         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
6742                 LOGE("Failed to link some elements\n");
6743                 goto INIT_ERROR;
6744         }
6745
6746
6747         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
6748         if (need_state_holder) {
6749                 /* create */
6750                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
6751                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
6752
6753                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst) {
6754                         LOGE("fakesink element could not be created\n");
6755                         goto INIT_ERROR;
6756                 }
6757                 GST_OBJECT_FLAG_UNSET(mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
6758
6759                 /* take ownership of fakesink. we are reusing it */
6760                 gst_object_ref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
6761
6762                 /* add */
6763                 if (FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
6764                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst)) {
6765                         LOGE("failed to add fakesink to bin\n");
6766                         goto INIT_ERROR;
6767                 }
6768         }
6769
6770         /* now we have completed mainbin. take it */
6771         player->pipeline->mainbin = mainbin;
6772
6773         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
6774                 GstPad *srcpad = NULL;
6775
6776                 if (mainbin[MMPLAYER_M_V_BUFFER].gst) {
6777                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_V_BUFFER].gst, "src");
6778                         if (srcpad) {
6779                                 __mmplayer_gst_create_decoder(player,
6780                                                                                                 MM_PLAYER_TRACK_TYPE_VIDEO,
6781                                                                                                 srcpad,
6782                                                                                                 MMPLAYER_M_AUTOPLUG_V_DEC,
6783                                                                                                 "video_decodebin");
6784
6785                                 gst_object_unref(GST_OBJECT(srcpad));
6786                                 srcpad = NULL;
6787                         }
6788                 }
6789
6790                 if ((player->a_stream_caps) && (mainbin[MMPLAYER_M_A_BUFFER].gst)) {
6791                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_BUFFER].gst, "src");
6792                         if (srcpad) {
6793                                 __mmplayer_gst_create_decoder(player,
6794                                                                                                 MM_PLAYER_TRACK_TYPE_AUDIO,
6795                                                                                                 srcpad,
6796                                                                                                 MMPLAYER_M_AUTOPLUG_A_DEC,
6797                                                                                                 "audio_decodebin");
6798
6799                                 gst_object_unref(GST_OBJECT(srcpad));
6800                                 srcpad = NULL;
6801                         } // else error
6802                 } //  else error
6803
6804                 if (mainbin[MMPLAYER_M_S_BUFFER].gst)
6805                         __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
6806         }
6807
6808         /* connect bus callback */
6809         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
6810         if (!bus) {
6811                 LOGE("cannot get bus from pipeline.\n");
6812                 goto INIT_ERROR;
6813         }
6814
6815         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
6816
6817         player->context.thread_default = g_main_context_get_thread_default();
6818
6819         if (NULL == player->context.thread_default) {
6820                 player->context.thread_default = g_main_context_default();
6821                 LOGD("thread-default context is the global default context");
6822         }
6823         LOGW("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
6824
6825         /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
6826         if (__mmplayer_check_subtitle(player)) {
6827                 if (MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player))
6828                         LOGE("fail to create subtitle src\n");
6829         }
6830
6831         /* set sync handler to get tag synchronously */
6832         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL);
6833
6834         /* finished */
6835         gst_object_unref(GST_OBJECT(bus));
6836         g_list_free(element_bucket);
6837
6838         MMPLAYER_FLEAVE();
6839
6840         return MM_ERROR_NONE;
6841
6842 INIT_ERROR:
6843
6844         __mmplayer_gst_destroy_pipeline(player);
6845         g_list_free(element_bucket);
6846
6847         if (mainbin) {
6848                 /* release element which are not added to bin */
6849                 for (i = 1; i < MMPLAYER_M_NUM; i++) {
6850                         /* NOTE : skip pipeline */
6851                         if (mainbin[i].gst) {
6852                                 GstObject* parent = NULL;
6853                                 parent = gst_element_get_parent(mainbin[i].gst);
6854
6855                                 if (!parent) {
6856                                         gst_object_unref(GST_OBJECT(mainbin[i].gst));
6857                                         mainbin[i].gst = NULL;
6858                                 } else
6859                                         gst_object_unref(GST_OBJECT(parent));
6860                         }
6861                 }
6862
6863                 /* release pipeline with it's childs */
6864                 if (mainbin[MMPLAYER_M_PIPE].gst)
6865                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
6866
6867                 MMPLAYER_FREEIF(mainbin);
6868         }
6869
6870         MMPLAYER_FREEIF(player->pipeline);
6871         return MM_ERROR_PLAYER_INTERNAL;
6872 }
6873
6874 static void
6875 __mmplayer_reset_gapless_state(mm_player_t* player)
6876 {
6877         MMPLAYER_FENTER();
6878         MMPLAYER_RETURN_IF_FAIL(player
6879                 && player->pipeline
6880                 && player->pipeline->audiobin
6881                 && player->pipeline->audiobin[MMPLAYER_A_BIN].gst);
6882
6883         memset(&player->gapless, 0, sizeof(mm_player_gapless_t));
6884
6885         MMPLAYER_FLEAVE();
6886         return;
6887 }
6888
6889 static int
6890 __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
6891 {
6892         gint timeout = 0;
6893         int ret = MM_ERROR_NONE;
6894
6895         MMPLAYER_FENTER();
6896
6897         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_INVALID_HANDLE);
6898
6899         /* cleanup stuffs */
6900         MMPLAYER_FREEIF(player->type);
6901         player->have_dynamic_pad = FALSE;
6902         player->no_more_pad = FALSE;
6903         player->num_dynamic_pad = 0;
6904         player->demux_pad_index = 0;
6905         player->subtitle_language_list = NULL;
6906         player->use_deinterleave = FALSE;
6907         player->max_audio_channels = 0;
6908         player->video_share_api_delta = 0;
6909         player->video_share_clock_delta = 0;
6910         player->video_hub_download_mode = 0;
6911         __mmplayer_reset_gapless_state(player);
6912
6913         if (player->streamer) {
6914                 __mm_player_streaming_deinitialize(player->streamer);
6915                 __mm_player_streaming_destroy(player->streamer);
6916                 player->streamer = NULL;
6917         }
6918
6919         /* cleanup unlinked mime type */
6920         MMPLAYER_FREEIF(player->unlinked_audio_mime);
6921         MMPLAYER_FREEIF(player->unlinked_video_mime);
6922         MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
6923
6924         /* cleanup running stuffs */
6925         __mmplayer_cancel_eos_timer(player);
6926
6927         /* cleanup gst stuffs */
6928         if (player->pipeline) {
6929                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
6930                 GstTagList* tag_list = player->pipeline->tag_list;
6931
6932                 /* first we need to disconnect all signal hander */
6933                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_ALL);
6934
6935                 /* disconnecting bus watch */
6936                 if (player->bus_watcher)
6937                         __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
6938                 player->bus_watcher = 0;
6939
6940                 if (mainbin) {
6941                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
6942                         MMPlayerGstElement* videobin = player->pipeline->videobin;
6943                         MMPlayerGstElement* textbin = player->pipeline->textbin;
6944                         GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
6945                         gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
6946                         gst_object_unref(bus);
6947
6948                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
6949                         ret = __mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout);
6950                         if (ret != MM_ERROR_NONE) {
6951                                 LOGE("fail to change state to NULL\n");
6952                                 return MM_ERROR_PLAYER_INTERNAL;
6953                         }
6954
6955                         LOGW("succeeded in chaning state to NULL\n");
6956
6957                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
6958
6959                         /* free fakesink */
6960                         if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
6961                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
6962
6963                         /* free avsysaudiosink
6964                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
6965                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
6966                         */
6967                         MMPLAYER_FREEIF(audiobin);
6968                         MMPLAYER_FREEIF(videobin);
6969                         MMPLAYER_FREEIF(textbin);
6970                         MMPLAYER_FREEIF(mainbin);
6971                 }
6972
6973                 if (tag_list)
6974                         gst_tag_list_free(tag_list);
6975
6976                 MMPLAYER_FREEIF(player->pipeline);
6977         }
6978         MMPLAYER_FREEIF(player->album_art);
6979
6980         if (player->v_stream_caps) {
6981                 gst_caps_unref(player->v_stream_caps);
6982                 player->v_stream_caps = NULL;
6983         }
6984         if (player->a_stream_caps) {
6985                 gst_caps_unref(player->a_stream_caps);
6986                 player->a_stream_caps = NULL;
6987         }
6988
6989         if (player->s_stream_caps) {
6990                 gst_caps_unref(player->s_stream_caps);
6991                 player->s_stream_caps = NULL;
6992         }
6993         _mmplayer_track_destroy(player);
6994
6995         if (player->sink_elements)
6996                 g_list_free(player->sink_elements);
6997         player->sink_elements = NULL;
6998
6999         if (player->bufmgr) {
7000                 tbm_bufmgr_deinit(player->bufmgr);
7001                 player->bufmgr = NULL;
7002         }
7003
7004         LOGW("finished destroy pipeline\n");
7005
7006         MMPLAYER_FLEAVE();
7007
7008         return ret;
7009 }
7010
7011 static int __gst_realize(mm_player_t* player) // @
7012 {
7013         gint timeout = 0;
7014         int ret = MM_ERROR_NONE;
7015
7016         MMPLAYER_FENTER();
7017
7018         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7019
7020         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7021
7022         ret = __mmplayer_gst_create_pipeline(player);
7023         if (ret) {
7024                 LOGE("failed to create pipeline\n");
7025                 return ret;
7026         }
7027
7028         /* set pipeline state to READY */
7029         /* NOTE : state change to READY must be performed sync. */
7030         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7031         ret = __mmplayer_gst_set_state(player,
7032                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
7033
7034         if (ret != MM_ERROR_NONE) {
7035                 /* return error if failed to set state */
7036                 LOGE("failed to set READY state");
7037                 return ret;
7038         }
7039
7040         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
7041
7042         /* create dot before error-return. for debugging */
7043         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-realize");
7044
7045         MMPLAYER_FLEAVE();
7046
7047         return ret;
7048 }
7049
7050 static int __gst_unrealize(mm_player_t* player) // @
7051 {
7052         int ret = MM_ERROR_NONE;
7053
7054         MMPLAYER_FENTER();
7055
7056         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7057
7058         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
7059         MMPLAYER_PRINT_STATE(player);
7060
7061         /* release miscellaneous information */
7062         __mmplayer_release_misc(player);
7063
7064         /* destroy pipeline */
7065         ret = __mmplayer_gst_destroy_pipeline(player);
7066         if (ret != MM_ERROR_NONE) {
7067                 LOGE("failed to destory pipeline\n");
7068                 return ret;
7069         }
7070
7071         /* release miscellaneous information.
7072            these info needs to be released after pipeline is destroyed. */
7073         __mmplayer_release_misc_post(player);
7074
7075         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
7076
7077         MMPLAYER_FLEAVE();
7078
7079         return ret;
7080 }
7081
7082 static int __gst_pending_seek(mm_player_t* player)
7083 {
7084         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7085         int ret = MM_ERROR_NONE;
7086
7087         MMPLAYER_FENTER();
7088
7089         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7090
7091         if (!player->pending_seek.is_pending) {
7092                 LOGD("pending seek is not reserved. nothing to do.\n");
7093                 return ret;
7094         }
7095
7096         /* check player state if player could pending seek or not. */
7097         current_state = MMPLAYER_CURRENT_STATE(player);
7098
7099         if (current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING) {
7100                 LOGW("try to pending seek in %s state, try next time. \n",
7101                         MMPLAYER_STATE_GET_NAME(current_state));
7102                 return ret;
7103         }
7104
7105         LOGD("trying to play from(%lu) pending position\n", player->pending_seek.pos);
7106
7107         ret = __gst_set_position(player, player->pending_seek.format, player->pending_seek.pos, FALSE);
7108
7109         if (MM_ERROR_NONE != ret)
7110                 LOGE("failed to seek pending postion. just keep staying current position.\n");
7111
7112         player->pending_seek.is_pending = FALSE;
7113
7114         MMPLAYER_FLEAVE();
7115
7116         return ret;
7117 }
7118
7119 static int __gst_start(mm_player_t* player) // @
7120 {
7121         gboolean sound_extraction = 0;
7122         int ret = MM_ERROR_NONE;
7123         gboolean async = FALSE;
7124
7125         MMPLAYER_FENTER();
7126
7127         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7128
7129         /* get sound_extraction property */
7130         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
7131
7132         /* NOTE : if SetPosition was called before Start. do it now */
7133         /* streaming doesn't support it. so it should be always sync */
7134         /* !!create one more api to check if there is pending seek rather than checking variables */
7135         if ((player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player)) {
7136                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
7137                 ret = __gst_pause(player, FALSE);
7138                 if (ret != MM_ERROR_NONE) {
7139                         LOGE("failed to set state to PAUSED for pending seek\n");
7140                         return ret;
7141                 }
7142
7143                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
7144
7145                 if (sound_extraction) {
7146                         LOGD("setting pcm extraction\n");
7147
7148                         ret = __mmplayer_set_pcm_extraction(player);
7149                         if (MM_ERROR_NONE != ret) {
7150                                 LOGW("failed to set pcm extraction\n");
7151                                 return ret;
7152                         }
7153                 } else {
7154                         if (MM_ERROR_NONE != __gst_pending_seek(player))
7155                                 LOGW("failed to seek pending postion. starting from the begin of content.\n");
7156                 }
7157         }
7158
7159         LOGD("current state before doing transition");
7160         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7161         MMPLAYER_PRINT_STATE(player);
7162
7163         /* set pipeline state to PLAYING  */
7164         if (player->es_player_push_mode)
7165                 async = TRUE;
7166         /* set pipeline state to PLAYING  */
7167         ret = __mmplayer_gst_set_state(player,
7168                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
7169
7170         if (ret == MM_ERROR_NONE) {
7171                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7172         } else {
7173                 LOGE("failed to set state to PLAYING");
7174                 return ret;
7175         }
7176
7177         /* generating debug info before returning error */
7178         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-start");
7179
7180         MMPLAYER_FLEAVE();
7181
7182         return ret;
7183 }
7184
7185 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
7186 {
7187         MMPLAYER_FENTER();
7188
7189         MMPLAYER_RETURN_IF_FAIL(player
7190                 && player->pipeline
7191                 && player->pipeline->audiobin
7192                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
7193
7194         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", TRUE, NULL);
7195
7196         usleep(time);
7197
7198         MMPLAYER_FLEAVE();
7199 }
7200
7201 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
7202 {
7203         MMPLAYER_FENTER();
7204
7205         MMPLAYER_RETURN_IF_FAIL(player
7206                 && player->pipeline
7207                 && player->pipeline->audiobin
7208                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
7209
7210         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", FALSE, NULL);
7211
7212         MMPLAYER_FLEAVE();
7213 }
7214
7215 static int __gst_stop(mm_player_t* player) // @
7216 {
7217         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
7218         MMHandleType attrs = 0;
7219         gboolean fadedown = FALSE;
7220         gboolean rewind = FALSE;
7221         gint timeout = 0;
7222         int ret = MM_ERROR_NONE;
7223         gboolean async = FALSE;
7224
7225         MMPLAYER_FENTER();
7226
7227         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7228         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7229
7230         LOGD("current state before doing transition");
7231         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7232         MMPLAYER_PRINT_STATE(player);
7233
7234         attrs = MMPLAYER_GET_ATTRS(player);
7235         if (!attrs) {
7236                 LOGE("cannot get content attribute\n");
7237                 return MM_ERROR_PLAYER_INTERNAL;
7238         }
7239
7240         mm_attrs_get_int_by_name(attrs, "sound_fadedown", &fadedown);
7241
7242         /* enable fadedown */
7243         if (fadedown || player->sound_focus.by_asm_cb)
7244                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
7245
7246         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
7247         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7248
7249         if ((!MMPLAYER_IS_STREAMING(player) && !MMPLAYER_IS_MS_BUFF_SRC(player)) ||
7250                 (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked))
7251                 rewind = TRUE;
7252
7253         if (player->es_player_push_mode)
7254                 async = TRUE;
7255         /* set gst state */
7256         ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, timeout);
7257
7258         /* disable fadeout */
7259         if (fadedown || player->sound_focus.by_asm_cb)
7260                 __mmplayer_undo_sound_fadedown(player);
7261
7262         /* return if set_state has failed */
7263         if (ret != MM_ERROR_NONE) {
7264                 LOGE("failed to set state.\n");
7265                 return ret;
7266         }
7267
7268         /* rewind */
7269         if (rewind) {
7270                 if (!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7271                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
7272                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
7273                         LOGW("failed to rewind\n");
7274                         ret = MM_ERROR_PLAYER_SEEK;
7275                 }
7276         }
7277
7278         /* initialize */
7279         player->sent_bos = FALSE;
7280
7281         if (player->es_player_push_mode) //for cloudgame
7282                 timeout = 0;
7283
7284         /* wait for seek to complete */
7285         change_ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
7286         if (change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL) {
7287                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
7288         } else {
7289                 LOGE("fail to stop player.\n");
7290                 ret = MM_ERROR_PLAYER_INTERNAL;
7291                 __mmplayer_dump_pipeline_state(player);
7292         }
7293
7294         /* generate dot file if enabled */
7295         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-stop");
7296
7297         MMPLAYER_FLEAVE();
7298
7299         return ret;
7300 }
7301
7302 int __gst_pause(mm_player_t* player, gboolean async) // @
7303 {
7304         int ret = MM_ERROR_NONE;
7305
7306         MMPLAYER_FENTER();
7307
7308         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7309         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7310
7311         LOGD("current state before doing transition");
7312         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
7313         MMPLAYER_PRINT_STATE(player);
7314
7315         /* set pipeline status to PAUSED */
7316         player->ignore_asyncdone = TRUE;
7317
7318         ret = __mmplayer_gst_set_state(player,
7319                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
7320
7321         player->ignore_asyncdone = FALSE;
7322
7323         if (FALSE == async) {
7324                 if (ret != MM_ERROR_NONE) {
7325                         GstMessage *msg = NULL;
7326                         GTimer *timer = NULL;
7327                         gdouble MAX_TIMEOUT_SEC = 3;
7328
7329                         LOGE("failed to set state to PAUSED");
7330
7331                         if (player->msg_posted) {
7332                                 LOGE("error msg is already posted.");
7333                                 return ret;
7334                         }
7335
7336                         timer = g_timer_new();
7337                         g_timer_start(timer);
7338
7339                         GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
7340
7341                         do {
7342                                 msg = gst_bus_timed_pop(bus, 100 * GST_MSECOND);
7343                                 if (msg) {
7344                                         if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
7345                                                 GError *error = NULL;
7346
7347                                                 /* parse error code */
7348                                                 gst_message_parse_error(msg, &error, NULL);
7349
7350                                                 if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
7351                                                         /* Note : the streaming error from the streaming source is handled
7352                                                          *   using __mmplayer_handle_streaming_error.
7353                                                          */
7354                                                         __mmplayer_handle_streaming_error(player, msg);
7355
7356                                                 } else if (error) {
7357                                                         LOGE("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
7358
7359                                                         if (error->domain == GST_STREAM_ERROR)
7360                                                                 ret = __gst_handle_stream_error(player, error, msg);
7361                                                         else if (error->domain == GST_RESOURCE_ERROR)
7362                                                                 ret = __gst_handle_resource_error(player, error->code, NULL);
7363                                                         else if (error->domain == GST_LIBRARY_ERROR)
7364                                                                 ret = __gst_handle_library_error(player, error->code);
7365                                                         else if (error->domain == GST_CORE_ERROR)
7366                                                                 ret = __gst_handle_core_error(player, error->code);
7367                                                 }
7368                                                 player->msg_posted = TRUE;
7369                                         }
7370                                         gst_message_unref(msg);
7371                                 }
7372                         } while (!player->msg_posted && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
7373                         /* clean */
7374                         gst_object_unref(bus);
7375                         g_timer_stop(timer);
7376                         g_timer_destroy(timer);
7377
7378                         return ret;
7379
7380                 } else if ((!MMPLAYER_IS_RTSP_STREAMING(player)) && (!player->video_stream_cb) &&
7381                                    (!player->pipeline->videobin) && (!player->pipeline->audiobin)) {
7382
7383                         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
7384
7385                 } else if (ret == MM_ERROR_NONE) {
7386
7387                         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
7388                 }
7389         }
7390
7391         /* generate dot file before returning error */
7392         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-pause");
7393
7394         MMPLAYER_FLEAVE();
7395
7396         return ret;
7397 }
7398
7399 int __gst_resume(mm_player_t* player, gboolean async) // @
7400 {
7401         int ret = MM_ERROR_NONE;
7402         gint timeout = 0;
7403
7404         MMPLAYER_FENTER();
7405
7406         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline,
7407                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7408
7409         LOGD("current state before doing transition");
7410         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7411         MMPLAYER_PRINT_STATE(player);
7412
7413         /* generate dot file before returning error */
7414         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-resume");
7415
7416         if (async)
7417                 LOGD("do async state transition to PLAYING.\n");
7418
7419         /* set pipeline state to PLAYING */
7420         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7421
7422         ret = __mmplayer_gst_set_state(player,
7423                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout);
7424         if (ret != MM_ERROR_NONE) {
7425                 LOGE("failed to set state to PLAYING\n");
7426                 return ret;
7427         } else {
7428                 if (async == FALSE) {
7429                         // MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7430                         LOGD("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
7431                         ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
7432                 }
7433         }
7434
7435         /* generate dot file before returning error */
7436         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-resume");
7437
7438         MMPLAYER_FLEAVE();
7439
7440         return ret;
7441 }
7442
7443 static int
7444 __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called) // @
7445 {
7446         unsigned long dur_msec = 0;
7447         gint64 dur_nsec = 0;
7448         gint64 pos_nsec = 0;
7449         gboolean ret = TRUE;
7450         gboolean accurated = FALSE;
7451         GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
7452
7453         MMPLAYER_FENTER();
7454         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7455         MMPLAYER_RETURN_VAL_IF_FAIL(!MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP);
7456
7457         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
7458                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
7459                 goto PENDING;
7460
7461         if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
7462                 /* check duration */
7463                 /* NOTE : duration cannot be zero except live streaming.
7464                  *              Since some element could have some timing problemn with quering duration, try again.
7465                  */
7466                 if (!player->duration) {
7467                         if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec))
7468                         {
7469                                 /* For RTSP Streaming , duration is not returned in READY state. So seek to the previous position does not work properly.
7470                                  * Added a patch to postpone the actual seek when state changes to PLAY. Sending a fake SEEK_COMPLETED event to finish the current request. */
7471                                 if ((MMPLAYER_IS_RTSP_STREAMING( player )) && (__mmplayer_get_stream_service_type(player) != STREAMING_SERVICE_LIVE)) {
7472                                         player->pending_seek.is_pending = TRUE;
7473                                         player->pending_seek.format = format;
7474                                         player->pending_seek.pos = position;
7475                                         player->doing_seek = FALSE;
7476                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
7477                                         return MM_ERROR_NONE;
7478                                 } else {
7479                                         goto SEEK_ERROR;
7480                                 }
7481                         }
7482                         player->duration = dur_nsec;
7483                 }
7484
7485                 if (player->duration) {
7486                         dur_msec = GST_TIME_AS_MSECONDS(player->duration);
7487                 } else {
7488                         LOGE("could not get the duration. fail to seek.\n");
7489                         goto SEEK_ERROR;
7490                 }
7491         }
7492         LOGD("playback rate: %f\n", player->playback_rate);
7493
7494         mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
7495         if (accurated)
7496                 seek_flags |= GST_SEEK_FLAG_ACCURATE;
7497         else
7498                 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
7499
7500         /* do seek */
7501         switch (format) {
7502         case MM_PLAYER_POS_FORMAT_TIME:
7503         {
7504                 if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
7505                         GstQuery *query = NULL;
7506                         gboolean seekable = FALSE;
7507
7508                         /* check position is valid or not */
7509                         if (position > dur_msec)
7510                                 goto INVALID_ARGS;
7511
7512                         query = gst_query_new_seeking (GST_FORMAT_TIME);
7513                         if (gst_element_query (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, query)) {
7514                                 gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
7515                                 gst_query_unref (query);
7516
7517                                 if (!seekable) {
7518                                         LOGW("non-seekable content");
7519                                         player->doing_seek = FALSE;
7520                                         return MM_ERROR_PLAYER_NO_OP;
7521                                 }
7522                         } else {
7523                                 LOGW("failed to get seeking query");
7524                                 gst_query_unref (query); /* keep seeking operation */
7525                         }
7526
7527                         LOGD("seeking to(%lu) msec, duration is %d msec\n", position, dur_msec);
7528
7529                         /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
7530                            But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
7531                            This causes problem is position calculation during normal pause resume scenarios also.
7532                            Currently during seek , we are sending the current position to rtspsrc module for position saving for later use. */
7533                         if ((MMPLAYER_IS_RTSP_STREAMING( player )) &&
7534                                 (__mmplayer_get_stream_service_type(player) != STREAMING_SERVICE_LIVE)) {
7535                                 if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
7536                                         LOGW("getting current position failed in seek\n");
7537
7538                                 player->last_position = pos_nsec;
7539                                 g_object_set( player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL );
7540                         }
7541
7542                         if (player->doing_seek) {
7543                                 LOGD("not completed seek");
7544                                 return MM_ERROR_PLAYER_DOING_SEEK;
7545                         }
7546                 }
7547
7548                 if (!internal_called)
7549                         player->doing_seek = TRUE;
7550
7551                 pos_nsec = position * G_GINT64_CONSTANT(1000000);
7552
7553                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked)) {
7554                         gint64 cur_time = 0;
7555
7556                         /* get current position */
7557                         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
7558
7559                         /* flush */
7560                         GstEvent *event = gst_event_new_seek(1.0,
7561                                                         GST_FORMAT_TIME,
7562                                                         (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
7563                                                         GST_SEEK_TYPE_SET, cur_time,
7564                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7565                         if (event)
7566                                 __gst_send_event_to_sink(player, event);
7567
7568                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
7569                                 __gst_pause(player, FALSE);
7570                 }
7571
7572                 /* rtsp streaming case, there is no sink after READY TO PAUSE state(no preroll state change).
7573                         that's why set position through property. */
7574                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
7575                         (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) &&
7576                         (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY) &&
7577                         (!player->videodec_linked) && (!player->audiodec_linked)) {
7578
7579                         g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "pending-start-position", pos_nsec, NULL);
7580                         LOGD("[%s] set position =%"GST_TIME_FORMAT,
7581                                         GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), GST_TIME_ARGS(pos_nsec));
7582                         player->doing_seek = FALSE;
7583                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
7584                 } else {
7585                         ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7586                                                         GST_FORMAT_TIME, seek_flags,
7587                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7588                 }
7589
7590                 if (!ret) {
7591                         LOGE("failed to set position. dur[%lu]  pos[%lu]  pos_msec[%llu]\n", dur_msec, position, pos_nsec);
7592                         goto SEEK_ERROR;
7593                 }
7594         }
7595         break;
7596
7597         case MM_PLAYER_POS_FORMAT_PERCENT:
7598         {
7599                 LOGD("seeking to(%lu)%% \n", position);
7600
7601                 if (player->doing_seek) {
7602                         LOGD("not completed seek");
7603                         return MM_ERROR_PLAYER_DOING_SEEK;
7604                 }
7605
7606                 if (!internal_called)
7607                         player->doing_seek = TRUE;
7608
7609                 /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
7610                 pos_nsec = (gint64)((position * player->duration) / 100);
7611                 ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7612                                                 GST_FORMAT_TIME, seek_flags,
7613                                                 GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7614                 if (!ret) {
7615                         LOGE("failed to set position. dur[%lud]  pos[%lud]  pos_msec[%"G_GUINT64_FORMAT"]\n", dur_msec, position, pos_nsec);
7616                         goto SEEK_ERROR;
7617                 }
7618         }
7619         break;
7620
7621         default:
7622                 goto INVALID_ARGS;
7623         }
7624
7625         /* NOTE : store last seeking point to overcome some bad operation
7626           *     (returning zero when getting current position) of some elements
7627           */
7628         player->last_position = pos_nsec;
7629
7630         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
7631         if (player->playback_rate > 1.0)
7632                 _mmplayer_set_playspeed((MMHandleType)player, player->playback_rate, FALSE);
7633
7634         MMPLAYER_FLEAVE();
7635         return MM_ERROR_NONE;
7636
7637 PENDING:
7638         player->pending_seek.is_pending = TRUE;
7639         player->pending_seek.format = format;
7640         player->pending_seek.pos = position;
7641
7642         LOGW("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n",
7643                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
7644
7645         return MM_ERROR_NONE;
7646
7647 INVALID_ARGS:
7648         LOGE("invalid arguments, position : %ld  dur : %ld format : %d \n", position, dur_msec, format);
7649         return MM_ERROR_INVALID_ARGUMENT;
7650
7651 SEEK_ERROR:
7652         player->doing_seek = FALSE;
7653         return MM_ERROR_PLAYER_SEEK;
7654 }
7655
7656 #define TRICKPLAY_OFFSET GST_MSECOND
7657
7658 static int
7659 __gst_get_position(mm_player_t* player, int format, unsigned long* position) // @
7660 {
7661         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7662         gint64 pos_msec = 0;
7663         gboolean ret = TRUE;
7664
7665         MMPLAYER_RETURN_VAL_IF_FAIL(player && position && player->pipeline && player->pipeline->mainbin,
7666                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7667
7668         current_state = MMPLAYER_CURRENT_STATE(player);
7669
7670         /* NOTE : query position except paused state to overcome some bad operation
7671          * please refer to below comments in details
7672          */
7673         if (current_state != MM_PLAYER_STATE_PAUSED)
7674                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
7675
7676         /* NOTE : get last point to overcome some bad operation of some elements
7677          *(returning zero when getting current position in paused state
7678          * and when failed to get postion during seeking
7679          */
7680         if ((current_state == MM_PLAYER_STATE_PAUSED) || (!ret)) {
7681                 LOGD("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_msec), ret, current_state);
7682
7683                 if (player->playback_rate < 0.0)
7684                         pos_msec = player->last_position - TRICKPLAY_OFFSET;
7685                 else
7686                         pos_msec = player->last_position;
7687
7688                 if (!ret)
7689                         pos_msec = player->last_position;
7690                 else
7691                         player->last_position = pos_msec;
7692
7693                 LOGD("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
7694
7695         } else {
7696                 if (player->duration > 0 && pos_msec > player->duration)
7697                         pos_msec = player->duration;
7698
7699                 if (player->sound_focus.keep_last_pos) {
7700                         LOGD("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position));
7701                         pos_msec = player->last_position;
7702                 } else {
7703                         player->last_position = pos_msec;
7704                 }
7705         }
7706
7707         switch (format) {
7708         case MM_PLAYER_POS_FORMAT_TIME:
7709                 *position = GST_TIME_AS_MSECONDS(pos_msec);
7710                 break;
7711
7712         case MM_PLAYER_POS_FORMAT_PERCENT:
7713         {
7714                 if (player->duration <= 0) {
7715                         LOGD("duration is [%lld], so returning position 0\n", player->duration);
7716                         *position = 0;
7717                 } else {
7718                         LOGD("postion is [%lld] msec , duration is [%lld] msec", pos_msec, player->duration);
7719                         *position = pos_msec * 100 / player->duration;
7720                 }
7721                 break;
7722         }
7723         default:
7724                 return MM_ERROR_PLAYER_INTERNAL;
7725         }
7726
7727         return MM_ERROR_NONE;
7728 }
7729
7730
7731 static int __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
7732 {
7733 #define STREAMING_IS_FINISHED   0
7734 #define BUFFERING_MAX_PER       100
7735 #define DEFAULT_PER_VALUE       -1
7736 #define CHECK_PERCENT_VALUE(a, min, max)(((a) > (min)) ? (((a) < (max)) ? (a) : (max)) : (min))
7737
7738         MMPlayerGstElement *mainbin = NULL;
7739         gint start_per = DEFAULT_PER_VALUE, stop_per = DEFAULT_PER_VALUE;
7740         gint64 buffered_total = 0;
7741         unsigned long position = 0;
7742         gint buffered_sec = -1;
7743         GstBufferingMode mode = GST_BUFFERING_STREAM;
7744         gint64 content_size_time = player->duration;
7745         guint64 content_size_bytes = player->http_content_size;
7746
7747         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
7748                                                 player->pipeline &&
7749                                                 player->pipeline->mainbin,
7750                                                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7751
7752         MMPLAYER_RETURN_VAL_IF_FAIL(start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT);
7753
7754         *start_pos = 0;
7755         *stop_pos = 0;
7756
7757         if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
7758                 /* and rtsp is not ready yet. */
7759                 LOGW("it's only used for http streaming case.\n");
7760                 return MM_ERROR_PLAYER_NO_OP;
7761         }
7762
7763         if (format != MM_PLAYER_POS_FORMAT_PERCENT) {
7764                 LOGW("Time format is not supported yet.\n");
7765                 return MM_ERROR_INVALID_ARGUMENT;
7766         }
7767
7768         if (content_size_time <= 0 || content_size_bytes <= 0) {
7769                 LOGW("there is no content size.");
7770                 return MM_ERROR_NONE;
7771         }
7772
7773         if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position) != MM_ERROR_NONE) {
7774                 LOGW("fail to get current position.");
7775                 return MM_ERROR_NONE;
7776         }
7777
7778         LOGD("pos %d ms, dur %d sec, len %"G_GUINT64_FORMAT" bytes",
7779                 position, (guint)(content_size_time/GST_SECOND), content_size_bytes);
7780
7781         mainbin = player->pipeline->mainbin;
7782         start_per = ceil(100 *(position*GST_MSECOND) / content_size_time);
7783
7784         if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
7785                 GstQuery *query = NULL;
7786                 gint byte_in_rate = 0, byte_out_rate = 0;
7787                 gint64 estimated_total = 0;
7788
7789                 query = gst_query_new_buffering(GST_FORMAT_BYTES);
7790                 if (!query || !gst_element_query(mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query)) {
7791                         LOGW("fail to get buffering query from queue2");
7792                         if (query)
7793                                 gst_query_unref(query);
7794                         return MM_ERROR_NONE;
7795                 }
7796
7797                 gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, NULL);
7798                 LOGD("mode %d, in_rate %d, out_rate %d", mode, byte_in_rate, byte_out_rate);
7799
7800                 if (mode == GST_BUFFERING_STREAM) {
7801                         /* using only queue in case of push mode(ts / mp3) */
7802                         if (gst_element_query_position(mainbin[MMPLAYER_M_SRC].gst,
7803                                 GST_FORMAT_BYTES, &buffered_total)) {
7804                                 LOGD("buffered_total %"G_GINT64_FORMAT, buffered_total);
7805                                 stop_per = 100 * buffered_total / content_size_bytes;
7806                         }
7807                 } else {
7808                         /* GST_BUFFERING_TIMESHIFT or GST_BUFFERING_DOWNLOAD */
7809                         guint idx = 0;
7810                         guint num_of_ranges = 0;
7811                         gint64 start_byte = 0, stop_byte = 0;
7812
7813                         gst_query_parse_buffering_range(query, NULL, NULL, NULL, &estimated_total);
7814                         if (estimated_total != STREAMING_IS_FINISHED) {
7815                                 /* buffered size info from queue2 */
7816                                 num_of_ranges = gst_query_get_n_buffering_ranges(query);
7817                                 for (idx = 0; idx < num_of_ranges; idx++) {
7818                                         gst_query_parse_nth_buffering_range(query, idx, &start_byte, &stop_byte);
7819                                         LOGD("range %d, %"G_GINT64_FORMAT" ~ %"G_GUINT64_FORMAT, idx, start_byte, stop_byte);
7820
7821                                         buffered_total += (stop_byte - start_byte);
7822                                 }
7823                         } else
7824                                 stop_per = BUFFERING_MAX_PER;
7825                 }
7826                 gst_query_unref(query);
7827         }
7828
7829         if (stop_per == DEFAULT_PER_VALUE) {
7830                 guint dur_sec = (guint)(content_size_time/GST_SECOND);
7831                 if (dur_sec > 0) {
7832                         guint avg_byterate = (guint)(content_size_bytes/dur_sec);
7833
7834                         /* buffered size info from multiqueue */
7835                         if (mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) {
7836                                 guint curr_size_bytes = 0;
7837                                 g_object_get(G_OBJECT(mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst),
7838                                         "curr-size-bytes", &curr_size_bytes, NULL);
7839                                 LOGD("curr_size_bytes of multiqueue = %d", curr_size_bytes);
7840                                 buffered_total += curr_size_bytes;
7841                         }
7842
7843                         if (avg_byterate > 0)
7844                                 buffered_sec = (gint)(ceil((gdouble)buffered_total/(gdouble)avg_byterate));
7845                         else if (player->total_maximum_bitrate > 0)
7846                                 buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total)/(gdouble)player->total_maximum_bitrate));
7847                         else if (player->total_bitrate > 0)
7848                                 buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total)/(gdouble)player->total_bitrate));
7849
7850                         if (buffered_sec >= 0)
7851                                 stop_per = start_per +(gint)(ceil)(100*(gdouble)buffered_sec/(gdouble)dur_sec);
7852                 }
7853         }
7854
7855         *start_pos = CHECK_PERCENT_VALUE(start_per, 0, 100);
7856         *stop_pos = CHECK_PERCENT_VALUE(stop_per, *start_pos, 100);
7857
7858         LOGD("buffered info: %"G_GINT64_FORMAT" bytes, %d sec, per %lu~%lu\n",
7859                 buffered_total, buffered_sec, *start_pos, *stop_pos);
7860
7861         return MM_ERROR_NONE;
7862 }
7863
7864 static int
7865 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param) // @
7866 {
7867         MMPLAYER_FENTER();
7868
7869         if (!player) {
7870                 LOGW("set_message_callback is called with invalid player handle\n");
7871                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
7872         }
7873
7874         player->msg_cb = callback;
7875         player->msg_cb_param = user_param;
7876
7877         LOGD("msg_cb : %p     msg_cb_param : %p\n", callback, user_param);
7878
7879         MMPLAYER_FLEAVE();
7880
7881         return MM_ERROR_NONE;
7882 }
7883
7884 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
7885 {
7886         int ret = MM_ERROR_PLAYER_INVALID_URI;
7887         char *path = NULL;
7888
7889         MMPLAYER_FENTER();
7890
7891         MMPLAYER_RETURN_VAL_IF_FAIL(uri , FALSE);
7892         MMPLAYER_RETURN_VAL_IF_FAIL(data , FALSE);
7893         MMPLAYER_RETURN_VAL_IF_FAIL((strlen(uri) <= MM_MAX_URL_LEN), FALSE);
7894
7895         memset(data, 0, sizeof(MMPlayerParseProfile));
7896
7897         if ((path = strstr(uri, "es_buff://"))) {
7898                 if (strlen(path)) {
7899                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7900                         data->uri_type = MM_PLAYER_URI_TYPE_MS_BUFF;
7901                         ret = MM_ERROR_NONE;
7902                 }
7903         } else if ((path = strstr(uri, "rtsp://"))) {
7904                 if (strlen(path)) {
7905                         if ((path = strstr(uri, "/wfd1.0/"))) {
7906                                 strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7907                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_WFD;
7908                                 ret = MM_ERROR_NONE;
7909                                 LOGD("uri is actually a wfd client path. giving it to wfdrtspsrc\n");
7910                         } else {
7911                                 strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7912                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7913                                 ret = MM_ERROR_NONE;
7914                         }
7915                 }
7916         } else if ((path = strstr(uri, "http://"))) {
7917                 if (strlen(path)) {
7918                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7919
7920                         if (g_str_has_suffix(g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
7921                                 g_str_has_suffix(g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
7922                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
7923                         else
7924                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
7925
7926                         ret = MM_ERROR_NONE;
7927                 }
7928         } else if ((path = strstr(uri, "https://"))) {
7929                 if (strlen(path)) {
7930                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7931
7932                 if (g_str_has_suffix(g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
7933                                 g_str_has_suffix(g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
7934                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
7935
7936                         data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
7937
7938                         ret = MM_ERROR_NONE;
7939                 }
7940         } else if ((path = strstr(uri, "rtspu://"))) {
7941                 if (strlen(path)) {
7942                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7943                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7944                         ret = MM_ERROR_NONE;
7945                 }
7946         } else if ((path = strstr(uri, "rtspr://"))) {
7947                 strncpy(data->uri, path, MM_MAX_URL_LEN-1);
7948                 char *separater = strstr(path, "*");
7949
7950                 if (separater) {
7951                         int urgent_len = 0;
7952                         char *urgent = separater + strlen("*");
7953
7954                         if ((urgent_len = strlen(urgent))) {
7955                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
7956                                 strncpy(data->urgent, urgent, MM_MAX_FILENAME_LEN-1);
7957                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7958                                 ret = MM_ERROR_NONE;
7959                         }
7960                 }
7961         } else if ((path = strstr(uri, "mms://"))) {
7962                 if (strlen(path)) {
7963                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7964                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
7965                         ret = MM_ERROR_NONE;
7966                 }
7967         } else if ((path = strstr(uri, "mem://"))) {
7968                 if (strlen(path)) {
7969                         int mem_size = 0;
7970                         char *buffer = NULL;
7971                         char *seperator = strchr(path, ',');
7972                         char ext[100] = {0,}, size[100] = {0,};
7973
7974                         if (seperator) {
7975                                 if ((buffer = strstr(path, "ext="))) {
7976                                         buffer += strlen("ext=");
7977
7978                                         if (strlen(buffer)) {
7979                                                 strncpy(ext, buffer, 99);
7980
7981                                                 if ((seperator = strchr(ext, ','))
7982                                                         || (seperator = strchr(ext, ' '))
7983                                                         || (seperator = strchr(ext, '\0'))) {
7984                                                         seperator[0] = '\0';
7985                                                 }
7986                                         }
7987                                 }
7988
7989                                 if ((buffer = strstr(path, "size="))) {
7990                                         buffer += strlen("size=");
7991
7992                                         if (strlen(buffer) > 0) {
7993                                                 strncpy(size, buffer, 99);
7994
7995                                                 if ((seperator = strchr(size, ','))
7996                                                         || (seperator = strchr(size, ' '))
7997                                                         || (seperator = strchr(size, '\0'))) {
7998                                                         seperator[0] = '\0';
7999                                                 }
8000
8001                                                 mem_size = atoi(size);
8002                                         }
8003                                 }
8004                         }
8005
8006                         LOGD("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
8007                         if (mem_size && param) {
8008                                 data->mem = param;
8009                                 data->mem_size = mem_size;
8010                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
8011                                 ret = MM_ERROR_NONE;
8012                         }
8013                 }
8014         } else {
8015                 gchar *location = NULL;
8016                 GError *err = NULL;
8017
8018                 if ((path = strstr(uri, "file://"))) {
8019
8020                         location = g_filename_from_uri(uri, NULL, &err);
8021
8022                         if (!location || (err != NULL)) {
8023                           LOGE("Invalid URI '%s' for filesrc: %s", path,
8024                                  (err != NULL) ? err->message : "unknown error");
8025
8026                           if (err) g_error_free(err);
8027                           if (location) g_free(location);
8028
8029                           data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8030                           goto exit;
8031                         }
8032
8033                         LOGD("path from uri: %s", location);
8034                 }
8035
8036                 path = (location != NULL) ? (location) : ((char*)uri);
8037                 int file_stat = MM_ERROR_NONE;
8038
8039                 file_stat = util_exist_file_path(path);
8040
8041                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
8042                 if (file_stat == MM_ERROR_NONE) {
8043                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", path);
8044
8045                         if (util_is_sdp_file(path)) {
8046                                 LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8047                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8048                         } else {
8049                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8050                         }
8051                         ret = MM_ERROR_NONE;
8052                 } else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED) {
8053                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8054                 } else {
8055                         LOGE("invalid uri, could not play..\n");
8056                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8057                 }
8058
8059                 if (location) g_free(location);
8060         }
8061
8062 exit:
8063         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE)
8064                 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
8065         else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION)
8066                 ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
8067
8068         /* dump parse result */
8069         SECURE_LOGW("incomming uri : %s\n", uri);
8070         LOGD("uri_type : %d, mem : %p, mem_size : %d, urgent : %s\n",
8071                 data->uri_type, data->mem, data->mem_size, data->urgent);
8072
8073         MMPLAYER_FLEAVE();
8074
8075         return ret;
8076 }
8077
8078 gboolean _asm_postmsg(gpointer *data)
8079 {
8080         mm_player_t* player = (mm_player_t*)data;
8081         MMMessageParamType msg = {0, };
8082
8083         MMPLAYER_FENTER();
8084         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
8085         LOGW("get notified");
8086
8087         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
8088                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE)) {
8089                 LOGW("dispatched");
8090                 return FALSE;
8091         }
8092
8093
8094         msg.union_type = MM_MSG_UNION_CODE;
8095         msg.code = player->sound_focus.focus_changed_msg;
8096
8097         MMPLAYER_POST_MSG(player, MM_MESSAGE_READY_TO_RESUME, &msg);
8098         player->resume_event_id = 0;
8099
8100         LOGW("dispatched");
8101         return FALSE;
8102 }
8103
8104 gboolean _asm_lazy_pause(gpointer *data)
8105 {
8106         mm_player_t* player = (mm_player_t*)data;
8107         int ret = MM_ERROR_NONE;
8108
8109         MMPLAYER_FENTER();
8110
8111         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
8112
8113         if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING) {
8114                 LOGD("Ready to proceed lazy pause\n");
8115                 ret = _mmplayer_pause((MMHandleType)player);
8116                 if (MM_ERROR_NONE != ret)
8117                         LOGE("MMPlayer pause failed in ASM callback lazy pause\n");
8118         } else
8119                 LOGD("Invalid state to proceed lazy pause\n");
8120
8121         /* unset mute */
8122         if (player->pipeline && player->pipeline->audiobin)
8123                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
8124
8125         player->sound_focus.by_asm_cb = FALSE; //should be reset here
8126
8127         MMPLAYER_FLEAVE();
8128
8129         return FALSE;
8130 }
8131
8132 gboolean
8133 __mmplayer_can_do_interrupt(mm_player_t *player)
8134 {
8135         if (!player || !player->pipeline || !player->attrs) {
8136                 LOGW("not initialized");
8137                 goto FAILED;
8138         }
8139
8140         if ((player->sound_focus.exit_cb) || (player->set_mode.pcm_extraction)) {
8141                 LOGW("leave from asm cb right now, %d, %d", player->sound_focus.exit_cb, player->set_mode.pcm_extraction);
8142                 goto FAILED;
8143         }
8144
8145         /* check if seeking */
8146         if (player->doing_seek) {
8147                 MMMessageParamType msg_param;
8148                 memset(&msg_param, 0, sizeof(MMMessageParamType));
8149                 msg_param.code = MM_ERROR_PLAYER_SEEK;
8150                 player->doing_seek = FALSE;
8151                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
8152                 goto FAILED;
8153         }
8154
8155         /* check other thread */
8156         if (!MMPLAYER_CMD_TRYLOCK(player)) {
8157                 LOGW("locked already, cmd state : %d", player->cmd);
8158
8159                 /* check application command */
8160                 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) {
8161                         LOGW("playing.. should wait cmd lock then, will be interrupted");
8162
8163                         /* lock will be released at mrp_resource_release_cb() */
8164                         MMPLAYER_CMD_LOCK(player);
8165                         goto INTERRUPT;
8166                 }
8167                 LOGW("nothing to do");
8168                 goto FAILED;
8169         } else {
8170                 LOGW("can interrupt immediately");
8171                 goto INTERRUPT;
8172         }
8173
8174 FAILED:    /* with CMD UNLOCKED */
8175         return FALSE;
8176
8177 INTERRUPT: /* with CMD LOCKED, released at mrp_resource_release_cb() */
8178         return TRUE;
8179 }
8180
8181 /* if you want to enable USE_ASM, please check the history get the ASM cb code. */
8182 static int
8183 __mmplayer_convert_sound_focus_state(gboolean acquire, const char *reason_for_change, MMPlayerFocusChangedMsg *msg)
8184 {
8185         int ret = MM_ERROR_NONE;
8186         MMPlayerFocusChangedMsg focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
8187
8188         if (strstr(reason_for_change, "alarm")) {
8189                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_ALARM;
8190
8191         } else if (strstr(reason_for_change, "notification")) {
8192                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_NOTIFICATION;
8193
8194         } else if (strstr(reason_for_change, "emergency")) {
8195                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_EMERGENCY;
8196
8197         } else if (strstr(reason_for_change, "call-voice") ||
8198                                 strstr(reason_for_change, "call-video") ||
8199                                 strstr(reason_for_change, "voip") ||
8200                                 strstr(reason_for_change, "ringtone-voip") ||
8201                                 strstr(reason_for_change, "ringtone-call")) {
8202                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_CALL;
8203
8204         } else if (strstr(reason_for_change, "media") ||
8205                                 strstr(reason_for_change, "radio") ||
8206                                 strstr(reason_for_change, "loopback") ||
8207                                 strstr(reason_for_change, "system") ||
8208                                 strstr(reason_for_change, "voice-information") ||
8209                                 strstr(reason_for_change, "voice-recognition")) {
8210                 focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_MEDIA;
8211
8212         } else {
8213                 ret = MM_ERROR_INVALID_ARGUMENT;
8214                 LOGW("not supported reason(%s), err(0x%08x)", reason_for_change, ret);
8215                 goto DONE;
8216         }
8217
8218         if (acquire && (focus_msg != MM_PLAYER_FOCUS_CHANGED_BY_MEDIA))
8219                 /* can acqurie */
8220                 focus_msg = MM_PLAYER_FOCUS_CHANGED_COMPLETED;
8221
8222         LOGD("converted from reason(%s) to msg(%d)", reason_for_change, focus_msg);
8223         *msg = focus_msg;
8224
8225 DONE:
8226         return ret;
8227 }
8228
8229 /* FIXME: will be updated with new funct */
8230 void __mmplayer_sound_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
8231                                        const char *reason_for_change, const char *additional_info, void *user_data)
8232 {
8233         mm_player_t* player = (mm_player_t*) user_data;
8234         int result = MM_ERROR_NONE;
8235         MMPlayerFocusChangedMsg msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
8236
8237         LOGW("focus watch notified");
8238
8239         if (!__mmplayer_can_do_interrupt(player)) {
8240                 LOGW("no need to interrupt, so leave");
8241                 goto EXIT_WITHOUT_UNLOCK;
8242         }
8243
8244         if (player->sound_focus.session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
8245                 LOGW("flags is UNINTERRUPTIBLE. do nothing.");
8246                 goto EXIT;
8247         }
8248
8249         LOGW("watch: state: %d, focus_type : %d, reason_for_change : %s",
8250                 focus_state, focus_type, (reason_for_change ? reason_for_change : "N/A"));
8251
8252         player->sound_focus.cb_pending = TRUE;
8253         player->sound_focus.by_asm_cb = TRUE;
8254
8255         if (focus_state == FOCUS_IS_ACQUIRED) {
8256                 LOGW("watch: FOCUS_IS_ACQUIRED");
8257                 player->sound_focus.acquired = TRUE;
8258
8259                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(FALSE, reason_for_change, &msg))
8260                         player->sound_focus.focus_changed_msg = (int)msg;
8261
8262                 if (strstr(reason_for_change, "call") ||
8263                         strstr(reason_for_change, "voip") ||    /* FIXME: to check */
8264                         strstr(reason_for_change, "alarm") ||
8265                         strstr(reason_for_change, "media")) {
8266                         if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
8267                                 // hold 0.7 second to excute "fadedown mute" effect
8268                                 LOGW("do fade down->pause->undo fade down");
8269
8270                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8271
8272                                 result = _mmplayer_pause((MMHandleType)player);
8273                                 if (result != MM_ERROR_NONE) {
8274                                         LOGW("fail to set Pause state by asm");
8275                                         goto EXIT;
8276                                 }
8277                                 __mmplayer_undo_sound_fadedown(player);
8278                         } else
8279                                 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
8280                                 _mmplayer_unrealize((MMHandleType)player);
8281                 } else {
8282                         LOGW("pause immediately");
8283                         result = _mmplayer_pause((MMHandleType)player);
8284                         if (result != MM_ERROR_NONE) {
8285                                 LOGW("fail to set Pause state by asm");
8286                                 goto EXIT;
8287                         }
8288                 }
8289         } else if (focus_state == FOCUS_IS_RELEASED) {
8290                 LOGW("FOCUS_IS_RELEASED: Got msg from asm to resume");
8291                 player->sound_focus.acquired = FALSE;
8292                 player->sound_focus.antishock = TRUE;
8293                 player->sound_focus.by_asm_cb = FALSE;
8294
8295                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(TRUE, reason_for_change, &msg))
8296                         player->sound_focus.focus_changed_msg = (int)msg;
8297
8298                 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
8299                 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
8300                 goto DONE;
8301         } else
8302                 LOGW("unknown focus state %d", focus_state);
8303
8304 DONE:
8305         player->sound_focus.by_asm_cb = FALSE;
8306         player->sound_focus.cb_pending = FALSE;
8307
8308 EXIT:
8309         MMPLAYER_CMD_UNLOCK(player);
8310         LOGW("dispatched");
8311         return;
8312
8313 EXIT_WITHOUT_UNLOCK:
8314         LOGW("dispatched");
8315         return;
8316 }
8317
8318 void
8319 __mmplayer_sound_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
8320         const char *reason_for_change, int option, const char *additional_info, void *user_data)
8321 {
8322         mm_player_t* player = (mm_player_t*) user_data;
8323         int result = MM_ERROR_NONE;
8324         MMPlayerFocusChangedMsg msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
8325
8326         LOGW("get focus notified");
8327
8328         if (!__mmplayer_can_do_interrupt(player)) {
8329                 LOGW("no need to interrupt, so leave");
8330                 goto EXIT_WITHOUT_UNLOCK;
8331         }
8332
8333         if (player->sound_focus.session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
8334                 LOGW("flags is UNINTERRUPTIBLE. do nothing.");
8335                 goto EXIT;
8336         }
8337
8338         LOGW("state: %d, focus_type : %d, reason_for_change : %s",
8339                 focus_state, focus_type, (reason_for_change ? reason_for_change : "N/A"));
8340
8341         player->sound_focus.cb_pending = TRUE;
8342         player->sound_focus.by_asm_cb = TRUE;
8343 //      player->sound_focus.event_src = event_src;
8344
8345         if (focus_state == FOCUS_IS_RELEASED) {
8346                 LOGW("FOCUS_IS_RELEASED");
8347                 player->sound_focus.acquired = FALSE;
8348
8349                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(FALSE, reason_for_change, &msg))
8350                         player->sound_focus.focus_changed_msg = (int)msg;
8351
8352                 if (strstr(reason_for_change, "call") ||
8353                         strstr(reason_for_change, "voip") ||    /* FIXME: to check */
8354                         strstr(reason_for_change, "alarm") ||
8355                         strstr(reason_for_change, "media")) {
8356                         if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
8357                                 //hold 0.7 second to excute "fadedown mute" effect
8358                                 LOGW("do fade down->pause->undo fade down");
8359
8360                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8361
8362                                 result = _mmplayer_pause((MMHandleType)player);
8363                                 if (result != MM_ERROR_NONE) {
8364                                         LOGW("fail to set Pause state by asm");
8365                                         goto EXIT;
8366                                 }
8367                                 __mmplayer_undo_sound_fadedown(player);
8368                         } else
8369                                 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
8370                                 _mmplayer_unrealize((MMHandleType)player);
8371                 } else {
8372                         LOGW("pause immediately");
8373                         result = _mmplayer_pause((MMHandleType)player);
8374                         if (result != MM_ERROR_NONE) {
8375                                 LOGW("fail to set Pause state by asm");
8376                                 goto EXIT;
8377                         }
8378                 }
8379         } else if (focus_state == FOCUS_IS_ACQUIRED) {
8380                 LOGW("FOCUS_IS_ACQUIRED: Got msg from asm to resume");
8381                 player->sound_focus.antishock = TRUE;
8382                 player->sound_focus.by_asm_cb = FALSE;
8383
8384                 if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(TRUE, reason_for_change, &msg))
8385                         player->sound_focus.focus_changed_msg = (int)msg;
8386
8387                 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
8388                 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
8389                 goto DONE;
8390         } else
8391                 LOGW("unknown focus state %d", focus_state);
8392
8393 DONE:
8394         player->sound_focus.by_asm_cb = FALSE;
8395         player->sound_focus.cb_pending = FALSE;
8396
8397 EXIT:
8398         if (mm_sound_update_focus_status(id, 0))
8399                 LOGE("failed to update focus status\n");
8400         MMPLAYER_CMD_UNLOCK(player);
8401         LOGW("dispatched");
8402         return;
8403
8404 EXIT_WITHOUT_UNLOCK:
8405         LOGW("dispatched");
8406         return;
8407 }
8408
8409
8410 int
8411 _mmplayer_create_player(MMHandleType handle) // @
8412 {
8413         int ret = MM_ERROR_PLAYER_INTERNAL;
8414         mm_player_t* player = MM_PLAYER_CAST(handle);
8415
8416         MMPLAYER_FENTER();
8417
8418         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8419
8420         /* initialize player state */
8421         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
8422         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
8423         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
8424         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
8425
8426         /* check current state */
8427         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_CREATE);
8428
8429         /* construct attributes */
8430         player->attrs = _mmplayer_construct_attribute(handle);
8431
8432         if (!player->attrs) {
8433                 LOGE("Failed to construct attributes\n");
8434                 return ret;
8435         }
8436
8437         /* initialize gstreamer with configured parameter */
8438         if (!__mmplayer_init_gstreamer(player)) {
8439                 LOGE("Initializing gstreamer failed\n");
8440                 _mmplayer_deconstruct_attribute(handle);
8441                 return ret;
8442         }
8443
8444         /* initialize factories if not using decodebin */
8445         if (player->factories == NULL)
8446                 __mmplayer_init_factories(player);
8447
8448         /* create lock. note that g_tread_init() has already called in gst_init() */
8449         g_mutex_init(&player->fsink_lock);
8450
8451         /* create update tag lock */
8452         g_mutex_init(&player->update_tag_lock);
8453
8454         /* create repeat mutex */
8455         g_mutex_init(&player->repeat_thread_mutex);
8456
8457         /* create repeat cond */
8458         g_cond_init(&player->repeat_thread_cond);
8459
8460         /* create repeat thread */
8461         player->repeat_thread =
8462                 g_thread_try_new("repeat_thread", __mmplayer_repeat_thread, (gpointer)player, NULL);
8463         if (!player->repeat_thread) {
8464                 LOGE("failed to create repeat_thread(%s)");
8465                 g_mutex_clear(&player->repeat_thread_mutex);
8466                 g_cond_clear(&player->repeat_thread_cond);
8467                 ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
8468                 goto ERROR;
8469         }
8470
8471         /* create next play mutex */
8472         g_mutex_init(&player->next_play_thread_mutex);
8473
8474         /* create next play cond */
8475         g_cond_init(&player->next_play_thread_cond);
8476
8477         /* create next play thread */
8478         player->next_play_thread =
8479                 g_thread_try_new("next_play_thread", __mmplayer_next_play_thread, (gpointer)player, NULL);
8480         if (!player->next_play_thread) {
8481                 LOGE("failed to create next play thread");
8482                 ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
8483                 g_mutex_clear(&player->next_play_thread_mutex);
8484                 g_cond_clear(&player->next_play_thread_cond);
8485                 goto ERROR;
8486         }
8487
8488         ret = _mmplayer_initialize_video_capture(player);
8489         if (ret != MM_ERROR_NONE) {
8490                 LOGE("failed to initialize video capture\n");
8491                 goto ERROR;
8492         }
8493
8494         /* initialize resource manager */
8495         if (MM_ERROR_NONE != _mmplayer_resource_manager_init(&player->resource_manager, player)) {
8496                 LOGE("failed to initialize resource manager\n");
8497                 goto ERROR;
8498         }
8499
8500         if (MMPLAYER_IS_HTTP_PD(player)) {
8501                 player->pd_downloader = NULL;
8502                 player->pd_file_save_path = NULL;
8503         }
8504
8505         /* create video bo lock and cond */
8506         g_mutex_init(&player->video_bo_mutex);
8507         g_cond_init(&player->video_bo_cond);
8508
8509         /* create media stream callback mutex */
8510         g_mutex_init(&player->media_stream_cb_lock);
8511
8512         player->streaming_type = STREAMING_SERVICE_NONE;
8513
8514         /* give default value of audio effect setting */
8515         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
8516         player->playback_rate = DEFAULT_PLAYBACK_RATE;
8517
8518         player->play_subtitle = FALSE;
8519         player->use_textoverlay = FALSE;
8520         player->play_count = 0;
8521         player->use_decodebin = TRUE;
8522         player->ignore_asyncdone = FALSE;
8523         player->use_deinterleave = FALSE;
8524         player->max_audio_channels = 0;
8525         player->video_share_api_delta = 0;
8526         player->video_share_clock_delta = 0;
8527         player->has_closed_caption = FALSE;
8528         player->video_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
8529         player->video_extra_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
8530         player->pending_resume = FALSE;
8531         if (player->ini.dump_element_keyword[0][0] == '\0')
8532                 player->ini.set_dump_element_flag = FALSE;
8533         else
8534                 player->ini.set_dump_element_flag = TRUE;
8535
8536         /* set player state to null */
8537         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
8538         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
8539
8540         return MM_ERROR_NONE;
8541
8542 ERROR:
8543         /* free lock */
8544         g_mutex_clear(&player->fsink_lock);
8545
8546         /* free update tag lock */
8547         g_mutex_clear(&player->update_tag_lock);
8548
8549         /* free thread */
8550         if (player->repeat_thread) {
8551                 player->repeat_thread_exit = TRUE;
8552                 MMPLAYER_REPEAT_THREAD_SIGNAL(player);
8553
8554                 g_thread_join(player->repeat_thread);
8555                 player->repeat_thread = NULL;
8556
8557                 g_mutex_clear(&player->repeat_thread_mutex);
8558                 g_cond_clear(&player->repeat_thread_cond);
8559         }
8560
8561         /* free next play thread */
8562         if (player->next_play_thread) {
8563                 player->next_play_thread_exit = TRUE;
8564                 MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
8565
8566                 g_thread_join(player->next_play_thread);
8567                 player->next_play_thread = NULL;
8568
8569                 g_mutex_clear(&player->next_play_thread_mutex);
8570                 g_cond_clear(&player->next_play_thread_cond);
8571         }
8572
8573         /* release attributes */
8574         _mmplayer_deconstruct_attribute(handle);
8575
8576         MMPLAYER_FLEAVE();
8577
8578         return ret;
8579 }
8580
8581 static gboolean
8582 __mmplayer_init_gstreamer(mm_player_t* player) // @
8583 {
8584         static gboolean initialized = FALSE;
8585         static const int max_argc = 50;
8586         gint* argc = NULL;
8587         gchar** argv = NULL;
8588         gchar** argv2 = NULL;
8589         GError *err = NULL;
8590         int i = 0;
8591         int arg_count = 0;
8592
8593         if (initialized) {
8594                 LOGD("gstreamer already initialized.\n");
8595                 return TRUE;
8596         }
8597
8598         /* alloc */
8599         argc = malloc(sizeof(int));
8600         argv = malloc(sizeof(gchar*) * max_argc);
8601         argv2 = malloc(sizeof(gchar*) * max_argc);
8602
8603         if (!argc || !argv || !argv2)
8604                 goto ERROR;
8605
8606         memset(argv, 0, sizeof(gchar*) * max_argc);
8607         memset(argv2, 0, sizeof(gchar*) * max_argc);
8608
8609         /* add initial */
8610         *argc = 1;
8611         argv[0] = g_strdup("mmplayer");
8612
8613         /* add gst_param */
8614         for (i = 0; i < 5; i++) {
8615                 /* FIXIT : num of param is now fixed to 5. make it dynamic */
8616                 if (strlen(player->ini.gst_param[i]) > 0) {
8617                         argv[*argc] = g_strdup(player->ini.gst_param[i]);
8618                         (*argc)++;
8619                 }
8620         }
8621
8622         /* we would not do fork for scanning plugins */
8623         argv[*argc] = g_strdup("--gst-disable-registry-fork");
8624         (*argc)++;
8625
8626         /* check disable registry scan */
8627         if (player->ini.skip_rescan) {
8628                 argv[*argc] = g_strdup("--gst-disable-registry-update");
8629                 (*argc)++;
8630         }
8631
8632         /* check disable segtrap */
8633         if (player->ini.disable_segtrap) {
8634                 argv[*argc] = g_strdup("--gst-disable-segtrap");
8635                 (*argc)++;
8636         }
8637
8638         LOGD("initializing gstreamer with following parameter\n");
8639         LOGD("argc : %d\n", *argc);
8640         arg_count = *argc;
8641
8642         for (i = 0; i < arg_count; i++) {
8643                 argv2[i] = argv[i];
8644                 LOGD("argv[%d] : %s\n", i, argv2[i]);
8645         }
8646
8647
8648         /* initializing gstreamer */
8649         if (!gst_init_check(argc, &argv, &err)) {
8650                 LOGE("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
8651                 if (err)
8652                         g_error_free(err);
8653
8654                 goto ERROR;
8655         }
8656         /* release */
8657         for (i = 0; i < arg_count; i++) {
8658                 //LOGD("release - argv[%d] : %s\n", i, argv2[i]);
8659                 MMPLAYER_FREEIF(argv2[i]);
8660         }
8661
8662         MMPLAYER_FREEIF(argv);
8663         MMPLAYER_FREEIF(argv2);
8664         MMPLAYER_FREEIF(argc);
8665
8666         /* done */
8667         initialized = TRUE;
8668
8669         return TRUE;
8670
8671 ERROR:
8672
8673         /* release */
8674         for (i = 0; i < arg_count; i++) {
8675                 LOGD("free[%d] : %s\n", i, argv2[i]);
8676                 MMPLAYER_FREEIF(argv2[i]);
8677         }
8678
8679         MMPLAYER_FREEIF(argv);
8680         MMPLAYER_FREEIF(argv2);
8681         MMPLAYER_FREEIF(argc);
8682
8683         return FALSE;
8684 }
8685
8686 int
8687 __mmplayer_destroy_streaming_ext(mm_player_t* player)
8688 {
8689         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8690
8691         if (player->pd_downloader) {
8692                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
8693                 MMPLAYER_FREEIF(player->pd_downloader);
8694         }
8695
8696         if (MMPLAYER_IS_HTTP_PD(player)) {
8697                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
8698                 MMPLAYER_FREEIF(player->pd_file_save_path);
8699         }
8700
8701         return MM_ERROR_NONE;
8702 }
8703
8704 static void
8705 __mmplayer_check_async_state_transition(mm_player_t* player)
8706 {
8707         GstState element_state = GST_STATE_VOID_PENDING;
8708         GstState element_pending_state = GST_STATE_VOID_PENDING;
8709         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
8710         GstElement * element = NULL;
8711         gboolean async = FALSE;
8712
8713         /* check player handle */
8714         MMPLAYER_RETURN_IF_FAIL(player &&
8715                                                 player->pipeline &&
8716                                                 player->pipeline->mainbin &&
8717                                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
8718
8719         if (player->attrs)
8720                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
8721
8722         if (!MMPLAYER_IS_MS_BUFF_SRC(player) && (async == FALSE)) {
8723                 LOGD("don't need to check the pipeline state");
8724                 return;
8725         }
8726
8727         MMPLAYER_PRINT_STATE(player);
8728
8729         /* wait for state transition */
8730         element = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
8731         ret = gst_element_get_state(element, &element_state, &element_pending_state, 1*GST_SECOND);
8732
8733         if (ret == GST_STATE_CHANGE_FAILURE) {
8734                 LOGE(" [%s] state : %s   pending : %s \n",
8735                         GST_ELEMENT_NAME(element),
8736                         gst_element_state_get_name(element_state),
8737                         gst_element_state_get_name(element_pending_state));
8738
8739                 /* dump state of all element */
8740                 __mmplayer_dump_pipeline_state(player);
8741
8742                 return;
8743         }
8744
8745         LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
8746         return;
8747 }
8748
8749 int
8750 _mmplayer_destroy(MMHandleType handle) // @
8751 {
8752         mm_player_t* player = MM_PLAYER_CAST(handle);
8753
8754         MMPLAYER_FENTER();
8755
8756         /* check player handle */
8757         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8758
8759         /* destroy can called at anytime */
8760         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_DESTROY);
8761
8762         /* check async state transition */
8763         __mmplayer_check_async_state_transition(player);
8764
8765         __mmplayer_destroy_streaming_ext(player);
8766
8767         /* release repeat thread */
8768         if (player->repeat_thread) {
8769                 player->repeat_thread_exit = TRUE;
8770                 MMPLAYER_REPEAT_THREAD_SIGNAL(player);
8771
8772                 LOGD("waitting for repeat thread exit\n");
8773                 g_thread_join(player->repeat_thread);
8774                 g_mutex_clear(&player->repeat_thread_mutex);
8775                 g_cond_clear(&player->repeat_thread_cond);
8776                 LOGD("repeat thread released\n");
8777         }
8778
8779         /* release next play thread */
8780         if (player->next_play_thread) {
8781                 player->next_play_thread_exit = TRUE;
8782                 MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
8783
8784                 LOGD("waitting for next play thread exit\n");
8785                 g_thread_join(player->next_play_thread);
8786                 g_mutex_clear(&player->next_play_thread_mutex);
8787                 g_cond_clear(&player->next_play_thread_cond);
8788                 LOGD("next play thread released\n");
8789         }
8790
8791         _mmplayer_release_video_capture(player);
8792
8793         /* flush any pending asm_cb */
8794         if (player->sound_focus.cb_pending) {
8795                 /* set a flag for make sure asm_cb to be returned immediately */
8796                 LOGW("asm cb has pending state");
8797                 player->sound_focus.exit_cb = TRUE;
8798
8799                 /* make sure to release any pending asm_cb which locked by cmd_lock */
8800                 MMPLAYER_CMD_UNLOCK(player);
8801                 sched_yield();
8802                 MMPLAYER_CMD_LOCK(player);
8803         }
8804
8805         /* withdraw asm */
8806         if (MM_ERROR_NONE != _mmplayer_sound_unregister(&player->sound_focus))
8807                 LOGE("failed to deregister asm server\n");
8808
8809         /* de-initialize resource manager */
8810         if (MM_ERROR_NONE != _mmplayer_resource_manager_deinit(&player->resource_manager))
8811                 LOGE("failed to deinitialize resource manager\n");
8812
8813 #ifdef USE_LAZY_PAUSE
8814         if (player->lazy_pause_event_id) {
8815                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->lazy_pause_event_id);
8816                 player->lazy_pause_event_id = 0;
8817         }
8818 #endif
8819
8820         if (player->resume_event_id) {
8821                 g_source_remove(player->resume_event_id);
8822                 player->resume_event_id = 0;
8823         }
8824
8825         if (player->resumable_cancel_id) {
8826                 g_source_remove(player->resumable_cancel_id);
8827                 player->resumable_cancel_id = 0;
8828         }
8829
8830         /* release pipeline */
8831         if (MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline(player)) {
8832                 LOGE("failed to destory pipeline\n");
8833                 return MM_ERROR_PLAYER_INTERNAL;
8834         }
8835
8836         if (player->is_external_subtitle_present && player->subtitle_language_list) {
8837           g_list_free(player->subtitle_language_list);
8838           player->subtitle_language_list = NULL;
8839         }
8840
8841         __mmplayer_release_dump_list(player->dump_list);
8842
8843         /* release miscellaneous information.
8844            these info needs to be released after pipeline is destroyed. */
8845         __mmplayer_release_misc_post(player);
8846
8847         /* release attributes */
8848         _mmplayer_deconstruct_attribute(handle);
8849
8850         /* release factories */
8851         __mmplayer_release_factories(player);
8852
8853         /* release lock */
8854         g_mutex_clear(&player->fsink_lock);
8855
8856         /* release lock */
8857         g_mutex_clear(&player->update_tag_lock);
8858
8859         /* release video bo lock and cond */
8860         g_mutex_clear(&player->video_bo_mutex);
8861         g_cond_clear(&player->video_bo_cond);
8862
8863         /* release media stream callback lock */
8864         g_mutex_clear(&player->media_stream_cb_lock);
8865
8866         MMPLAYER_FLEAVE();
8867
8868         return MM_ERROR_NONE;
8869 }
8870
8871 int
8872 __mmplayer_realize_streaming_ext(mm_player_t* player)
8873 {
8874         int ret = MM_ERROR_NONE;
8875
8876         MMPLAYER_FENTER();
8877         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8878
8879         if (MMPLAYER_IS_HTTP_PD(player)) {
8880                 gboolean bret = FALSE;
8881
8882                 player->pd_downloader = _mmplayer_create_pd_downloader();
8883                 if (!player->pd_downloader) {
8884                         LOGE("Unable to create PD Downloader...");
8885                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
8886                 }
8887
8888                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
8889
8890                 if (FALSE == bret) {
8891                         LOGE("Unable to create PD Downloader...");
8892                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
8893                 }
8894         }
8895
8896         MMPLAYER_FLEAVE();
8897         return ret;
8898 }
8899
8900 int
8901 _mmplayer_sound_register_with_pid(MMHandleType hplayer, int pid) // @
8902 {
8903         mm_player_t* player = (mm_player_t*)hplayer;
8904         MMHandleType attrs = 0;
8905         int ret = MM_ERROR_NONE;
8906
8907         attrs = MMPLAYER_GET_ATTRS(player);
8908         if (!attrs) {
8909                 LOGE("fail to get attributes.\n");
8910                 return MM_ERROR_PLAYER_INTERNAL;
8911         }
8912
8913         player->sound_focus.pid = pid;
8914
8915         /* register to asm */
8916         if (MM_ERROR_NONE != _mmplayer_sound_register(&player->sound_focus,
8917                                                 (mm_sound_focus_changed_cb)__mmplayer_sound_focus_callback,
8918                                                 (mm_sound_focus_changed_watch_cb)__mmplayer_sound_focus_watch_callback,
8919                                                 (void*)player)) {
8920                 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
8921                 LOGE("failed to register asm server\n");
8922                 return MM_ERROR_POLICY_INTERNAL;
8923         }
8924         return ret;
8925 }
8926
8927 int
8928 _mmplayer_get_client_pid(MMHandleType hplayer, int* pid)
8929 {
8930         mm_player_t* player = (mm_player_t*) hplayer;
8931
8932         MMPLAYER_FENTER();
8933
8934         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8935
8936         *pid = player->sound_focus.pid;
8937
8938         LOGD("registered pid[%d] %p", *pid, player);
8939
8940         MMPLAYER_FLEAVE();
8941
8942         return MM_ERROR_NONE;
8943 }
8944
8945 int
8946 _mmplayer_realize(MMHandleType hplayer) // @
8947 {
8948         mm_player_t* player = (mm_player_t*)hplayer;
8949         char *uri = NULL;
8950         void *param = NULL;
8951         gboolean update_registry = FALSE;
8952         MMHandleType attrs = 0;
8953         int ret = MM_ERROR_NONE;
8954
8955         MMPLAYER_FENTER();
8956
8957         /* check player handle */
8958         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED)
8959
8960         /* check current state */
8961         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_REALIZE);
8962
8963         attrs = MMPLAYER_GET_ATTRS(player);
8964         if (!attrs) {
8965                 LOGE("fail to get attributes.\n");
8966                 return MM_ERROR_PLAYER_INTERNAL;
8967         }
8968         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
8969         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
8970
8971         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_NONE) {
8972                 ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
8973
8974                 if (ret != MM_ERROR_NONE) {
8975                         LOGE("failed to parse profile\n");
8976                         return ret;
8977                 }
8978         }
8979
8980         /* FIXIT : we can use thouse in player->profile directly */
8981         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM) {
8982                 player->mem_buf.buf = (char *)player->profile.mem;
8983                 player->mem_buf.len = player->profile.mem_size;
8984                 player->mem_buf.offset = 0;
8985         }
8986
8987         if (uri && (strstr(uri, "es_buff://"))) {
8988                 if (strstr(uri, "es_buff://push_mode"))
8989                         player->es_player_push_mode = TRUE;
8990                 else
8991                         player->es_player_push_mode = FALSE;
8992         }
8993
8994         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS) {
8995                 LOGW("mms protocol is not supported format.\n");
8996                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
8997         }
8998
8999         if (MMPLAYER_IS_STREAMING(player))
9000                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
9001         else
9002                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
9003
9004         player->smooth_streaming = FALSE;
9005         player->videodec_linked  = 0;
9006         player->videosink_linked = 0;
9007         player->audiodec_linked  = 0;
9008         player->audiosink_linked = 0;
9009         player->textsink_linked = 0;
9010         player->is_external_subtitle_present = FALSE;
9011         player->is_external_subtitle_added_now = FALSE;
9012         /* set the subtitle ON default */
9013         player->is_subtitle_off = FALSE;
9014
9015         /* registry should be updated for downloadable codec */
9016         mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
9017
9018         if (update_registry) {
9019                 LOGD("updating registry...\n");
9020                 gst_update_registry();
9021
9022                 /* then we have to rebuild factories */
9023                 __mmplayer_release_factories(player);
9024                 __mmplayer_init_factories(player);
9025         }
9026
9027         /* realize pipeline */
9028         ret = __gst_realize(player);
9029         if (ret != MM_ERROR_NONE)
9030                 LOGE("fail to realize the player.\n");
9031         else
9032                 ret = __mmplayer_realize_streaming_ext(player);
9033
9034         MMPLAYER_FLEAVE();
9035
9036         return ret;
9037 }
9038
9039 int
9040 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
9041 {
9042         MMPLAYER_FENTER();
9043         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9044
9045         /* destroy can called at anytime */
9046         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player)) {
9047                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
9048                 MMPLAYER_FREEIF(player->pd_downloader);
9049         }
9050
9051         MMPLAYER_FLEAVE();
9052         return MM_ERROR_NONE;
9053 }
9054
9055 int
9056 _mmplayer_unrealize(MMHandleType hplayer)
9057 {
9058         mm_player_t* player = (mm_player_t*)hplayer;
9059         MMPlayerResourceState resource_state = RESOURCE_STATE_NONE;
9060         int ret = MM_ERROR_NONE;
9061
9062         MMPLAYER_FENTER();
9063
9064         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED)
9065
9066         /* check current state */
9067         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_UNREALIZE);
9068
9069         /* check async state transition */
9070         __mmplayer_check_async_state_transition(player);
9071
9072         __mmplayer_unrealize_streaming_ext(player);
9073
9074         /* unrealize pipeline */
9075         ret = __gst_unrealize(player);
9076
9077         /* set asm stop if success */
9078         if (MM_ERROR_NONE == ret) {
9079                 ret = _mmplayer_sound_release_focus(&player->sound_focus);
9080                 if (ret != MM_ERROR_NONE)
9081                         LOGE("failed to release sound focus, ret(0x%x)\n", ret);
9082
9083                 if (!player->resource_manager.by_rm_cb && /* is being released */
9084                         _mmplayer_resource_manager_get_state(&player->resource_manager, &resource_state) == MM_ERROR_NONE) {
9085                         if (resource_state >= RESOURCE_STATE_ACQUIRED) {
9086                                 ret = _mmplayer_resource_manager_release(&player->resource_manager);
9087                                 if (ret != MM_ERROR_NONE)
9088                                         LOGE("failed to release resource, ret(0x%x)\n", ret);
9089                         }
9090                 }
9091
9092                 if (_mmplayer_resource_manager_get_state(&player->resource_manager, &resource_state) == MM_ERROR_NONE) {
9093                         if (resource_state == RESOURCE_STATE_PREPARED) {
9094                                 ret = _mmplayer_resource_manager_unprepare(&player->resource_manager);
9095                                 if (ret != MM_ERROR_NONE)
9096                                         LOGE("failed to unprepare resource, ret(0x%x)\n", ret);
9097                         }
9098                 }
9099         } else
9100                 LOGE("failed and don't change asm state to stop");
9101
9102         MMPLAYER_FLEAVE();
9103
9104         return ret;
9105 }
9106
9107 int
9108 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
9109 {
9110         mm_player_t* player = (mm_player_t*)hplayer;
9111
9112         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9113
9114         return __gst_set_message_callback(player, callback, user_param);
9115 }
9116
9117 int
9118 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
9119 {
9120         mm_player_t *player = (mm_player_t*)hplayer;
9121
9122         MMPLAYER_RETURN_VAL_IF_FAIL(state, MM_ERROR_INVALID_ARGUMENT);
9123
9124         *state = MMPLAYER_CURRENT_STATE(player);
9125
9126         return MM_ERROR_NONE;
9127 }
9128
9129
9130 int
9131 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
9132 {
9133         mm_player_t* player = (mm_player_t*) hplayer;
9134         GstElement* vol_element = NULL;
9135         int i = 0;
9136
9137         MMPLAYER_FENTER();
9138
9139         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9140
9141         LOGD("volume [L]=%f:[R]=%f\n",
9142                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
9143
9144         /* invalid factor range or not */
9145         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++) {
9146                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
9147                         LOGE("Invalid factor!(valid factor:0~1.0)\n");
9148                         return MM_ERROR_INVALID_ARGUMENT;
9149                 }
9150         }
9151
9152         /* not support to set other value into each channel */
9153         if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
9154                 return MM_ERROR_INVALID_ARGUMENT;
9155
9156         /* Save volume to handle. Currently the first array element will be saved. */
9157         player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
9158
9159         /* check pipeline handle */
9160         if (!player->pipeline || !player->pipeline->audiobin) {
9161                 LOGD("audiobin is not created yet\n");
9162                 LOGD("but, current stored volume will be set when it's created.\n");
9163
9164                 /* NOTE : stored volume will be used in create_audiobin
9165                  * returning MM_ERROR_NONE here makes application to able to
9166                  * set volume at anytime.
9167                  */
9168                 return MM_ERROR_NONE;
9169         }
9170
9171         /* setting volume to volume element */
9172         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
9173
9174         if (vol_element) {
9175                 LOGD("volume is set [%f]\n", player->sound.volume);
9176                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
9177         }
9178
9179         MMPLAYER_FLEAVE();
9180
9181         return MM_ERROR_NONE;
9182 }
9183
9184
9185 int
9186 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
9187 {
9188         mm_player_t* player = (mm_player_t*) hplayer;
9189         int i = 0;
9190
9191         MMPLAYER_FENTER();
9192
9193         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9194         MMPLAYER_RETURN_VAL_IF_FAIL(volume, MM_ERROR_INVALID_ARGUMENT);
9195
9196         /* returning stored volume */
9197         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
9198                 volume->level[i] = player->sound.volume;
9199
9200         MMPLAYER_FLEAVE();
9201
9202         return MM_ERROR_NONE;
9203 }
9204
9205
9206
9207 int
9208 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
9209 {
9210         mm_player_t* player = (mm_player_t*) hplayer;
9211         GstElement* vol_element = NULL;
9212
9213         MMPLAYER_FENTER();
9214
9215         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9216
9217         /* mute value shoud 0 or 1 */
9218         if (mute != 0 && mute != 1) {
9219                 LOGE("bad mute value\n");
9220
9221                 /* FIXIT : definitly, we need _BAD_PARAM error code */
9222                 return MM_ERROR_INVALID_ARGUMENT;
9223         }
9224
9225         player->sound.mute = mute;
9226
9227         /* just hold mute value if pipeline is not ready */
9228         if (!player->pipeline || !player->pipeline->audiobin) {
9229                 LOGD("pipeline is not ready. holding mute value\n");
9230                 return MM_ERROR_NONE;
9231         }
9232
9233         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
9234
9235         /* NOTE : volume will only created when the bt is enabled */
9236         if (vol_element) {
9237                 LOGD("mute : %d\n", mute);
9238                 g_object_set(vol_element, "mute", mute, NULL);
9239         } else
9240                 LOGD("volume elemnet is not created. using volume in audiosink\n");
9241
9242         MMPLAYER_FLEAVE();
9243
9244         return MM_ERROR_NONE;
9245 }
9246
9247 int
9248 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
9249 {
9250         mm_player_t* player = (mm_player_t*) hplayer;
9251
9252         MMPLAYER_FENTER();
9253
9254         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9255         MMPLAYER_RETURN_VAL_IF_FAIL(pmute, MM_ERROR_INVALID_ARGUMENT);
9256
9257         /* just hold mute value if pipeline is not ready */
9258         if (!player->pipeline || !player->pipeline->audiobin) {
9259                 LOGD("pipeline is not ready. returning stored value\n");
9260                 *pmute = player->sound.mute;
9261                 return MM_ERROR_NONE;
9262         }
9263
9264         *pmute = player->sound.mute;
9265
9266         MMPLAYER_FLEAVE();
9267
9268         return MM_ERROR_NONE;
9269 }
9270
9271 int
9272 _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
9273 {
9274         mm_player_t* player = (mm_player_t*) hplayer;
9275
9276         MMPLAYER_FENTER();
9277
9278         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9279
9280         player->video_stream_changed_cb = callback;
9281         player->video_stream_changed_cb_user_param = user_param;
9282         LOGD("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
9283
9284         MMPLAYER_FLEAVE();
9285
9286         return MM_ERROR_NONE;
9287 }
9288
9289 int
9290 _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
9291 {
9292         mm_player_t* player = (mm_player_t*) hplayer;
9293
9294         MMPLAYER_FENTER();
9295
9296         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9297
9298         player->audio_stream_changed_cb = callback;
9299         player->audio_stream_changed_cb_user_param = user_param;
9300         LOGD("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
9301
9302         MMPLAYER_FLEAVE();
9303
9304         return MM_ERROR_NONE;
9305 }
9306
9307 int
9308 _mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param) // @
9309 {
9310         mm_player_t* player = (mm_player_t*) hplayer;
9311
9312         MMPLAYER_FENTER();
9313
9314         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9315
9316         player->audio_stream_render_cb_ex = callback;
9317         player->audio_stream_cb_user_param = user_param;
9318         player->audio_stream_sink_sync = sync;
9319         LOGD("Audio Stream cb Handle value is %p : %p audio_stream_sink_sync : %d\n", player, player->audio_stream_render_cb_ex, player->audio_stream_sink_sync);
9320
9321         MMPLAYER_FLEAVE();
9322
9323         return MM_ERROR_NONE;
9324 }
9325
9326 int
9327 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
9328 {
9329         mm_player_t* player = (mm_player_t*) hplayer;
9330
9331         MMPLAYER_FENTER();
9332
9333         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9334
9335         if (callback && !player->bufmgr)
9336                 player->bufmgr = tbm_bufmgr_init(-1);
9337
9338         player->set_mode.media_packet_video_stream = (callback) ? TRUE : FALSE;
9339         player->video_stream_cb = callback;
9340         player->video_stream_cb_user_param = user_param;
9341
9342         LOGD("Stream cb Handle value is %p : %p, enable:%d\n", player, player->video_stream_cb, player->set_mode.media_packet_video_stream);
9343
9344         MMPLAYER_FLEAVE();
9345
9346         return MM_ERROR_NONE;
9347 }
9348
9349 int
9350 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
9351 {
9352         mm_player_t* player = (mm_player_t*) hplayer;
9353
9354         MMPLAYER_FENTER();
9355
9356         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9357
9358         player->audio_stream_cb = callback;
9359         player->audio_stream_cb_user_param = user_param;
9360         LOGD("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
9361
9362         MMPLAYER_FLEAVE();
9363
9364         return MM_ERROR_NONE;
9365 }
9366
9367 // set prepare size
9368 int
9369 _mmplayer_set_prepare_buffering_time(MMHandleType hplayer, int second)
9370 {
9371         mm_player_t* player = (mm_player_t*) hplayer;
9372
9373         MMPLAYER_FENTER();
9374
9375         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9376
9377         if (MMPLAYER_CURRENT_STATE(player) !=  MM_PLAYER_STATE_NULL)
9378                 return MM_ERROR_PLAYER_INVALID_STATE;
9379
9380         LOGD("pre buffer size : %d sec\n", second);
9381
9382         if (second <= 0) {
9383                 LOGE("bad size value\n");
9384                 return MM_ERROR_INVALID_ARGUMENT;
9385         }
9386
9387         if (player->streamer == NULL) {
9388                 player->streamer = __mm_player_streaming_create();
9389                 __mm_player_streaming_initialize(player->streamer);
9390         }
9391
9392         player->streamer->buffering_req.initial_second = second;
9393
9394         MMPLAYER_FLEAVE();
9395
9396         return MM_ERROR_NONE;
9397 }
9398
9399 // set runtime mode
9400 int
9401 _mmplayer_set_runtime_buffering_mode(MMHandleType hplayer, MMPlayerBufferingMode mode, int second)
9402 {
9403         mm_player_t* player = (mm_player_t*) hplayer;
9404
9405         MMPLAYER_FENTER();
9406
9407         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9408
9409         LOGD("mode %d\n", mode);
9410
9411         if ((mode < 0) || (mode > MM_PLAYER_BUFFERING_MODE_MAX) ||
9412                 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) && (second <= 0)))
9413                 return MM_ERROR_INVALID_ARGUMENT;
9414
9415         if (player->streamer == NULL) {
9416                 player->streamer = __mm_player_streaming_create();
9417                 __mm_player_streaming_initialize(player->streamer);
9418         }
9419
9420         player->streamer->buffering_req.mode = mode;
9421
9422         if ((second > 0) &&
9423                 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) ||
9424                 (mode == MM_PLAYER_BUFFERING_MODE_ADAPTIVE)))
9425                 player->streamer->buffering_req.runtime_second = second;
9426
9427         MMPLAYER_FLEAVE();
9428
9429         return MM_ERROR_NONE;
9430 }
9431
9432 static int
9433 __mmplayer_start_streaming_ext(mm_player_t *player)
9434 {
9435         gint ret = MM_ERROR_NONE;
9436
9437         MMPLAYER_FENTER();
9438         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9439
9440         if (MMPLAYER_IS_HTTP_PD(player)) {
9441                 if (!player->pd_downloader) {
9442                         ret = __mmplayer_realize_streaming_ext(player);
9443
9444                         if (ret != MM_ERROR_NONE) {
9445                                 LOGE("failed to realize streaming ext\n");
9446                                 return ret;
9447                         }
9448                 }
9449
9450                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI) {
9451                         ret = _mmplayer_start_pd_downloader((MMHandleType)player);
9452                         if (!ret) {
9453                                 LOGE("ERROR while starting PD...\n");
9454                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
9455                         }
9456                         ret = MM_ERROR_NONE;
9457                 }
9458         }
9459
9460         MMPLAYER_FLEAVE();
9461         return ret;
9462 }
9463
9464 int
9465 _mmplayer_start(MMHandleType hplayer) // @
9466 {
9467         mm_player_t* player = (mm_player_t*) hplayer;
9468         gint ret = MM_ERROR_NONE;
9469
9470         MMPLAYER_FENTER();
9471
9472         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9473
9474         /* check current state */
9475         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_START);
9476
9477         ret = _mmplayer_sound_acquire_focus(&player->sound_focus);
9478         if (ret != MM_ERROR_NONE) {
9479                 LOGE("failed to acquire sound focus.\n");
9480                 return ret;
9481         }
9482
9483         /* NOTE : we should check and create pipeline again if not created as we destroy
9484          * whole pipeline when stopping in streamming playback
9485          */
9486         if (!player->pipeline) {
9487                 ret = __gst_realize(player);
9488                 if (MM_ERROR_NONE != ret) {
9489                         LOGE("failed to realize before starting. only in streamming\n");
9490                         /* unlock */
9491                         return ret;
9492                 }
9493         }
9494
9495         ret = __mmplayer_start_streaming_ext(player);
9496         if (ret != MM_ERROR_NONE)
9497                 LOGE("failed to start streaming ext \n");
9498
9499         /* start pipeline */
9500         ret = __gst_start(player);
9501         if (ret != MM_ERROR_NONE)
9502                 LOGE("failed to start player.\n");
9503
9504         MMPLAYER_FLEAVE();
9505
9506         return ret;
9507 }
9508
9509 /* NOTE: post "not supported codec message" to application
9510  * when one codec is not found during AUTOPLUGGING in MSL.
9511  * So, it's separated with error of __mmplayer_gst_callback().
9512  * And, if any codec is not found, don't send message here.
9513  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
9514  */
9515 int
9516 __mmplayer_handle_missed_plugin(mm_player_t* player)
9517 {
9518         MMMessageParamType msg_param;
9519         memset(&msg_param, 0, sizeof(MMMessageParamType));
9520         gboolean post_msg_direct = FALSE;
9521
9522         MMPLAYER_FENTER();
9523
9524         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9525
9526         LOGD("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
9527                         player->not_supported_codec, player->can_support_codec);
9528
9529         if (player->not_found_demuxer) {
9530                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9531                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
9532
9533                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9534                 MMPLAYER_FREEIF(msg_param.data);
9535
9536                 return MM_ERROR_NONE;
9537         }
9538
9539         if (player->not_supported_codec) {
9540                 if (player->can_support_codec) {
9541                         // There is one codec to play
9542                         post_msg_direct = TRUE;
9543                 } else {
9544                         if (player->pipeline->audiobin) // Some content has only PCM data in container.
9545                                 post_msg_direct = TRUE;
9546                 }
9547
9548                 if (post_msg_direct) {
9549                         MMMessageParamType msg_param;
9550                         memset(&msg_param, 0, sizeof(MMMessageParamType));
9551
9552                         if (player->not_supported_codec ==  MISSING_PLUGIN_AUDIO) {
9553                                 LOGW("not found AUDIO codec, posting error code to application.\n");
9554
9555                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9556                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9557                         } else if (player->not_supported_codec ==  MISSING_PLUGIN_VIDEO) {
9558                                 LOGW("not found VIDEO codec, posting error code to application.\n");
9559
9560                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9561                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
9562                         }
9563
9564                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9565
9566                         MMPLAYER_FREEIF(msg_param.data);
9567
9568                         return MM_ERROR_NONE;
9569                 } else {
9570                         // no any supported codec case
9571                         LOGW("not found any codec, posting error code to application.\n");
9572
9573                         if (player->not_supported_codec ==  MISSING_PLUGIN_AUDIO) {
9574                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9575                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9576                         } else {
9577                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9578                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
9579                         }
9580
9581                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9582
9583                         MMPLAYER_FREEIF(msg_param.data);
9584                 }
9585         }
9586
9587         MMPLAYER_FLEAVE();
9588
9589         return MM_ERROR_NONE;
9590 }
9591
9592 static void __mmplayer_check_pipeline(mm_player_t* player)
9593 {
9594         GstState element_state = GST_STATE_VOID_PENDING;
9595         GstState element_pending_state = GST_STATE_VOID_PENDING;
9596         gint timeout = 0;
9597         int ret = MM_ERROR_NONE;
9598
9599         if (player->gapless.reconfigure) {
9600                 LOGW("pipeline is under construction.\n");
9601
9602                 MMPLAYER_PLAYBACK_LOCK(player);
9603                 MMPLAYER_PLAYBACK_UNLOCK(player);
9604
9605                 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
9606
9607                 /* wait for state transition */
9608                 ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND);
9609
9610                 if (ret == GST_STATE_CHANGE_FAILURE)
9611                         LOGE("failed to change pipeline state within %d sec\n", timeout);
9612         }
9613 }
9614
9615 /* NOTE : it should be able to call 'stop' anytime*/
9616 int
9617 _mmplayer_stop(MMHandleType hplayer) // @
9618 {
9619         mm_player_t* player = (mm_player_t*)hplayer;
9620         int ret = MM_ERROR_NONE;
9621
9622         MMPLAYER_FENTER();
9623
9624         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9625
9626         /* check current state */
9627         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_STOP);
9628
9629         /* check pipline building state */
9630         __mmplayer_check_pipeline(player);
9631         __mmplayer_reset_gapless_state(player);
9632
9633         /* NOTE : application should not wait for EOS after calling STOP */
9634         __mmplayer_cancel_eos_timer(player);
9635
9636         __mmplayer_unrealize_streaming_ext(player);
9637
9638         /* reset */
9639         player->doing_seek = FALSE;
9640
9641         /* stop pipeline */
9642         ret = __gst_stop(player);
9643
9644         if (ret != MM_ERROR_NONE)
9645                 LOGE("failed to stop player.\n");
9646
9647         MMPLAYER_FLEAVE();
9648
9649         return ret;
9650 }
9651
9652 int
9653 _mmplayer_pause(MMHandleType hplayer) // @
9654 {
9655         mm_player_t* player = (mm_player_t*)hplayer;
9656         gint64 pos_msec = 0;
9657         gboolean async = FALSE;
9658         gint ret = MM_ERROR_NONE;
9659
9660         MMPLAYER_FENTER();
9661
9662         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9663
9664         /* check current state */
9665         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_PAUSE);
9666
9667         /* check pipline building state */
9668         __mmplayer_check_pipeline(player);
9669
9670         switch (MMPLAYER_CURRENT_STATE(player)) {
9671         case MM_PLAYER_STATE_READY:
9672                 {
9673                         /* check prepare async or not.
9674                          * In the case of streaming playback, it's recommned to avoid blocking wait.
9675                          */
9676                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
9677                         LOGD("prepare working mode : %s", (async ? "async" : "sync"));
9678
9679                         /* Changing back sync of rtspsrc to async */
9680                         if (MMPLAYER_IS_RTSP_STREAMING(player)) {
9681                                 LOGD("async prepare working mode for rtsp");
9682                                 async = TRUE;
9683                         }
9684                 }
9685                 break;
9686
9687         case MM_PLAYER_STATE_PLAYING:
9688                 {
9689                         /* NOTE : store current point to overcome some bad operation
9690                         *(returning zero when getting current position in paused state) of some
9691                         * elements
9692                         */
9693                         if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec))
9694                                 LOGW("getting current position failed in paused\n");
9695
9696                         player->last_position = pos_msec;
9697
9698                         /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
9699                            But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
9700                            This causes problem is position calculation during normal pause resume scenarios also.
9701                            Currently during pause , we are sending the current position to rtspsrc module for position saving. */
9702                         if ((MMPLAYER_IS_RTSP_STREAMING( player )) &&
9703                                 (__mmplayer_get_stream_service_type(player) != STREAMING_SERVICE_LIVE)) {
9704                                 g_object_set( player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL );
9705                         }
9706                 }
9707                 break;
9708         }
9709
9710         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
9711                 LOGD("doing async pause in case of ms buff src");
9712                 async = TRUE;
9713         }
9714
9715         /* pause pipeline */
9716         ret = __gst_pause(player, async);
9717
9718         if (ret != MM_ERROR_NONE)
9719                 LOGE("failed to pause player. ret : 0x%x\n", ret);
9720
9721         if (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) {
9722                 if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "display_rotation"))
9723                         LOGE("failed to update display_rotation");
9724         }
9725
9726         MMPLAYER_FLEAVE();
9727
9728         return ret;
9729 }
9730
9731 int
9732 _mmplayer_resume(MMHandleType hplayer)
9733 {
9734         mm_player_t* player = (mm_player_t*)hplayer;
9735         int ret = MM_ERROR_NONE;
9736         gboolean async = FALSE;
9737
9738         MMPLAYER_FENTER();
9739
9740         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9741
9742         /* Changing back sync mode rtspsrc to async */
9743         if ((MMPLAYER_IS_RTSP_STREAMING(player))) {
9744                 LOGD("async resume for rtsp case");
9745                 async = TRUE;
9746         }
9747
9748         /* check current state */
9749         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_RESUME);
9750
9751         ret = _mmplayer_sound_acquire_focus(&player->sound_focus);
9752         if (ret != MM_ERROR_NONE) {
9753                 LOGE("failed to acquire sound focus.\n");
9754                 return ret;
9755         }
9756
9757         ret = __gst_resume(player, async);
9758
9759         if (ret != MM_ERROR_NONE)
9760                 LOGE("failed to resume player.\n");
9761
9762         MMPLAYER_FLEAVE();
9763
9764         return ret;
9765 }
9766
9767 int
9768 __mmplayer_set_play_count(mm_player_t* player, gint count)
9769 {
9770         MMHandleType attrs = 0;
9771
9772         MMPLAYER_FENTER();
9773
9774         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9775
9776         attrs =  MMPLAYER_GET_ATTRS(player);
9777         if (!attrs) {
9778                 LOGE("fail to get attributes.\n");
9779                 return MM_ERROR_PLAYER_INTERNAL;
9780         }
9781
9782         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
9783         if (mmf_attrs_commit(attrs)) /* return -1 if error */
9784                 LOGE("failed to commit\n");
9785
9786         MMPLAYER_FLEAVE();
9787
9788         return  MM_ERROR_NONE;
9789 }
9790
9791 int
9792 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
9793 {
9794         mm_player_t* player = (mm_player_t*)hplayer;
9795         gint64 start_pos = 0;
9796         gint64 end_pos = 0;
9797         gint infinity = -1;
9798
9799         MMPLAYER_FENTER();
9800
9801         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9802         MMPLAYER_RETURN_VAL_IF_FAIL(end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT);
9803
9804         player->section_repeat = TRUE;
9805         player->section_repeat_start = start;
9806         player->section_repeat_end = end;
9807
9808         start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
9809         end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
9810
9811         __mmplayer_set_play_count(player, infinity);
9812
9813         if ((!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
9814                                         player->playback_rate,
9815                                         GST_FORMAT_TIME,
9816                                         (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
9817                                         GST_SEEK_TYPE_SET, start_pos,
9818                                         GST_SEEK_TYPE_SET, end_pos))) {
9819                 LOGE("failed to activate section repeat\n");
9820
9821                 return MM_ERROR_PLAYER_SEEK;
9822         }
9823
9824         LOGD("succeeded to set section repeat from %d to %d\n",
9825                 player->section_repeat_start, player->section_repeat_end);
9826
9827         MMPLAYER_FLEAVE();
9828
9829         return  MM_ERROR_NONE;
9830 }
9831
9832 static int
9833 __mmplayer_set_pcm_extraction(mm_player_t* player)
9834 {
9835         gint64 start_nsec = 0;
9836         gint64 end_nsec = 0;
9837         gint64 dur_nsec = 0;
9838         gint64 dur_msec = 0;
9839         int required_start = 0;
9840         int required_end = 0;
9841         int ret = 0;
9842
9843         MMPLAYER_FENTER();
9844
9845         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
9846
9847         mm_attrs_multiple_get(player->attrs,
9848                 NULL,
9849                 "pcm_extraction_start_msec", &required_start,
9850                 "pcm_extraction_end_msec", &required_end,
9851                 NULL);
9852
9853         LOGD("pcm extraction required position is from [%d] to [%d](msec)\n", required_start, required_end);
9854
9855         if (required_start == 0 && required_end == 0) {
9856                 LOGD("extracting entire stream");
9857                 return MM_ERROR_NONE;
9858         } else if (required_start < 0 || required_start > required_end || required_end < 0) {
9859                 LOGD("invalid range for pcm extraction");
9860                 return MM_ERROR_INVALID_ARGUMENT;
9861         }
9862
9863         /* get duration */
9864         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
9865         if (!ret) {
9866                 LOGE("failed to get duration");
9867                 return MM_ERROR_PLAYER_INTERNAL;
9868         }
9869         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
9870
9871         if (dur_msec < required_end) {
9872                 // FIXME
9873                 LOGD("invalid end pos for pcm extraction");
9874                 return MM_ERROR_INVALID_ARGUMENT;
9875         }
9876
9877         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
9878         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
9879
9880         if ((!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
9881                                         1.0,
9882                                         GST_FORMAT_TIME,
9883                                         (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
9884                                         GST_SEEK_TYPE_SET, start_nsec,
9885                                         GST_SEEK_TYPE_SET, end_nsec))) {
9886                 LOGE("failed to seek for pcm extraction\n");
9887
9888                 return MM_ERROR_PLAYER_SEEK;
9889         }
9890
9891         LOGD("succeeded to set up segment extraction from [%llu] to [%llu](nsec)\n", start_nsec, end_nsec);
9892
9893         MMPLAYER_FLEAVE();
9894
9895         return MM_ERROR_NONE;
9896 }
9897
9898 int
9899 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
9900 {
9901         mm_player_t* player = (mm_player_t*)hplayer;
9902         gint64 cur_pos = 0;
9903         gint onetime = 1;
9904
9905         MMPLAYER_FENTER();
9906
9907         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9908
9909         player->section_repeat = FALSE;
9910
9911         __mmplayer_set_play_count(player, onetime);
9912
9913         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_pos);
9914
9915         if ((!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
9916                                         1.0,
9917                                         GST_FORMAT_TIME,
9918                                         (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
9919                                         GST_SEEK_TYPE_SET, cur_pos,
9920                                         GST_SEEK_TYPE_SET, player->duration))) {
9921                 LOGE("failed to deactivate section repeat\n");
9922
9923                 return MM_ERROR_PLAYER_SEEK;
9924         }
9925
9926         MMPLAYER_FENTER();
9927
9928         return MM_ERROR_NONE;
9929 }
9930
9931 int
9932 _mmplayer_set_playspeed(MMHandleType hplayer, float rate, bool streaming)
9933 {
9934         mm_player_t* player = (mm_player_t*)hplayer;
9935         gint64 pos_msec = 0;
9936         int ret = MM_ERROR_NONE;
9937         int mute = FALSE;
9938         signed long long start = 0, stop = 0;
9939         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
9940         MMPLAYER_FENTER();
9941
9942         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
9943         MMPLAYER_RETURN_VAL_IF_FAIL(streaming || !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API);
9944
9945         /* The sound of video is not supported under 0.0 and over 2.0. */
9946         if (rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN) {
9947                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
9948                         mute = TRUE;
9949         }
9950         _mmplayer_set_mute(hplayer, mute);
9951
9952         if (player->playback_rate == rate)
9953                 return MM_ERROR_NONE;
9954
9955         /* If the position is reached at start potion during fast backward, EOS is posted.
9956          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
9957          * */
9958         player->playback_rate = rate;
9959
9960         current_state = MMPLAYER_CURRENT_STATE(player);
9961
9962         if (current_state != MM_PLAYER_STATE_PAUSED)
9963                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
9964
9965         LOGD("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_msec), ret, current_state);
9966
9967         if ((current_state == MM_PLAYER_STATE_PAUSED)
9968                 || (!ret) /*|| (player->last_position != 0 && pos_msec == 0)*/) {
9969                 LOGW("returning last point : %lld\n", player->last_position);
9970                 pos_msec = player->last_position;
9971         }
9972
9973
9974         if (rate >= 0) {
9975                 start = pos_msec;
9976                 stop = GST_CLOCK_TIME_NONE;
9977         } else {
9978                 start = GST_CLOCK_TIME_NONE;
9979                 stop = pos_msec;
9980         }
9981         if ((!gst_element_seek(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
9982                                 rate,
9983                                 GST_FORMAT_TIME,
9984                                 (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
9985                                 GST_SEEK_TYPE_SET, start,
9986                                 GST_SEEK_TYPE_SET, stop))) {
9987                 LOGE("failed to set speed playback\n");
9988                 return MM_ERROR_PLAYER_SEEK;
9989         }
9990
9991         LOGD("succeeded to set speed playback as %0.1f\n", rate);
9992
9993         MMPLAYER_FLEAVE();
9994
9995         return MM_ERROR_NONE;;
9996 }
9997
9998 int
9999 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
10000 {
10001         mm_player_t* player = (mm_player_t*)hplayer;
10002         int ret = MM_ERROR_NONE;
10003
10004         MMPLAYER_FENTER();
10005
10006         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10007
10008         /* check pipline building state */
10009         __mmplayer_check_pipeline(player);
10010
10011         ret = __gst_set_position(player, format, (unsigned long)position, FALSE);
10012
10013         MMPLAYER_FLEAVE();
10014
10015         return ret;
10016 }
10017
10018 int
10019 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
10020 {
10021         mm_player_t* player = (mm_player_t*)hplayer;
10022         int ret = MM_ERROR_NONE;
10023
10024         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10025
10026         ret = __gst_get_position(player, format, position);
10027
10028         return ret;
10029 }
10030
10031 int
10032 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
10033 {
10034         mm_player_t* player = (mm_player_t*)hplayer;
10035         int ret = MM_ERROR_NONE;
10036
10037         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10038
10039         ret = __gst_get_buffer_position(player, format, start_pos, stop_pos);
10040
10041         return ret;
10042 }
10043
10044 int
10045 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
10046 {
10047         mm_player_t* player = (mm_player_t*)hplayer;
10048         int ret = MM_ERROR_NONE;
10049
10050         MMPLAYER_FENTER();
10051
10052         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10053
10054         ret = __gst_adjust_subtitle_position(player, format, position);
10055
10056         MMPLAYER_FLEAVE();
10057
10058         return ret;
10059 }
10060 int
10061 _mmplayer_adjust_video_postion(MMHandleType hplayer, int offset) // @
10062 {
10063         mm_player_t* player = (mm_player_t*)hplayer;
10064         int ret = MM_ERROR_NONE;
10065
10066         MMPLAYER_FENTER();
10067
10068         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10069
10070         ret = __gst_adjust_video_position(player, offset);
10071
10072         MMPLAYER_FLEAVE();
10073
10074         return ret;
10075 }
10076
10077 static gboolean
10078 __mmplayer_is_midi_type(gchar* str_caps)
10079 {
10080         if ((g_strrstr(str_caps, "audio/midi")) ||
10081                 (g_strrstr(str_caps, "application/x-gst_ff-mmf")) ||
10082                 (g_strrstr(str_caps, "application/x-smaf")) ||
10083                 (g_strrstr(str_caps, "audio/x-imelody")) ||
10084                 (g_strrstr(str_caps, "audio/mobile-xmf")) ||
10085                 (g_strrstr(str_caps, "audio/xmf")) ||
10086                 (g_strrstr(str_caps, "audio/mxmf"))) {
10087                 LOGD("midi\n");
10088                 return TRUE;
10089         }
10090
10091         return FALSE;
10092 }
10093
10094 static gboolean
10095 __mmplayer_is_only_mp3_type(gchar *str_caps)
10096 {
10097         if (g_strrstr(str_caps, "application/x-id3") ||
10098                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion= (int)1")))
10099                 return TRUE;
10100         return FALSE;
10101 }
10102
10103 static void
10104 __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps)
10105 {
10106         GstStructure* caps_structure = NULL;
10107         gint samplerate = 0;
10108         gint channels = 0;
10109
10110         MMPLAYER_FENTER();
10111         MMPLAYER_RETURN_IF_FAIL(player && caps);
10112
10113         caps_structure = gst_caps_get_structure(caps, 0);
10114
10115         /* set stream information */
10116         gst_structure_get_int(caps_structure, "rate", &samplerate);
10117         mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
10118
10119         gst_structure_get_int(caps_structure, "channels", &channels);
10120         mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
10121
10122         LOGD("audio samplerate : %d     channels : %d\n", samplerate, channels);
10123 }
10124
10125 static void
10126 __mmplayer_update_content_type_info(mm_player_t* player)
10127 {
10128         MMPLAYER_FENTER();
10129         MMPLAYER_RETURN_IF_FAIL(player && player->type);
10130
10131         if (__mmplayer_is_midi_type(player->type)) {
10132                 player->bypass_audio_effect = TRUE;
10133         } else if (g_strrstr(player->type, "application/x-hls")) {
10134                 /* If it can't know exact type when it parses uri because of redirection case,
10135                  * it will be fixed by typefinder or when doing autoplugging.
10136                  */
10137                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
10138                 if (player->streamer) {
10139                         player->streamer->is_adaptive_streaming = TRUE;
10140                         player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
10141                         player->streamer->buffering_req.runtime_second = 5;
10142                 }
10143         } else if (g_strrstr(player->type, "application/dash+xml")) {
10144                 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
10145         }
10146
10147         MMPLAYER_FLEAVE();
10148 }
10149
10150 static void
10151 __mmplayer_typefind_have_type(GstElement *tf, guint probability, // @
10152 GstCaps *caps, gpointer data)
10153 {
10154         mm_player_t* player = (mm_player_t*)data;
10155         GstPad* pad = NULL;
10156
10157         MMPLAYER_FENTER();
10158
10159         MMPLAYER_RETURN_IF_FAIL(player && tf && caps);
10160
10161         /* store type string */
10162         MMPLAYER_FREEIF(player->type);
10163         player->type = gst_caps_to_string(caps);
10164         if (player->type)
10165                 LOGD("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
10166
10167         if ((!MMPLAYER_IS_WFD_STREAMING(player)) &&
10168                 (!MMPLAYER_IS_RTSP_STREAMING(player)) &&
10169                 (g_strrstr(player->type, "audio/x-raw-int"))) {
10170                 LOGE("not support media format\n");
10171
10172                 if (player->msg_posted == FALSE) {
10173                         MMMessageParamType msg_param;
10174                         memset(&msg_param, 0, sizeof(MMMessageParamType));
10175
10176                         msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
10177                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
10178
10179                         /* don't post more if one was sent already */
10180                         player->msg_posted = TRUE;
10181                 }
10182                 return;
10183         }
10184
10185         __mmplayer_update_content_type_info(player);
10186
10187         pad = gst_element_get_static_pad(tf, "src");
10188         if (!pad) {
10189                 LOGE("fail to get typefind src pad.\n");
10190                 return;
10191         }
10192
10193         if (player->use_decodebin) {
10194                 if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
10195                         gboolean async = FALSE;
10196                         LOGE("failed to autoplug %s\n", player->type);
10197
10198                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10199
10200                         if (async && player->msg_posted == FALSE)
10201                                 __mmplayer_handle_missed_plugin(player);
10202
10203                         goto DONE;
10204                 }
10205         } else {
10206                 /* try to plug */
10207                 if (!__mmplayer_try_to_plug(player, pad, caps)) {
10208                         gboolean async = FALSE;
10209                         LOGE("failed to autoplug %s\n", player->type);
10210
10211                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10212
10213                         if (async && player->msg_posted == FALSE)
10214                                 __mmplayer_handle_missed_plugin(player);
10215
10216                         goto DONE;
10217                 }
10218
10219                 /* finish autopluging if no dynamic pad waiting */
10220                 if ((!player->have_dynamic_pad) && (!player->has_many_types)) {
10221                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
10222                                 __mmplayer_pipeline_complete(NULL, (gpointer)player);
10223                 }
10224         }
10225
10226 DONE:
10227         gst_object_unref(GST_OBJECT(pad));
10228
10229         MMPLAYER_FLEAVE();
10230
10231         return;
10232 }
10233
10234 static GstElement *
10235 __mmplayer_create_decodebin(mm_player_t* player)
10236 {
10237         GstElement *decodebin = NULL;
10238
10239         MMPLAYER_FENTER();
10240
10241         /* create decodebin */
10242         decodebin = gst_element_factory_make("decodebin", NULL);
10243
10244         if (!decodebin) {
10245                 LOGE("fail to create decodebin\n");
10246                 goto ERROR;
10247         }
10248
10249         /* raw pad handling signal */
10250         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
10251                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
10252
10253         /* no-more-pad pad handling signal */
10254         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
10255                                                 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
10256
10257         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
10258                                                 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
10259
10260         /* This signal is emitted when a pad for which there is no further possible
10261            decoding is added to the decodebin.*/
10262         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
10263                                                 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player);
10264
10265         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
10266            before looking for any elements that can handle that stream.*/
10267         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
10268                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
10269
10270         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
10271            before looking for any elements that can handle that stream.*/
10272         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
10273                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
10274
10275         /* This signal is emitted once decodebin has finished decoding all the data.*/
10276         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
10277                                                 G_CALLBACK(__mmplayer_gst_decode_drained), player);
10278
10279         /* This signal is emitted when a element is added to the bin.*/
10280         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
10281                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
10282
10283 ERROR:
10284         return decodebin;
10285 }
10286
10287 static gboolean
10288 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
10289 {
10290         MMPlayerGstElement* mainbin = NULL;
10291         GstElement* decodebin = NULL;
10292         GstElement* queue2 = NULL;
10293         GstPad* sinkpad = NULL;
10294         GstPad* qsrcpad = NULL;
10295         gint64 dur_bytes = 0L;
10296
10297         guint max_buffer_size_bytes = 0;
10298         gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
10299
10300         MMPLAYER_FENTER();
10301         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, FALSE);
10302
10303         mainbin = player->pipeline->mainbin;
10304
10305         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
10306                 (MMPLAYER_IS_HTTP_STREAMING(player))) {
10307                 LOGD("creating http streaming buffering queue(queue2)\n");
10308
10309                 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
10310                         LOGE("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
10311                 } else {
10312                         queue2 = gst_element_factory_make("queue2", "queue2");
10313                         if (!queue2) {
10314                                 LOGE("failed to create buffering queue element\n");
10315                                 goto ERROR;
10316                         }
10317
10318                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) {
10319                                 LOGE("failed to add buffering queue\n");
10320                                 goto ERROR;
10321                         }
10322
10323                         sinkpad = gst_element_get_static_pad(queue2, "sink");
10324                         qsrcpad = gst_element_get_static_pad(queue2, "src");
10325
10326                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
10327                                 LOGE("failed to link buffering queue\n");
10328                                 goto ERROR;
10329                         }
10330
10331                         if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
10332                                 LOGE("fail to get duration.\n");
10333
10334                         LOGD("dur_bytes = %lld\n", dur_bytes);
10335
10336                         muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
10337
10338                         if (dur_bytes > 0) {
10339                                 if (MMPLAYER_USE_FILE_FOR_BUFFERING(player)) {
10340                                         type = MUXED_BUFFER_TYPE_FILE;
10341                                 } else {
10342                                         type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
10343                                         player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
10344                                 }
10345                         } else {
10346                                 dur_bytes = 0;
10347                         }
10348
10349                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
10350                         // if (!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
10351                         if (!g_strrstr(player->type, "video/mpegts")) {
10352                                 max_buffer_size_bytes = (type == MUXED_BUFFER_TYPE_FILE) ? (player->ini.http_max_size_bytes) : (5*1024*1024);
10353                                 LOGD("max_buffer_size_bytes = %d\n", max_buffer_size_bytes);
10354
10355                                 __mm_player_streaming_set_queue2(player->streamer,
10356                                                                                                 queue2,
10357                                                                                                 FALSE,
10358                                                                                                 max_buffer_size_bytes,
10359                                                                                                 player->ini.http_buffering_time,
10360                                                                                                 1.0,                                                            // no meaning
10361                                                                                                 player->ini.http_buffering_limit,       // no meaning
10362                                                                                                 type,
10363                                                                                                 player->http_file_buffering_path,
10364                                                                                                 (guint64)dur_bytes);
10365                         }
10366
10367                         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(queue2)) {
10368                                 LOGE("failed to sync queue2 state with parent\n");
10369                                 goto ERROR;
10370                         }
10371
10372                         srcpad = qsrcpad;
10373
10374                         gst_object_unref(GST_OBJECT(sinkpad));
10375
10376                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
10377                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
10378                 }
10379         }
10380
10381         /* create decodebin */
10382         decodebin = __mmplayer_create_decodebin(player);
10383
10384         if (!decodebin) {
10385                 LOGE("can not create autoplug element\n");
10386                 goto ERROR;
10387         }
10388
10389         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
10390                 LOGE("failed to add decodebin\n");
10391                 goto ERROR;
10392         }
10393
10394         /* to force caps on the decodebin element and avoid reparsing stuff by
10395         * typefind. It also avoids a deadlock in the way typefind activates pads in
10396         * the state change */
10397         g_object_set(decodebin, "sink-caps", caps, NULL);
10398
10399         sinkpad = gst_element_get_static_pad(decodebin, "sink");
10400
10401         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
10402                 LOGE("failed to link decodebin\n");
10403                 goto ERROR;
10404         }
10405
10406         gst_object_unref(GST_OBJECT(sinkpad));
10407
10408         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
10409         mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin;
10410
10411         /* set decodebin property about buffer in streaming playback. *
10412          * in case of hls, it does not need to have big buffer        *
10413          * because it is kind of adaptive streaming.                  */
10414         if (((!MMPLAYER_IS_HTTP_PD(player)) &&
10415            (MMPLAYER_IS_HTTP_STREAMING(player))) || MMPLAYER_IS_DASH_STREAMING(player)) {
10416                 guint max_size_bytes = MAX_DECODEBIN_BUFFER_BYTES;
10417                 guint64 max_size_time = MAX_DECODEBIN_BUFFER_TIME;
10418                 init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
10419
10420                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {
10421                         max_size_bytes = MAX_DECODEBIN_ADAPTIVE_BUFFER_BYTES;
10422                         max_size_time = MAX_DECODEBIN_ADAPTIVE_BUFFER_TIME;
10423                 }
10424
10425                 g_object_set(G_OBJECT(decodebin), "use-buffering", TRUE,
10426                                                                                         "high-percent", (gint)player->ini.http_buffering_limit,
10427                                                                                         "low-percent", 1,   // 1%
10428                                                                                         "max-size-bytes", max_size_bytes,
10429                                                                                         "max-size-time", (guint64)(max_size_time * GST_SECOND),
10430                                                                                         "max-size-buffers", 0, NULL);  // disable or automatic
10431         }
10432
10433         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin)) {
10434                 LOGE("failed to sync decodebin state with parent\n");
10435                 goto ERROR;
10436         }
10437
10438         MMPLAYER_FLEAVE();
10439
10440         return TRUE;
10441
10442 ERROR:
10443
10444         if (sinkpad)
10445                 gst_object_unref(GST_OBJECT(sinkpad));
10446
10447         if (queue2) {
10448                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
10449                  * You need to explicitly set elements to the NULL state before
10450                  * dropping the final reference, to allow them to clean up.
10451                  */
10452                 gst_element_set_state(queue2, GST_STATE_NULL);
10453
10454                 /* And, it still has a parent "player".
10455                  * You need to let the parent manage the object instead of unreffing the object directly.
10456                  */
10457                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
10458                 gst_object_unref(queue2);
10459                 queue2 = NULL;
10460         }
10461
10462         if (decodebin) {
10463                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
10464                  * You need to explicitly set elements to the NULL state before
10465                  * dropping the final reference, to allow them to clean up.
10466                  */
10467                 gst_element_set_state(decodebin, GST_STATE_NULL);
10468
10469                 /* And, it still has a parent "player".
10470                  * You need to let the parent manage the object instead of unreffing the object directly.
10471                  */
10472
10473                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
10474                 gst_object_unref(decodebin);
10475                 decodebin = NULL;
10476         }
10477
10478         return FALSE;
10479 }
10480
10481 /* it will return first created element */
10482 static gboolean
10483 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
10484 {
10485         MMPlayerGstElement* mainbin = NULL;
10486         const char* mime = NULL;
10487         const GList* item = NULL;
10488         const gchar* klass = NULL;
10489         GstCaps* res = NULL;
10490         gboolean skip = FALSE;
10491         GstPad* queue_pad = NULL;
10492         GstElement* queue = NULL;
10493         GstElement *element = NULL;
10494
10495         MMPLAYER_FENTER();
10496
10497         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, FALSE);
10498
10499         mainbin = player->pipeline->mainbin;
10500
10501         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
10502
10503         /* return if we got raw output */
10504         if (g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
10505                 || g_str_has_prefix(mime, "text/plain") || g_str_has_prefix(mime, "text/x-pango-markup")) {
10506
10507                 element = (GstElement*)gst_pad_get_parent(pad);
10508 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
10509  * No queue will be added. I think it can caused breaking sound when playing raw audio
10510  * frames but there's no different. Decodebin also doesn't add with those wav fils.
10511  * Anyway, currentely raw-queue seems not necessary.
10512  */
10513 #if 1
10514                 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
10515                  * has linked. if so, we need to add queue for quality of output. note that
10516                  * decodebin also has same problem.
10517                  */
10518                 klass = gst_element_factory_get_metadata(gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
10519
10520                 /* add queue if needed */
10521                 if ((g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
10522                         || g_strrstr(klass, "Parse")) &&  !g_str_has_prefix(mime, "text")) {
10523                         LOGD("adding raw queue\n");
10524
10525                         queue = gst_element_factory_make("queue", NULL);
10526                         if (!queue) {
10527                                 LOGW("failed to create queue\n");
10528                                 goto ERROR;
10529                         }
10530
10531                         /* warmup */
10532                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY)) {
10533                                 LOGW("failed to set state READY to queue\n");
10534                                 goto ERROR;
10535                         }
10536
10537                         /* add to pipeline */
10538                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue)) {
10539                                 LOGW("failed to add queue\n");
10540                                 goto ERROR;
10541                         }
10542
10543                         /* link queue */
10544                         queue_pad = gst_element_get_static_pad(queue, "sink");
10545
10546                         if (GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad)) {
10547                                 LOGW("failed to link queue\n");
10548                                 goto ERROR;
10549                         }
10550                         gst_object_unref(GST_OBJECT(queue_pad));
10551                         queue_pad = NULL;
10552
10553                         /* running */
10554                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED)) {
10555                                 LOGW("failed to set state PAUSED to queue\n");
10556                                 goto ERROR;
10557                         }
10558
10559                         /* replace given pad to queue:src */
10560                         pad = gst_element_get_static_pad(queue, "src");
10561                         if (!pad) {
10562                                 LOGW("failed to get pad from queue\n");
10563                                 goto ERROR;
10564                         }
10565                 }
10566 #endif
10567                 /* check if player can do start continually */
10568                 MMPLAYER_CHECK_CMD_IF_EXIT(player);
10569
10570                 if (__mmplayer_link_sink(player, pad))
10571                         __mmplayer_gst_decode_callback(element, pad, player);
10572
10573                 gst_object_unref(GST_OBJECT(element));
10574                 element = NULL;
10575
10576                 return TRUE;
10577         }
10578
10579         item = player->factories;
10580         for (; item != NULL; item = item->next) {
10581                 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
10582                 const GList *pads;
10583                 gint idx = 0;
10584
10585                 skip = FALSE;
10586
10587                 /* filtering exclude keyword */
10588                 for (idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++) {
10589                         if (g_strrstr(GST_OBJECT_NAME(factory),
10590                                         player->ini.exclude_element_keyword[idx])) {
10591                                 LOGW("skipping [%s] by exculde keyword [%s]\n",
10592                                         GST_OBJECT_NAME(factory),
10593                                         player->ini.exclude_element_keyword[idx]);
10594
10595                                 skip = TRUE;
10596                                 break;
10597                         }
10598                 }
10599
10600                 if (MMPLAYER_IS_RTSP_STREAMING(player) && g_strrstr(GST_OBJECT_NAME(factory), "omx_mpeg4dec")) {
10601                         // omx decoder can not support mpeg4video data partitioned
10602                         // rtsp streaming didn't know mpeg4video data partitioned format
10603                         // so, if rtsp playback, player will skip omx_mpeg4dec.
10604                         LOGW("skipping [%s] when rtsp streaming \n",
10605                                         GST_OBJECT_NAME(factory));
10606
10607                         skip = TRUE;
10608                 }
10609
10610                 if (skip) continue;
10611
10612                 /* check factory class for filtering */
10613                 klass = gst_element_factory_get_metadata(GST_ELEMENT_FACTORY(factory), GST_ELEMENT_METADATA_KLASS);
10614
10615                 /*parsers are not required in case of external feeder*/
10616                 if (g_strrstr(klass, "Codec/Parser") && MMPLAYER_IS_MS_BUFF_SRC(player))
10617                         continue;
10618
10619                 /* NOTE : msl don't need to use image plugins.
10620                  * So, those plugins should be skipped for error handling.
10621                  */
10622                 if (g_strrstr(klass, "Codec/Decoder/Image")) {
10623                         LOGD("skipping [%s] by not required\n", GST_OBJECT_NAME(factory));
10624                         continue;
10625                 }
10626
10627                 /* check pad compatability */
10628                 for (pads = gst_element_factory_get_static_pad_templates(factory);
10629                                         pads != NULL; pads = pads->next) {
10630                         GstStaticPadTemplate *temp1 = pads->data;
10631                         GstCaps* static_caps = NULL;
10632
10633                         if (temp1->direction != GST_PAD_SINK
10634                                 || temp1->presence != GST_PAD_ALWAYS)
10635                                 continue;
10636
10637                         /* using existing caps */
10638                         if (GST_IS_CAPS(&temp1->static_caps.caps))
10639                                 static_caps = gst_caps_ref(temp1->static_caps.caps);
10640                         /* create one */
10641                         else
10642                                 static_caps = gst_caps_from_string(temp1->static_caps.string);
10643
10644                         res = gst_caps_intersect((GstCaps*)caps, static_caps);
10645                         gst_caps_unref(static_caps);
10646                         static_caps = NULL;
10647
10648                         if (res && !gst_caps_is_empty(res)) {
10649                                 GstElement *new_element;
10650                                 GList *elements = player->parsers;
10651                                 char *name_template = g_strdup(temp1->name_template);
10652                                 gchar *name_to_plug = GST_OBJECT_NAME(factory);
10653                                 gst_caps_unref(res);
10654
10655                                 /* check ALP Codec can be used or not */
10656                                 if ((g_strrstr(klass, "Codec/Decoder/Audio"))) {
10657                                         /* consider mp3 audio only */
10658                                         if (!MMPLAYER_IS_STREAMING(player) && __mmplayer_is_only_mp3_type(player->type)) {
10659                                                 /* try to use ALP decoder first instead of selected decoder */
10660                                                 GstElement *element = NULL;
10661                                                 GstElementFactory * element_facory;
10662                                                 gchar *path = NULL;
10663                                                 guint64 data_size = 0;
10664                                                 #define MIN_THRESHOLD_SIZE  320 * 1024 // 320K
10665                                                 struct stat sb;
10666
10667                                                 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
10668
10669                                                 if (stat(path, &sb) == 0)
10670                                                         data_size = (guint64)sb.st_size;
10671                                                 LOGD("file size : %u", data_size);
10672
10673                                                 if (data_size > MIN_THRESHOLD_SIZE) {
10674                                                         LOGD("checking if ALP can be used or not");
10675                                                         element = gst_element_factory_make("omx_mp3dec", "omx mp3 decoder");
10676                                                         if (element) {
10677                                                                 /* check availability because multi-instance is not supported */
10678                                                                 GstStateChangeReturn ret = gst_element_set_state(element, GST_STATE_READY);
10679
10680                                                                 if (ret != GST_STATE_CHANGE_SUCCESS) {
10681                                                                         // use just selected decoder
10682                                                                         gst_object_unref(element);
10683                                                                 } else if (ret == GST_STATE_CHANGE_SUCCESS) {
10684                                                                         // replace facotry to use omx
10685                                                                         /* clean  */
10686                                                                         gst_element_set_state(element, GST_STATE_NULL);
10687                                                                         gst_object_unref(element);
10688
10689                                                                         element_facory = gst_element_factory_find("omx_mp3dec");
10690                                                                         /* replace, otherwise use selected thing instead */
10691                                                                         if (element_facory) {
10692                                                                                 factory = element_facory;
10693                                                                                 name_to_plug = GST_OBJECT_NAME(factory);
10694                                                                         }
10695                                                                 }
10696                                                         }
10697                                                 }
10698                                         }
10699                                 } else if ((g_strrstr(klass, "Codec/Decoder/Video"))) {
10700                                         if (g_strrstr(GST_OBJECT_NAME(factory), "omx_")) {
10701                                                 char *env = getenv("MM_PLAYER_HW_CODEC_DISABLE");
10702                                                 if (env != NULL) {
10703                                                         if (strncasecmp(env, "yes", 3) == 0) {
10704                                                                 LOGD("skipping [%s] by disabled\n", name_to_plug);
10705                                                                 MMPLAYER_FREEIF(name_template);
10706                                                                 continue;
10707                                                         }
10708                                                 }
10709                                         }
10710                                 }
10711
10712                                 LOGD("found %s to plug\n", name_to_plug);
10713
10714                                 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
10715                                 if (!new_element) {
10716                                         LOGE("failed to create element [%s]. continue with next.\n",
10717                                                 GST_OBJECT_NAME(factory));
10718
10719                                         MMPLAYER_FREEIF(name_template);
10720
10721                                         continue;
10722                                 }
10723
10724                                 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
10725                                  * because parser can accept its own output as input.
10726                                  */
10727                                 if (g_strrstr(klass, "Parser")) {
10728                                         gchar *selected = NULL;
10729
10730                                         for (; elements; elements = g_list_next(elements)) {
10731                                                 gchar *element_name = elements->data;
10732
10733                                                 if (g_strrstr(element_name, name_to_plug)) {
10734                                                         LOGD("but, %s already linked, so skipping it\n", name_to_plug);
10735                                                         skip = TRUE;
10736                                                 }
10737                                         }
10738
10739                                         if (skip) {
10740                                                 MMPLAYER_FREEIF(name_template);
10741                                                 continue;
10742                                         }
10743
10744                                         selected = g_strdup(name_to_plug);
10745                                         player->parsers = g_list_append(player->parsers, selected);
10746                                 }
10747
10748                                 /* store specific handles for futher control */
10749                                 if (g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) {
10750                                         /* FIXIT : first value will be overwritten if there's more
10751                                          * than 1 demuxer/parser
10752                                          */
10753                                         LOGD("plugged element is demuxer. take it\n");
10754                                         mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
10755                                         mainbin[MMPLAYER_M_DEMUX].gst = new_element;
10756
10757                                         /*Added for multi audio support */
10758                                         if (g_strrstr(klass, "Demux")) {
10759                                                 mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
10760                                                 mainbin[MMPLAYER_M_DEMUX_EX].gst = new_element;
10761
10762                                                 /* NOTE : workaround for bug in mpegtsdemux since doesn't emit
10763                                                 no-more-pad signal. this may cause wrong content attributes at PAUSED state
10764                                                 this code should be removed after mpegtsdemux is fixed */
10765                                                 if (g_strrstr(GST_OBJECT_NAME(factory), "mpegtsdemux")) {
10766                                                         LOGW("force no-more-pad to TRUE since mpegtsdemux os not giving no-more-pad signal. content attributes may wrong");
10767                                                         player->no_more_pad = TRUE;
10768                                                 }
10769                                         }
10770                                         if (g_strrstr(name_to_plug, "asfdemux")) // to support trust-zone only
10771                                                 g_object_set(mainbin[MMPLAYER_M_DEMUX_EX].gst, "file-location", player->profile.uri, NULL);
10772                                 } else if (g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player, pad)) {
10773                                         if (mainbin[MMPLAYER_M_DEC1].gst == NULL) {
10774                                                 LOGD("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
10775                                                 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
10776                                                 mainbin[MMPLAYER_M_DEC1].gst = new_element;
10777                                         } else if (mainbin[MMPLAYER_M_DEC2].gst == NULL) {
10778                                                 LOGD("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
10779                                                 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
10780                                                 mainbin[MMPLAYER_M_DEC2].gst = new_element;
10781                                         }
10782                                         /* NOTE : IF one codec is found, add it to supported_codec and remove from
10783                                          * missing plugin. Both of them are used to check what's supported codec
10784                                          * before returning result of play start. And, missing plugin should be
10785                                          * updated here for multi track files.
10786                                          */
10787                                         if (g_str_has_prefix(mime, "video")) {
10788                                                 GstPad *src_pad = NULL;
10789                                                 GstPadTemplate *pad_templ = NULL;
10790                                                 GstCaps *caps = NULL;
10791                                                 gchar *caps_str = NULL;
10792
10793                                                 LOGD("found VIDEO decoder\n");
10794                                                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
10795                                                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
10796
10797                                                 src_pad = gst_element_get_static_pad(new_element, "src");
10798                                                 pad_templ = gst_pad_get_pad_template(src_pad);
10799                                                 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
10800
10801                                                 caps_str = gst_caps_to_string(caps);
10802
10803                                                 /* clean */
10804                                                 MMPLAYER_FREEIF(caps_str);
10805                                                 gst_object_unref(src_pad);
10806                                         } else if (g_str_has_prefix(mime, "audio")) {
10807                                                 LOGD("found AUDIO decoder\n");
10808                                                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
10809                                                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
10810                                         }
10811                                 }
10812
10813                                 if (!__mmplayer_close_link(player, pad, new_element,
10814                                                         name_template, gst_element_factory_get_static_pad_templates(factory))) {
10815                                         MMPLAYER_FREEIF(name_template);
10816                                         if (player->keep_detecting_vcodec)
10817                                                 continue;
10818
10819                                         /* Link is failed even though a supportable codec is found. */
10820                                         __mmplayer_check_not_supported_codec(player, klass, mime);
10821
10822                                         LOGE("failed to call _close_link\n");
10823                                         return FALSE;
10824                                 }
10825
10826                                 MMPLAYER_FREEIF(name_template);
10827                                 return TRUE;
10828                         }
10829
10830                         gst_caps_unref(res);
10831                         break;
10832                 }
10833         }
10834
10835         /* There is no available codec. */
10836         __mmplayer_check_not_supported_codec(player, klass, mime);
10837
10838         MMPLAYER_FLEAVE();
10839         return FALSE;
10840
10841 ERROR:
10842         /* release */
10843         if (queue)
10844                 gst_object_unref(queue);
10845
10846         if (queue_pad)
10847                 gst_object_unref(queue_pad);
10848
10849         if (element)
10850                 gst_object_unref(element);
10851
10852         return FALSE;
10853 }
10854
10855
10856 static int
10857 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
10858 {
10859         MMPLAYER_FENTER();
10860
10861         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
10862         MMPLAYER_RETURN_VAL_IF_FAIL(mime, MM_ERROR_INVALID_ARGUMENT);
10863
10864         LOGD("class : %s, mime : %s \n", factory_class, mime);
10865
10866         /* add missing plugin */
10867         /* NOTE : msl should check missing plugin for image mime type.
10868          * Some motion jpeg clips can have playable audio track.
10869          * So, msl have to play audio after displaying popup written video format not supported.
10870          */
10871         if (!(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)) {
10872                 if (!(player->can_support_codec | player->videodec_linked | player->audiodec_linked)) {
10873                         LOGD("not found demuxer\n");
10874                         player->not_found_demuxer = TRUE;
10875                         player->unlinked_demuxer_mime = g_strdup_printf("%s", mime);
10876
10877                         goto DONE;
10878                 }
10879         }
10880
10881         if (!g_strrstr(factory_class, "Demuxer")) {
10882                 if ((g_str_has_prefix(mime, "video")) || (g_str_has_prefix(mime, "image"))) {
10883                         LOGD("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
10884                                 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
10885
10886                         /* check that clip have multi tracks or not */
10887                         if ((player->can_support_codec & FOUND_PLUGIN_VIDEO) && (player->videodec_linked)) {
10888                                 LOGD("video plugin is already linked\n");
10889                         } else {
10890                                 LOGW("add VIDEO to missing plugin\n");
10891                                 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
10892                         }
10893                 } else if (g_str_has_prefix(mime, "audio")) {
10894                         if ((player->can_support_codec & FOUND_PLUGIN_AUDIO) && (player->audiodec_linked)) {
10895                                 LOGD("audio plugin is already linked\n");
10896                         } else {
10897                                 LOGW("add AUDIO to missing plugin\n");
10898                                 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
10899                         }
10900                 }
10901         }
10902
10903 DONE:
10904         MMPLAYER_FLEAVE();
10905
10906         return MM_ERROR_NONE;
10907 }
10908
10909
10910 static void
10911 __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
10912 {
10913         mm_player_t* player = (mm_player_t*)data;
10914
10915         MMPLAYER_FENTER();
10916
10917         MMPLAYER_RETURN_IF_FAIL(player);
10918
10919         /* remove fakesink. */
10920         if (!__mmplayer_gst_remove_fakesink(player,
10921                                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK])) {
10922                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
10923                  * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
10924                  * source element are not same. To overcome this situation, this function will called
10925                  * several places and several times. Therefore, this is not an error case.
10926                  */
10927                 return;
10928         }
10929
10930         LOGD("pipeline has completely constructed\n");
10931
10932         if ((player->ini.async_start) &&
10933                 (player->msg_posted == FALSE) &&
10934                 (player->cmd >= MMPLAYER_COMMAND_START))
10935                 __mmplayer_handle_missed_plugin(player);
10936
10937         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-complete");
10938 }
10939
10940 static gboolean
10941 __mmplayer_verify_next_play_path(mm_player_t *player)
10942 {
10943         MMHandleType attrs = 0;
10944         MMPlayerParseProfile profile;
10945         gint uri_idx = 0, check_cnt = 0;
10946         char *uri = NULL;
10947         gint mode = MM_PLAYER_PD_MODE_NONE;
10948         gint video = 0;
10949         gint count = 0;
10950         gint gapless = 0;
10951         guint num_of_list = 0;
10952
10953         MMPLAYER_FENTER();
10954
10955         LOGD("checking for gapless play");
10956
10957         if (player->pipeline->textbin) {
10958                 LOGE("subtitle path is enabled. gapless play is not supported.\n");
10959                 goto ERROR;
10960         }
10961
10962         attrs = MMPLAYER_GET_ATTRS(player);
10963         if (!attrs) {
10964                 LOGE("fail to get attributes.\n");
10965                 goto ERROR;
10966         }
10967
10968         mm_attrs_get_int_by_name(attrs, "content_video_found", &video);
10969
10970 #ifdef TIZEN_TV
10971         /* gapless playback is not supported in case of video at TV profile. */
10972         if (video) {
10973                 LOGW("not support video gapless playback");
10974                 goto ERROR;
10975         }
10976 #endif
10977
10978         if (mm_attrs_get_int_by_name(attrs, "pd_mode", &mode) == MM_ERROR_NONE) {
10979                 if (mode == TRUE) {
10980                         LOGW("pd mode\n");
10981                         goto ERROR;
10982                 }
10983         }
10984
10985         if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
10986                 LOGE("can not get play count\n");
10987
10988         if (mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless) != MM_ERROR_NONE)
10989                 LOGE("can not get gapless mode\n");
10990
10991         if (video && !gapless) {
10992                 LOGW("not enabled video gapless playback");
10993                 goto ERROR;
10994         }
10995
10996         if ((count == -1 || count > 1)) /* enable gapless when looping or repeat */
10997                 gapless = 1;
10998
10999         if (!gapless) {
11000                 LOGW("gapless is disabled\n");  /* FIXME: playlist(without gapless) is not implemented. */
11001                 goto ERROR;
11002         }
11003
11004         num_of_list = g_list_length(player->uri_info.uri_list);
11005
11006         LOGD("repeat count = %d, num_of_list = %d\n", count, num_of_list);
11007
11008         if (num_of_list == 0) {
11009                 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE) {
11010                         LOGE("can not get profile_uri\n");
11011                         goto ERROR;
11012                 }
11013
11014                 if (!uri) {
11015                         LOGE("uri list is empty.\n");
11016                         goto ERROR;
11017                 }
11018
11019                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
11020                 LOGD("add original path : %s ", uri);
11021
11022                 num_of_list = 1;
11023                 uri = NULL;
11024         }
11025
11026         uri_idx = player->uri_info.uri_idx;
11027
11028         while (TRUE) {
11029                 check_cnt++;
11030
11031                 if (check_cnt > num_of_list) {
11032                         LOGE("there is no valid uri.");
11033                         goto ERROR;
11034                 }
11035
11036                 LOGD("uri idx : %d / %d\n", uri_idx, num_of_list);
11037
11038                 if (uri_idx < num_of_list-1) {
11039                         uri_idx++;
11040                 } else {
11041                         if ((count <= 1) && (count != -1)) {
11042                                 LOGD("no repeat.");
11043                                 goto ERROR;
11044                         } else if (count > 1) {
11045                                 /* decrease play count */
11046                                 /* we succeeded to rewind. update play count and then wait for next EOS */
11047                                 count--;
11048
11049                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
11050
11051                                 /* commit attribute */
11052                                 if (mmf_attrs_commit(attrs))
11053                                         LOGE("failed to commit attribute\n");
11054                         }
11055
11056                         /* count < 0 : repeat continually */
11057                         uri_idx = 0;
11058                 }
11059
11060                 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
11061                 LOGD("uri idx : %d, uri = %s\n", uri_idx, uri);
11062
11063                 if (uri == NULL) {
11064                         LOGW("next uri does not exist\n");
11065                         continue;
11066                 }
11067
11068                 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE) {
11069                         LOGE("failed to parse profile\n");
11070                         continue;
11071                 }
11072
11073                 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
11074                         (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP)) {
11075                         LOGW("uri type is not supported(%d).", profile.uri_type);
11076                         continue;
11077                 }
11078
11079                 break;
11080         }
11081
11082         player->uri_info.uri_idx = uri_idx;
11083         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
11084
11085         if (mmf_attrs_commit(player->attrs)) {
11086                 LOGE("failed to commit.\n");
11087                 goto ERROR;
11088         }
11089
11090         LOGD("next uri %s(%d)\n", uri, uri_idx);
11091
11092         return TRUE;
11093
11094 ERROR:
11095
11096         LOGE("unable to play next path. EOS will be posted soon.\n");
11097         return FALSE;
11098 }
11099
11100 static void
11101 __mmplayer_initialize_next_play(mm_player_t *player)
11102 {
11103         int i;
11104
11105         MMPLAYER_FENTER();
11106
11107         player->smooth_streaming = FALSE;
11108         player->videodec_linked = 0;
11109         player->audiodec_linked = 0;
11110         player->videosink_linked = 0;
11111         player->audiosink_linked = 0;
11112         player->textsink_linked = 0;
11113         player->is_external_subtitle_present = FALSE;
11114         player->is_external_subtitle_added_now = FALSE;
11115         player->not_supported_codec = MISSING_PLUGIN_NONE;
11116         player->can_support_codec = FOUND_PLUGIN_NONE;
11117         player->pending_seek.is_pending = FALSE;
11118         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
11119         player->pending_seek.pos = 0;
11120         player->msg_posted = FALSE;
11121         player->has_many_types = FALSE;
11122         player->no_more_pad = FALSE;
11123         player->not_found_demuxer = 0;
11124         player->doing_seek = FALSE;
11125         player->max_audio_channels = 0;
11126         player->is_subtitle_force_drop = FALSE;
11127         player->play_subtitle = FALSE;
11128         player->use_textoverlay = FALSE;
11129         player->adjust_subtitle_pos = 0;
11130
11131         player->updated_bitrate_count = 0;
11132         player->total_bitrate = 0;
11133         player->updated_maximum_bitrate_count = 0;
11134         player->total_maximum_bitrate = 0;
11135
11136         _mmplayer_track_initialize(player);
11137         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
11138
11139         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
11140                 player->bitrate[i] = 0;
11141                 player->maximum_bitrate[i] = 0;
11142         }
11143
11144         if (player->v_stream_caps) {
11145                 gst_caps_unref(player->v_stream_caps);
11146                 player->v_stream_caps = NULL;
11147         }
11148
11149         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
11150         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
11151
11152         /* clean found parsers */
11153         if (player->parsers) {
11154                 GList *parsers = player->parsers;
11155                 for (; parsers; parsers = g_list_next(parsers)) {
11156                         gchar *name = parsers->data;
11157                         MMPLAYER_FREEIF(name);
11158                 }
11159                 g_list_free(player->parsers);
11160                 player->parsers = NULL;
11161         }
11162
11163         /* clean found audio decoders */
11164         if (player->audio_decoders) {
11165                 GList *a_dec = player->audio_decoders;
11166                 for (; a_dec; a_dec = g_list_next(a_dec)) {
11167                         gchar *name = a_dec->data;
11168                         MMPLAYER_FREEIF(name);
11169                 }
11170                 g_list_free(player->audio_decoders);
11171                 player->audio_decoders = NULL;
11172         }
11173
11174         MMPLAYER_FLEAVE();
11175 }
11176
11177 static void
11178 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
11179 {
11180         MMPlayerGstElement *mainbin = NULL;
11181         MMMessageParamType msg_param = {0,};
11182         GstElement *element = NULL;
11183         MMHandleType attrs = 0;
11184         char *uri = NULL;
11185         enum MainElementID elemId = MMPLAYER_M_NUM;
11186
11187         MMPLAYER_FENTER();
11188
11189         if ((player == NULL) ||
11190                 (player->pipeline == NULL) ||
11191                 (player->pipeline->mainbin == NULL)) {
11192                 LOGE("player is null.\n");
11193                 goto ERROR;
11194         }
11195
11196         mainbin = player->pipeline->mainbin;
11197         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
11198
11199         attrs = MMPLAYER_GET_ATTRS(player);
11200         if (!attrs) {
11201                 LOGE("fail to get attributes.\n");
11202                 goto ERROR;
11203         }
11204
11205         /* Initialize Player values */
11206         __mmplayer_initialize_next_play(player);
11207
11208         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
11209
11210         if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE) {
11211                 LOGE("failed to parse profile\n");
11212                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
11213                 goto ERROR;
11214         }
11215
11216         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
11217                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player))) {
11218                 LOGE("it's dash or hls. not support.");
11219                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
11220                 goto ERROR;
11221         }
11222
11223         /* setup source */
11224         switch (player->profile.uri_type) {
11225         /* file source */
11226         case MM_PLAYER_URI_TYPE_FILE:
11227         {
11228                 LOGD("using filesrc for 'file://' handler.\n");
11229                 if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
11230                         LOGE("failed to get storage info");
11231                         break;
11232                 }
11233
11234                 element = gst_element_factory_make("filesrc", "source");
11235
11236                 if (!element) {
11237                         LOGE("failed to create filesrc\n");
11238                         break;
11239                 }
11240
11241                 g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
11242                 break;
11243         }
11244         case MM_PLAYER_URI_TYPE_URL_HTTP:
11245         {
11246                 gchar *user_agent, *proxy, *cookies, **cookie_list;
11247                 gint http_timeout = DEFAULT_HTTP_TIMEOUT;
11248                 user_agent = proxy = cookies = NULL;
11249                 cookie_list = NULL;
11250
11251                 element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
11252                 if (!element) {
11253                         LOGE("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
11254                         break;
11255                 }
11256                 LOGD("using http streamming source [%s].\n", player->ini.httpsrc_element);
11257
11258                 /* get attribute */
11259                 mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
11260                 mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
11261                 mm_attrs_get_string_by_name(attrs, "streaming_proxy", &proxy);
11262                 mm_attrs_get_int_by_name(attrs, "streaming_timeout", &http_timeout);
11263
11264                 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
11265                         (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT)) {
11266                         LOGD("get timeout from ini\n");
11267                         http_timeout = player->ini.http_timeout;
11268                 }
11269
11270                 /* get attribute */
11271                 SECURE_LOGD("location : %s\n", player->profile.uri);
11272                 SECURE_LOGD("cookies : %s\n", cookies);
11273                 SECURE_LOGD("proxy : %s\n", proxy);
11274                 SECURE_LOGD("user_agent :  %s\n", user_agent);
11275                 LOGD("timeout : %d\n", http_timeout);
11276
11277                 /* setting property to streaming source */
11278                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
11279                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
11280                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
11281
11282                 /* check if prosy is vailid or not */
11283                 if (util_check_valid_url(proxy))
11284                         g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
11285                 /* parsing cookies */
11286                 if ((cookie_list = util_get_cookie_list((const char*)cookies)))
11287                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
11288                 if (user_agent)
11289                         g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
11290                 break;
11291         }
11292         default:
11293                 LOGE("not support uri type %d\n", player->profile.uri_type);
11294                 break;
11295         }
11296
11297         if (!element) {
11298                 LOGE("no source element was created.\n");
11299                 goto ERROR;
11300         }
11301
11302         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
11303                 LOGE("failed to add source element to pipeline\n");
11304                 gst_object_unref(GST_OBJECT(element));
11305                 element = NULL;
11306                 goto ERROR;
11307         }
11308
11309         /* take source element */
11310         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
11311         mainbin[MMPLAYER_M_SRC].gst = element;
11312
11313         element = NULL;
11314
11315         if (MMPLAYER_IS_HTTP_STREAMING(player)) {
11316                 if (player->streamer == NULL) {
11317                         player->streamer = __mm_player_streaming_create();
11318                         __mm_player_streaming_initialize(player->streamer);
11319                 }
11320
11321                 elemId = MMPLAYER_M_TYPEFIND;
11322                 element = gst_element_factory_make("typefind", "typefinder");
11323                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
11324                         G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
11325         } else {
11326                 elemId = MMPLAYER_M_AUTOPLUG;
11327                 element = __mmplayer_create_decodebin(player);
11328         }
11329
11330         /* check autoplug element is OK */
11331         if (!element) {
11332                 LOGE("can not create element(%d)\n", elemId);
11333                 goto ERROR;
11334         }
11335
11336         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
11337                 LOGE("failed to add sinkbin to pipeline\n");
11338                 gst_object_unref(GST_OBJECT(element));
11339                 element = NULL;
11340                 goto ERROR;
11341         }
11342
11343         mainbin[elemId].id = elemId;
11344         mainbin[elemId].gst = element;
11345
11346         if (gst_element_link(mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE) {
11347                 LOGE("Failed to link src - autoplug(or typefind)\n");
11348                 goto ERROR;
11349         }
11350
11351         if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
11352                 LOGE("Failed to change state of src element\n");
11353                 goto ERROR;
11354         }
11355
11356         if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
11357                 if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
11358                         LOGE("Failed to change state of decodebin\n");
11359                         goto ERROR;
11360                 }
11361         } else {
11362                 if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {
11363                         LOGE("Failed to change state of src element\n");
11364                         goto ERROR;
11365                 }
11366         }
11367
11368         player->gapless.stream_changed = TRUE;
11369         player->gapless.running = TRUE;
11370         MMPLAYER_FLEAVE();
11371         return;
11372
11373 ERROR:
11374         if (player) {
11375                 MMPLAYER_PLAYBACK_UNLOCK(player);
11376
11377                 if (!player->msg_posted) {
11378                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
11379                         player->msg_posted = TRUE;
11380                 }
11381         }
11382         return;
11383 }
11384
11385 static gboolean
11386 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
11387 {
11388         mm_player_selector_t *selector = &player->selector[type];
11389         MMPlayerGstElement *sinkbin = NULL;
11390         enum MainElementID selectorId = MMPLAYER_M_NUM;
11391         enum MainElementID sinkId = MMPLAYER_M_NUM;
11392         GstPad *srcpad = NULL;
11393         GstPad *sinkpad = NULL;
11394         gboolean send_notice = FALSE;
11395
11396         MMPLAYER_FENTER();
11397         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11398
11399         LOGD("type %d", type);
11400
11401         switch (type) {
11402         case MM_PLAYER_TRACK_TYPE_AUDIO:
11403                 selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
11404                 sinkId = MMPLAYER_A_BIN;
11405                 sinkbin = player->pipeline->audiobin;
11406                 break;
11407         case MM_PLAYER_TRACK_TYPE_VIDEO:
11408                 selectorId = MMPLAYER_M_V_INPUT_SELECTOR;
11409                 sinkId = MMPLAYER_V_BIN;
11410                 sinkbin = player->pipeline->videobin;
11411                 send_notice = TRUE;
11412                 break;
11413         case MM_PLAYER_TRACK_TYPE_TEXT:
11414                 selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
11415                 sinkId = MMPLAYER_T_BIN;
11416                 sinkbin = player->pipeline->textbin;
11417                 break;
11418         default:
11419                 LOGE("requested type is not supportable");
11420                 return FALSE;
11421                 break;
11422         }
11423
11424         if (player->pipeline->mainbin[selectorId].gst) {
11425                 gint n;
11426
11427                 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
11428
11429                 if (selector->event_probe_id != 0)
11430                         gst_pad_remove_probe(srcpad, selector->event_probe_id);
11431                 selector->event_probe_id = 0;
11432
11433                 if ((sinkbin) && (sinkbin[sinkId].gst)) {
11434                         sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
11435
11436                         if (srcpad && sinkpad) {
11437                                 /* after getting drained signal there is no data flows, so no need to do pad_block */
11438                                 LOGD("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
11439                                 gst_pad_unlink(srcpad, sinkpad);
11440
11441                                 /* send custom event to sink pad to handle it at video sink */
11442                                 if (send_notice) {
11443                                         LOGD("send custom event to sinkpad");
11444                                         GstStructure *s = gst_structure_new_empty("application/flush-buffer");
11445                                         GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, s);
11446                                         gst_pad_send_event(sinkpad, event);
11447                                 }
11448                         }
11449
11450                         gst_object_unref(sinkpad);
11451                         sinkpad = NULL;
11452                 }
11453                 gst_object_unref(srcpad);
11454                 srcpad = NULL;
11455
11456                 LOGD("selector release");
11457
11458                 /* release and unref requests pad from the selector */
11459                 for (n = 0; n < selector->channels->len; n++) {
11460                         GstPad *sinkpad = g_ptr_array_index(selector->channels, n);
11461                         gst_element_release_request_pad((player->pipeline->mainbin[selectorId].gst), sinkpad);
11462                 }
11463                 g_ptr_array_set_size(selector->channels, 0);
11464
11465                 gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
11466                 gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
11467
11468                 player->pipeline->mainbin[selectorId].gst = NULL;
11469                 selector = NULL;
11470         }
11471
11472         return TRUE;
11473 }
11474
11475 static void
11476 __mmplayer_deactivate_old_path(mm_player_t *player)
11477 {
11478         MMPLAYER_FENTER();
11479         MMPLAYER_RETURN_IF_FAIL(player);
11480
11481         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
11482                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
11483                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
11484                 LOGE("deactivate selector error");
11485                 goto ERROR;
11486         }
11487
11488         _mmplayer_track_destroy(player);
11489         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
11490
11491         if (player->streamer) {
11492                 __mm_player_streaming_deinitialize(player->streamer);
11493                 __mm_player_streaming_destroy(player->streamer);
11494                 player->streamer = NULL;
11495         }
11496
11497         MMPLAYER_PLAYBACK_LOCK(player);
11498         MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
11499
11500         MMPLAYER_FLEAVE();
11501         return;
11502
11503 ERROR:
11504
11505         if (!player->msg_posted) {
11506                 MMMessageParamType msg = {0,};
11507
11508                 /*post error*/
11509                 msg.code = MM_ERROR_PLAYER_INTERNAL;
11510                 LOGE("next_uri_play> deactivate error");
11511
11512                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
11513                 player->msg_posted = TRUE;
11514         }
11515         return;
11516 }
11517
11518 int _mmplayer_set_file_buffering_path(MMHandleType hplayer, const char* file_path)
11519 {
11520         int result = MM_ERROR_NONE;
11521         mm_player_t* player = (mm_player_t*) hplayer;
11522         MMPLAYER_FENTER();
11523
11524         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
11525
11526         if (file_path) {
11527                 player->http_file_buffering_path = (gchar*)file_path;
11528                 LOGD("temp file path: %s\n", player->http_file_buffering_path);
11529         }
11530         MMPLAYER_FLEAVE();
11531         return result;
11532 }
11533
11534 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
11535 {
11536         int result = MM_ERROR_NONE;
11537         mm_player_t* player = (mm_player_t*) hplayer;
11538         MMPLAYER_FENTER();
11539
11540         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
11541
11542         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
11543         if (mmf_attrs_commit(player->attrs)) {
11544                 LOGE("failed to commit the original uri.\n");
11545                 result = MM_ERROR_PLAYER_INTERNAL;
11546         } else {
11547                 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
11548                         LOGE("failed to add the original uri in the uri list.\n");
11549         }
11550
11551         MMPLAYER_FLEAVE();
11552         return result;
11553 }
11554
11555 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
11556 {
11557         mm_player_t* player = (mm_player_t*) hplayer;
11558         guint num_of_list = 0;
11559
11560         MMPLAYER_FENTER();
11561
11562         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
11563         MMPLAYER_RETURN_VAL_IF_FAIL(uri, MM_ERROR_INVALID_ARGUMENT);
11564
11565         if (player->pipeline && player->pipeline->textbin) {
11566                 LOGE("subtitle path is enabled.\n");
11567                 return MM_ERROR_PLAYER_INVALID_STATE;
11568         }
11569
11570         num_of_list = g_list_length(player->uri_info.uri_list);
11571
11572         if (is_first_path == TRUE) {
11573                 if (num_of_list == 0) {
11574                         player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
11575                         LOGD("add original path : %s", uri);
11576                 } else {
11577                         player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
11578                         player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
11579
11580                         LOGD("change original path : %s", uri);
11581                 }
11582         } else {
11583                 MMHandleType attrs = 0;
11584                 attrs = MMPLAYER_GET_ATTRS(player);
11585
11586                 if (num_of_list == 0) {
11587                         char *original_uri = NULL;
11588
11589                         if (attrs) {
11590                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
11591
11592                                 if (!original_uri) {
11593                                         LOGE("there is no original uri.");
11594                                         return MM_ERROR_PLAYER_INVALID_STATE;
11595                                 }
11596
11597                                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
11598                                 player->uri_info.uri_idx = 0;
11599
11600                                 LOGD("add original path at first : %s(%d)", original_uri);
11601                         }
11602                 }
11603
11604                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
11605                 LOGD("add new path : %s(total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
11606         }
11607
11608         MMPLAYER_FLEAVE();
11609         return MM_ERROR_NONE;
11610 }
11611
11612 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
11613 {
11614         mm_player_t* player = (mm_player_t*) hplayer;
11615         char *next_uri = NULL;
11616         guint num_of_list = 0;
11617
11618         MMPLAYER_FENTER();
11619         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
11620
11621         num_of_list = g_list_length(player->uri_info.uri_list);
11622
11623         if (num_of_list > 0) {
11624                 gint uri_idx = player->uri_info.uri_idx;
11625
11626                 if (uri_idx < num_of_list-1)
11627                         uri_idx++;
11628                 else
11629                         uri_idx = 0;
11630
11631                 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
11632                 LOGE("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
11633
11634                 *uri = g_strdup(next_uri);
11635         }
11636
11637         MMPLAYER_FLEAVE();
11638         return MM_ERROR_NONE;
11639 }
11640
11641 static void
11642 __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad,
11643 GstCaps *caps, gpointer data)
11644 {
11645         mm_player_t* player = (mm_player_t*)data;
11646         const gchar* klass = NULL;
11647         const gchar* mime = NULL;
11648         gchar* caps_str = NULL;
11649
11650         klass = gst_element_factory_get_metadata(gst_element_get_factory(elem), GST_ELEMENT_METADATA_KLASS);
11651         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
11652         caps_str = gst_caps_to_string(caps);
11653
11654         LOGW("unknown type of caps : %s from %s",
11655                                         caps_str, GST_ELEMENT_NAME(elem));
11656
11657         MMPLAYER_FREEIF(caps_str);
11658
11659         /* There is no available codec. */
11660         __mmplayer_check_not_supported_codec(player, klass, mime);
11661 }
11662
11663 static gboolean
11664 __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad,
11665 GstCaps * caps,  gpointer data)
11666 {
11667         mm_player_t* player = (mm_player_t*)data;
11668         const char* mime = NULL;
11669         gboolean ret = TRUE;
11670
11671         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
11672         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
11673
11674         if (g_str_has_prefix(mime, "audio")) {
11675                 GstStructure* caps_structure = NULL;
11676                 gint samplerate = 0;
11677                 gint channels = 0;
11678                 gchar *caps_str = NULL;
11679
11680                 caps_structure = gst_caps_get_structure(caps, 0);
11681                 gst_structure_get_int(caps_structure, "rate", &samplerate);
11682                 gst_structure_get_int(caps_structure, "channels", &channels);
11683
11684                 if ((channels > 0 && samplerate == 0)) {
11685                         LOGD("exclude audio...");
11686                         ret = FALSE;
11687                 }
11688
11689                 caps_str = gst_caps_to_string(caps);
11690                 /* set it directly because not sent by TAG */
11691                 if (g_strrstr(caps_str, "mobile-xmf"))
11692                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
11693                 MMPLAYER_FREEIF(caps_str);
11694         } else if (g_str_has_prefix(mime, "video") && !player->ini.video_playback_supported) {
11695                 MMMessageParamType msg_param;
11696                 memset(&msg_param, 0, sizeof(MMMessageParamType));
11697                 msg_param.code = MM_ERROR_NOT_SUPPORT_API;
11698                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
11699                 LOGD("video file is not supported on this device");
11700                 ret = FALSE;
11701         } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
11702                 LOGD("already video linked");
11703                 ret = FALSE;
11704         } else {
11705                 LOGD("found new stream");
11706         }
11707
11708         return ret;
11709 }
11710
11711 static gint
11712 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad,
11713 GstCaps* caps, GstElementFactory* factory, gpointer data)
11714 {
11715         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
11716          We are defining our own and will be removed when it actually exposed */
11717         typedef enum {
11718                 GST_AUTOPLUG_SELECT_TRY,
11719                 GST_AUTOPLUG_SELECT_EXPOSE,
11720                 GST_AUTOPLUG_SELECT_SKIP
11721         } GstAutoplugSelectResult;
11722
11723         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
11724         mm_player_t* player = (mm_player_t*)data;
11725
11726         gchar* factory_name = NULL;
11727         gchar* caps_str = NULL;
11728         const gchar* klass = NULL;
11729         gint idx = 0;
11730
11731         factory_name = GST_OBJECT_NAME(factory);
11732         klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
11733         caps_str = gst_caps_to_string(caps);
11734
11735         LOGD("found new element [%s] to link", factory_name);
11736
11737         /* store type string */
11738         if (player->type == NULL) {
11739                 player->type = gst_caps_to_string(caps);
11740                 __mmplayer_update_content_type_info(player);
11741         }
11742
11743         /* filtering exclude keyword */
11744         for (idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++) {
11745                 if (strstr(factory_name, player->ini.exclude_element_keyword[idx])) {
11746                         LOGW("skipping [%s] by exculde keyword [%s]\n",
11747                         factory_name, player->ini.exclude_element_keyword[idx]);
11748
11749                         // NOTE : does we need to check n_value against the number of item selected?
11750                         result = GST_AUTOPLUG_SELECT_SKIP;
11751                         goto DONE;
11752                 }
11753         }
11754
11755         /* exclude webm format */
11756         /* NOTE : MSL have to post MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT
11757          * because webm format is not supportable.
11758          * If webm is disabled in "autoplug-continue", there is no state change
11759          * failure or error because the decodebin will expose the pad directly.
11760          * It make MSL invoke _prepare_async_callback.
11761          * So, we need to disable webm format in "autoplug-select" */
11762         if (caps_str && strstr(caps_str, "webm")) {
11763                 LOGW("webm is not supported");
11764                 result = GST_AUTOPLUG_SELECT_SKIP;
11765                 goto DONE;
11766         }
11767
11768         /* check factory class for filtering */
11769         /* NOTE : msl don't need to use image plugins.
11770          * So, those plugins should be skipped for error handling.
11771          */
11772         if (g_strrstr(klass, "Codec/Decoder/Image")) {
11773                 LOGD("skipping [%s] by not required\n", factory_name);
11774                 result = GST_AUTOPLUG_SELECT_SKIP;
11775                 goto DONE;
11776         }
11777
11778         if ((MMPLAYER_IS_MS_BUFF_SRC(player)) &&
11779                 (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser")))) {
11780                 // TO CHECK : subtitle if needed, add subparse exception.
11781                 LOGD("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
11782                 result = GST_AUTOPLUG_SELECT_SKIP;
11783                 goto DONE;
11784         }
11785
11786         if (g_strrstr(factory_name, "mpegpsdemux")) {
11787                 LOGD("skipping PS container - not support\n");
11788                 result = GST_AUTOPLUG_SELECT_SKIP;
11789                 goto DONE;
11790         }
11791
11792         if (g_strrstr(factory_name, "mssdemux"))
11793                 player->smooth_streaming = TRUE;
11794
11795         /* check ALP Codec can be used or not */
11796         if ((g_strrstr(klass, "Codec/Decoder/Audio"))) {
11797                 GstStructure* str = NULL;
11798                 gint channels = 0;
11799
11800                 str = gst_caps_get_structure(caps, 0);
11801                 if (str) {
11802                         gst_structure_get_int(str, "channels", &channels);
11803
11804                         LOGD("check audio ch : %d %d\n", player->max_audio_channels, channels);
11805                         if (player->max_audio_channels < channels)
11806                                 player->max_audio_channels = channels;
11807                 }
11808                 /* set stream information */
11809                 if (!player->audiodec_linked)
11810                         __mmplayer_set_audio_attrs(player, caps);
11811         } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
11812                 if ((strlen(player->ini.videocodec_element_hw) > 0) &&
11813                         (g_strrstr(factory_name, player->ini.videocodec_element_hw))) {
11814                         /* prepare resource manager for video decoder */
11815                         MMPlayerResourceState resource_state = RESOURCE_STATE_NONE;
11816
11817                         if (_mmplayer_resource_manager_get_state(&player->resource_manager, &resource_state) == MM_ERROR_NONE) {
11818                                 /* prepare resource manager for video decoder */
11819                                 if ((resource_state >= RESOURCE_STATE_INITIALIZED) && (resource_state < RESOURCE_STATE_ACQUIRED)) {
11820                                         if (_mmplayer_resource_manager_prepare(&player->resource_manager, RESOURCE_TYPE_VIDEO_DECODER)
11821                                                 != MM_ERROR_NONE) {
11822                                                 LOGW("could not prepare for video_decoder resource, skip it.");
11823                                                 result = GST_AUTOPLUG_SELECT_SKIP;
11824                                                 goto DONE;
11825                                         }
11826                                 }
11827                         }
11828                 }
11829         }
11830
11831         if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
11832                 (g_strrstr(klass, "Codec/Decoder/Video"))) {
11833                 gint stype = 0;
11834                 gint width = 0;
11835                 GstStructure *str = NULL;
11836                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
11837
11838                 /* don't make video because of not required */
11839                 if ((stype == MM_DISPLAY_SURFACE_NULL) &&
11840                         (player->set_mode.media_packet_video_stream == FALSE)) {
11841                         LOGD("no video because it's not required. -> return expose");
11842                         result = GST_AUTOPLUG_SELECT_EXPOSE;
11843                         goto DONE;
11844                 }
11845
11846                 /* get w/h for omx state-tune */
11847                 str = gst_caps_get_structure(caps, 0);
11848                 gst_structure_get_int(str, "width", &width);
11849
11850                 if (width != 0) {
11851                         if (player->v_stream_caps) {
11852                                 gst_caps_unref(player->v_stream_caps);
11853                                 player->v_stream_caps = NULL;
11854                         }
11855
11856                         player->v_stream_caps = gst_caps_copy(caps);
11857                         LOGD("take caps for video state tune");
11858                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
11859                 }
11860         }
11861
11862         if (g_strrstr(klass, "Decoder")) {
11863                 const char* mime = NULL;
11864                 mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
11865
11866                 if (g_str_has_prefix(mime, "video")) {
11867                         // __mmplayer_check_video_zero_cpoy(player, factory);
11868
11869                         player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
11870                         player->can_support_codec |= FOUND_PLUGIN_VIDEO;
11871
11872                         player->videodec_linked = 1;
11873                 } else if (g_str_has_prefix(mime, "audio")) {
11874                         player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
11875                         player->can_support_codec |= FOUND_PLUGIN_AUDIO;
11876
11877                         player->audiodec_linked = 1;
11878                 }
11879         }
11880
11881 DONE:
11882         MMPLAYER_FREEIF(caps_str);
11883
11884         return result;
11885 }
11886
11887
11888 #if 0
11889 static GValueArray*
11890 __mmplayer_gst_decode_autoplug_factories(GstElement *bin,  GstPad* pad,
11891 GstCaps * caps,  gpointer data)
11892 {
11893         //mm_player_t* player = (mm_player_t*)data;
11894
11895         LOGD("decodebin is requesting factories for caps [%s] from element[%s]",
11896         gst_caps_to_string(caps),
11897         GST_ELEMENT_NAME(GST_PAD_PARENT(pad)));
11898
11899         return NULL;
11900 }
11901 #endif
11902
11903 static void
11904 __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad,
11905 gpointer data) // @
11906 {
11907         //mm_player_t* player = (mm_player_t*)data;
11908         GstCaps* caps = NULL;
11909
11910         LOGD("[Decodebin2] pad-removed signal\n");
11911
11912         caps = gst_pad_query_caps(new_pad, NULL);
11913         if (caps) {
11914                 gchar* caps_str = NULL;
11915                 caps_str = gst_caps_to_string(caps);
11916
11917                 LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem));
11918
11919                 MMPLAYER_FREEIF(caps_str);
11920         }
11921 }
11922
11923 static void
11924 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
11925 {
11926         mm_player_t* player = (mm_player_t*)data;
11927         GstIterator *iter = NULL;
11928         GValue item = { 0, };
11929         GstPad *pad = NULL;
11930         gboolean done = FALSE;
11931         gboolean is_all_drained = TRUE;
11932
11933         MMPLAYER_FENTER();
11934         MMPLAYER_RETURN_IF_FAIL(player);
11935
11936         LOGD("__mmplayer_gst_decode_drained");
11937
11938         if (player->use_deinterleave == TRUE) {
11939                 LOGD("group playing mode.");
11940                 return;
11941         }
11942
11943         if (!MMPLAYER_CMD_TRYLOCK(player)) {
11944                 LOGW("Fail to get cmd lock");
11945                 return;
11946         }
11947
11948         if (!player->gapless.reconfigure && /* If it is already checked, skip verify. */
11949                 !__mmplayer_verify_next_play_path(player)) {
11950                 LOGD("decoding is finished.");
11951                 __mmplayer_reset_gapless_state(player);
11952                 MMPLAYER_CMD_UNLOCK(player);
11953                 return;
11954         }
11955
11956         player->gapless.reconfigure = TRUE;
11957
11958         /* check decodebin src pads whether they received EOS or not */
11959         iter = gst_element_iterate_src_pads(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
11960
11961         while (!done) {
11962                 switch (gst_iterator_next(iter, &item)) {
11963                 case GST_ITERATOR_OK:
11964                         pad = g_value_get_object(&item);
11965                         if (!GST_PAD_IS_EOS(pad)) {
11966                                 LOGW("[%s:%s] not received EOS yet.", GST_DEBUG_PAD_NAME(pad));
11967                                 is_all_drained = FALSE;
11968                                 break;
11969                         }
11970                         g_value_reset(&item);
11971                         break;
11972                 case GST_ITERATOR_RESYNC:
11973                         gst_iterator_resync(iter);
11974                         break;
11975                 case GST_ITERATOR_ERROR:
11976                 case GST_ITERATOR_DONE:
11977                         done = TRUE;
11978                         break;
11979                 }
11980         }
11981         g_value_unset(&item);
11982         gst_iterator_free(iter);
11983
11984         if (!is_all_drained) {
11985                 LOGD("Wait util the all pads get EOS.");
11986                 MMPLAYER_CMD_UNLOCK(player);
11987                 MMPLAYER_FLEAVE();
11988                 return;
11989         }
11990
11991         player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_AUDIO] = FALSE;
11992         player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_VIDEO] = FALSE;
11993
11994         /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
11995         __mmplayer_deactivate_old_path(player);
11996         MMPLAYER_CMD_UNLOCK(player);
11997
11998         MMPLAYER_FLEAVE();
11999 }
12000
12001 static void
12002 __mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
12003 {
12004         mm_player_t* player = (mm_player_t*)data;
12005         const gchar* klass = NULL;
12006         gchar* factory_name = NULL;
12007
12008         klass = gst_element_factory_get_metadata(gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
12009         factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
12010
12011         LOGD("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
12012
12013         if (__mmplayer_add_dump_buffer_probe(player, element))
12014                 LOGD("add buffer probe");
12015
12016         //<-
12017         if (g_strrstr(klass, "Codec/Decoder/Audio")) {
12018                 gchar* selected = NULL;
12019                 selected = g_strdup(GST_ELEMENT_NAME(element));
12020                 player->audio_decoders = g_list_append(player->audio_decoders, selected);
12021         }
12022         //-> temp code
12023
12024         if (g_strrstr(klass, "Parser")) {
12025                 gchar* selected = NULL;
12026
12027                 selected = g_strdup(factory_name);
12028                 player->parsers = g_list_append(player->parsers, selected);
12029         }
12030
12031         if ((g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) && !(g_strrstr(klass, "Adaptive"))) {
12032                 /* FIXIT : first value will be overwritten if there's more
12033                  * than 1 demuxer/parser
12034                  */
12035
12036                 //LOGD("plugged element is demuxer. take it\n");
12037                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
12038                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
12039
12040                 /*Added for multi audio support */ // Q. del?
12041                 if (g_strrstr(klass, "Demux")) {
12042                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
12043                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
12044                 }
12045         }
12046
12047         if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) {
12048                 int surface_type = 0;
12049
12050                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
12051         }
12052
12053         // to support trust-zone only
12054         if (g_strrstr(factory_name, "asfdemux")) {
12055                 LOGD("set file-location %s\n", player->profile.uri);
12056                 g_object_set(G_OBJECT(element), "file-location", player->profile.uri, NULL);
12057
12058                 if (player->video_hub_download_mode == TRUE)
12059                         g_object_set(G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
12060         } else if (g_strrstr(factory_name, "legacyh264parse")) {
12061                 LOGD("[%s] output-format to legacyh264parse\n", "mssdemux");
12062                 g_object_set(G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
12063         } else if (g_strrstr(factory_name, "mpegaudioparse")) {
12064                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
12065                         (__mmplayer_is_only_mp3_type(player->type))) {
12066                         LOGD("[mpegaudioparse] set streaming pull mode.");
12067                         g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
12068                 }
12069         } else if (g_strrstr(factory_name, player->ini.videocodec_element_hw))
12070                 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
12071
12072
12073         if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
12074                 (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))) {
12075                 LOGD("plugged element is multiqueue. take it\n");
12076
12077                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
12078                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
12079
12080                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
12081                         (MMPLAYER_IS_HTTP_LIVE_STREAMING(player))) {
12082                         /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
12083                         __mm_player_streaming_set_multiqueue(player->streamer,
12084                                 element,
12085                                 TRUE,
12086                                 player->ini.http_buffering_time,
12087                                 1.0,
12088                                 player->ini.http_buffering_limit);
12089
12090                         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
12091                 }
12092         }
12093
12094         return;
12095 }
12096
12097 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
12098 {
12099         MMPLAYER_FENTER();
12100         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
12101
12102         if (MMPLAYER_IS_STREAMING(player))
12103                 return FALSE;
12104
12105         /* This callback can be set to music player only. */
12106         if ((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO) {
12107                 LOGW("audio callback is not supported for video");
12108                 return FALSE;
12109         }
12110
12111         if (player->audio_stream_cb) {
12112                 GstPad *pad = NULL;
12113
12114                 pad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
12115
12116                 if (!pad) {
12117                         LOGE("failed to get sink pad from audiosink to probe data\n");
12118                         return FALSE;
12119                 }
12120                 player->audio_cb_probe_id = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
12121                         __mmplayer_audio_stream_probe, player, NULL);
12122
12123                 gst_object_unref(pad);
12124
12125                 pad = NULL;
12126         } else {
12127                 LOGE("There is no audio callback to configure.\n");
12128                 return FALSE;
12129         }
12130
12131         MMPLAYER_FLEAVE();
12132
12133         return TRUE;
12134 }
12135
12136 static void
12137 __mmplayer_init_factories(mm_player_t* player) // @
12138 {
12139         MMPLAYER_RETURN_IF_FAIL(player);
12140
12141         player->factories = gst_registry_feature_filter(gst_registry_get(),
12142                 (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
12143         player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
12144 }
12145
12146 static void
12147 __mmplayer_release_factories(mm_player_t* player) // @
12148 {
12149         MMPLAYER_FENTER();
12150         MMPLAYER_RETURN_IF_FAIL(player);
12151
12152         if (player->factories) {
12153                 gst_plugin_feature_list_free(player->factories);
12154                 player->factories = NULL;
12155         }
12156
12157         MMPLAYER_FLEAVE();
12158 }
12159
12160 static void
12161 __mmplayer_release_misc(mm_player_t* player)
12162 {
12163         int i;
12164         gboolean cur_mode = player->set_mode.rich_audio;
12165         MMPLAYER_FENTER();
12166
12167         MMPLAYER_RETURN_IF_FAIL(player);
12168
12169         player->video_stream_cb = NULL;
12170         player->video_stream_cb_user_param = NULL;
12171         player->video_stream_prerolled = FALSE;
12172
12173         player->audio_stream_cb = NULL;
12174         player->audio_stream_render_cb_ex = NULL;
12175         player->audio_stream_cb_user_param = NULL;
12176         player->audio_stream_sink_sync = false;
12177
12178         player->video_stream_changed_cb = NULL;
12179         player->video_stream_changed_cb_user_param = NULL;
12180
12181         player->audio_stream_changed_cb = NULL;
12182         player->audio_stream_changed_cb_user_param = NULL;
12183
12184         player->sent_bos = FALSE;
12185         player->playback_rate = DEFAULT_PLAYBACK_RATE;
12186
12187         player->doing_seek = FALSE;
12188
12189         player->updated_bitrate_count = 0;
12190         player->total_bitrate = 0;
12191         player->updated_maximum_bitrate_count = 0;
12192         player->total_maximum_bitrate = 0;
12193
12194         player->not_found_demuxer = 0;
12195
12196         player->last_position = 0;
12197         player->duration = 0;
12198         player->http_content_size = 0;
12199         player->not_supported_codec = MISSING_PLUGIN_NONE;
12200         player->can_support_codec = FOUND_PLUGIN_NONE;
12201         player->pending_seek.is_pending = FALSE;
12202         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
12203         player->pending_seek.pos = 0;
12204         player->msg_posted = FALSE;
12205         player->has_many_types = FALSE;
12206         player->max_audio_channels = 0;
12207         player->video_share_api_delta = 0;
12208         player->video_share_clock_delta = 0;
12209         player->sound_focus.keep_last_pos = FALSE;
12210         player->sound_focus.acquired = FALSE;
12211         player->is_subtitle_force_drop = FALSE;
12212         player->play_subtitle = FALSE;
12213         player->use_textoverlay = FALSE;
12214         player->adjust_subtitle_pos = 0;
12215         player->last_multiwin_status = FALSE;
12216         player->has_closed_caption = FALSE;
12217         player->set_mode.media_packet_video_stream = FALSE;
12218         player->profile.uri_type = MM_PLAYER_URI_TYPE_NONE;
12219         memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
12220         /* recover mode */
12221         player->set_mode.rich_audio = cur_mode;
12222
12223         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
12224                 player->bitrate[i] = 0;
12225                 player->maximum_bitrate[i] = 0;
12226         }
12227
12228         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
12229
12230         /* remove media stream cb(appsrc cb) */
12231         for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++) {
12232                 player->media_stream_buffer_status_cb[i] = NULL;
12233                 player->media_stream_seek_data_cb[i] = NULL;
12234         }
12235         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
12236
12237         /* free memory related to audio effect */
12238         MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
12239
12240         if (player->state_tune_caps) {
12241                 gst_caps_unref(player->state_tune_caps);
12242                 player->state_tune_caps = NULL;
12243         }
12244
12245         MMPLAYER_FLEAVE();
12246 }
12247
12248 static void
12249 __mmplayer_release_misc_post(mm_player_t* player)
12250 {
12251         char *original_uri = NULL;
12252         MMPLAYER_FENTER();
12253
12254         /* player->pipeline is already released before. */
12255
12256         MMPLAYER_RETURN_IF_FAIL(player);
12257
12258         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
12259         mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
12260
12261         /* clean found parsers */
12262         if (player->parsers) {
12263                 GList *parsers = player->parsers;
12264                 for (; parsers; parsers = g_list_next(parsers)) {
12265                         gchar *name = parsers->data;
12266                         MMPLAYER_FREEIF(name);
12267                 }
12268                 g_list_free(player->parsers);
12269                 player->parsers = NULL;
12270         }
12271
12272         /* clean found audio decoders */
12273         if (player->audio_decoders) {
12274                 GList *a_dec = player->audio_decoders;
12275                 for (; a_dec; a_dec = g_list_next(a_dec)) {
12276                         gchar *name = a_dec->data;
12277                         MMPLAYER_FREEIF(name);
12278                 }
12279                 g_list_free(player->audio_decoders);
12280                 player->audio_decoders = NULL;
12281         }
12282
12283         /* clean the uri list except original uri */
12284         if (player->uri_info.uri_list) {
12285                 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
12286
12287                 if (player->attrs) {
12288                         mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
12289                         LOGD("restore original uri = %s\n", original_uri);
12290
12291                         if (mmf_attrs_commit(player->attrs))
12292                                 LOGE("failed to commit the original uri.\n");
12293                 }
12294
12295                 GList *uri_list = player->uri_info.uri_list;
12296                 for (; uri_list; uri_list = g_list_next(uri_list)) {
12297                         gchar *uri = uri_list->data;
12298                         MMPLAYER_FREEIF(uri);
12299                 }
12300                 g_list_free(player->uri_info.uri_list);
12301                 player->uri_info.uri_list = NULL;
12302         }
12303
12304         /* clear the audio stream buffer list */
12305         __mmplayer_audio_stream_clear_buffer(player, FALSE);
12306
12307         /* clear the video stream bo list */
12308         __mmplayer_video_stream_destroy_bo_list(player);
12309         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
12310
12311         player->uri_info.uri_idx = 0;
12312         MMPLAYER_FLEAVE();
12313 }
12314
12315 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
12316 {
12317         GstElement *element = NULL;
12318         GstPad *sinkpad;
12319
12320         LOGD("creating %s to plug\n", name);
12321
12322         element = gst_element_factory_make(name, NULL);
12323         if (!element) {
12324                 LOGE("failed to create queue\n");
12325                 return NULL;
12326         }
12327
12328         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY)) {
12329                 LOGE("failed to set state READY to %s\n", name);
12330                 gst_object_unref(element);
12331                 return NULL;
12332         }
12333
12334         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element)) {
12335                 LOGE("failed to add %s\n", name);
12336                 gst_object_unref(element);
12337                 return NULL;
12338         }
12339
12340         sinkpad = gst_element_get_static_pad(element, "sink");
12341
12342         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
12343                 LOGE("failed to link %s\n", name);
12344                 gst_object_unref(sinkpad);
12345                 gst_object_unref(element);
12346                 return NULL;
12347         }
12348
12349         LOGD("linked %s to pipeline successfully\n", name);
12350
12351         gst_object_unref(sinkpad);
12352
12353         return element;
12354 }
12355
12356 static gboolean
12357 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
12358 const char *padname, const GList *templlist)
12359 {
12360         GstPad *pad = NULL;
12361         gboolean has_dynamic_pads = FALSE;
12362         gboolean has_many_types = FALSE;
12363         const char *klass = NULL;
12364         GstStaticPadTemplate *padtemplate = NULL;
12365         GstElementFactory *factory = NULL;
12366         GstElement* queue = NULL;
12367         GstElement* parser = NULL;
12368         GstPad *pssrcpad = NULL;
12369         GstPad *qsrcpad = NULL, *qsinkpad = NULL;
12370         MMPlayerGstElement *mainbin = NULL;
12371         GstStructure* str = NULL;
12372         GstCaps* srccaps = NULL;
12373         GstState target_state = GST_STATE_READY;
12374         gboolean isvideo_decoder = FALSE;
12375         guint q_max_size_time = 0;
12376
12377         MMPLAYER_FENTER();
12378
12379         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
12380                 player->pipeline &&
12381                 player->pipeline->mainbin,
12382                 FALSE);
12383
12384         mainbin = player->pipeline->mainbin;
12385
12386         LOGD("plugging pad %s:%s to newly create %s:%s\n",
12387                         GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)),
12388                         GST_PAD_NAME(srcpad),
12389                         GST_ELEMENT_NAME(sinkelement),
12390                         padname);
12391
12392         factory = gst_element_get_factory(sinkelement);
12393         klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
12394
12395         /* check if player can do start continually */
12396         MMPLAYER_CHECK_CMD_IF_EXIT(player);
12397
12398         /* need it to warm up omx before linking to pipeline */
12399         if (g_strrstr(GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), "demux")) {
12400                 LOGD("get demux caps.\n");
12401                 if (player->state_tune_caps) {
12402                         gst_caps_unref(player->state_tune_caps);
12403                         player->state_tune_caps = NULL;
12404                 }
12405                 player->state_tune_caps = gst_caps_copy(gst_pad_get_current_caps(srcpad));
12406         }
12407
12408         /* NOTE : OMX Codec can check if resource is available or not at this state. */
12409         if (g_strrstr(GST_ELEMENT_NAME(sinkelement), "omx")) {
12410                 if (player->state_tune_caps != NULL) {
12411                         LOGD("set demux's caps to omx codec if resource is available");
12412                         if (gst_pad_set_caps(gst_element_get_static_pad(sinkelement, "sink"), player->state_tune_caps)) {
12413                                 target_state = GST_STATE_PAUSED;
12414                                 isvideo_decoder = TRUE;
12415                                 g_object_set(G_OBJECT(sinkelement), "state-tuning", TRUE, NULL);
12416                         } else
12417                                 LOGW("failed to set caps for state tuning");
12418                 }
12419                 gst_caps_unref(player->state_tune_caps);
12420                 player->state_tune_caps = NULL;
12421         }
12422
12423         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, target_state)) {
12424                 LOGE("failed to set %d state to %s\n", target_state, GST_ELEMENT_NAME(sinkelement));
12425                 if (isvideo_decoder) {
12426                         gst_element_set_state(sinkelement, GST_STATE_NULL);
12427                         gst_object_unref(G_OBJECT(sinkelement));
12428                         player->keep_detecting_vcodec = TRUE;
12429                 }
12430                 goto ERROR;
12431         }
12432
12433         /* add to pipeline */
12434         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement)) {
12435                 LOGE("failed to add %s to mainbin\n", GST_ELEMENT_NAME(sinkelement));
12436                 goto ERROR;
12437         }
12438
12439         LOGD("element klass : %s\n", klass);
12440
12441         /* added to support multi track files */
12442         /* only decoder case and any of the video/audio still need to link*/
12443         if (g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player, srcpad)) {
12444                 gchar *name = g_strdup(GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)));
12445
12446                 if (g_strrstr(name, "mpegtsdemux") || g_strrstr(name, "mssdemux")) {
12447                         gchar *src_demux_caps_str = NULL;
12448                         gchar *needed_parser = NULL;
12449                         GstCaps *src_demux_caps = NULL;
12450                         gboolean smooth_streaming = FALSE;
12451
12452                         src_demux_caps = gst_pad_query_caps(srcpad, NULL);
12453                         src_demux_caps_str = gst_caps_to_string(src_demux_caps);
12454
12455                         gst_caps_unref(src_demux_caps);
12456
12457                         if (g_strrstr(src_demux_caps_str, "video/x-h264")) {
12458                                 if (g_strrstr(name, "mssdemux")) {
12459                                         needed_parser = g_strdup("legacyh264parse");
12460                                         smooth_streaming = TRUE;
12461                                 } else
12462                                         needed_parser = g_strdup("h264parse");
12463                         } else if (g_strrstr(src_demux_caps_str, "video/mpeg"))
12464                                 needed_parser = g_strdup("mpeg4videoparse");
12465
12466                         MMPLAYER_FREEIF(src_demux_caps_str);
12467
12468                         if (needed_parser) {
12469                                 parser = __mmplayer_element_create_and_link(player, srcpad, needed_parser);
12470                                 MMPLAYER_FREEIF(needed_parser);
12471
12472                                 if (!parser) {
12473                                         LOGE("failed to create parser\n");
12474                                 } else {
12475                                         if (smooth_streaming)
12476                                                 g_object_set(parser, "output-format", 1, NULL); /* NALU/Byte Stream format */
12477
12478                                         /* update srcpad if parser is created */
12479                                         pssrcpad = gst_element_get_static_pad(parser, "src");
12480                                         srcpad = pssrcpad;
12481                                 }
12482                         }
12483                 }
12484                 MMPLAYER_FREEIF(name);
12485
12486                 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
12487                 if (!queue) {
12488                         LOGE("failed to create queue\n");
12489                         goto ERROR;
12490                 }
12491
12492                 /* update srcpad to link with decoder */
12493                 qsrcpad = gst_element_get_static_pad(queue, "src");
12494                 srcpad = qsrcpad;
12495
12496                 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
12497
12498                 /* assigning queue handle for futher manipulation purpose */
12499                 /* FIXIT : make it some kind of list so that msl can support more then two stream(text, data, etc...) */
12500                 if (mainbin[MMPLAYER_M_Q1].gst == NULL) {
12501                         mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
12502                         mainbin[MMPLAYER_M_Q1].gst = queue;
12503
12504                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS) {
12505                                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_Q1].gst), "max-size-time", 0 , NULL);
12506                                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_Q1].gst), "max-size-buffers", 2, NULL);
12507                                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_Q1].gst), "max-size-bytes", 0, NULL);
12508                         } else {
12509                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
12510                                         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
12511                         }
12512                 } else if (mainbin[MMPLAYER_M_Q2].gst == NULL) {
12513                         mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
12514                         mainbin[MMPLAYER_M_Q2].gst = queue;
12515
12516                         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS) {
12517                                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_Q2].gst), "max-size-time", 0 , NULL);
12518                                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_Q2].gst), "max-size-buffers", 2, NULL);
12519                                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_Q2].gst), "max-size-bytes", 0, NULL);
12520                         } else {
12521                                 if (!MMPLAYER_IS_RTSP_STREAMING(player))
12522                                         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
12523                         }
12524                 } else {
12525                         LOGE("Not supporting more then two elementary stream\n");
12526                         g_assert(1);
12527                 }
12528
12529                 pad = gst_element_get_static_pad(sinkelement, padname);
12530
12531                 if (!pad) {
12532                         LOGW("failed to get pad(%s) from %s. retrying with [sink]\n",
12533                                 padname, GST_ELEMENT_NAME(sinkelement));
12534
12535                         pad = gst_element_get_static_pad(sinkelement, "sink");
12536                         if (!pad) {
12537                                 LOGE("failed to get pad(sink) from %s. \n",
12538                                 GST_ELEMENT_NAME(sinkelement));
12539                                 goto ERROR;
12540                         }
12541                 }
12542
12543                 /* to check the video/audio type set the proper flag*/
12544                 const gchar *mime_type = NULL;
12545                 srccaps = gst_pad_query_caps(srcpad, NULL);
12546                 if (!srccaps)
12547                         goto ERROR;
12548                 str = gst_caps_get_structure(srccaps, 0);
12549                 if (!str)
12550                         goto ERROR;
12551                 mime_type = gst_structure_get_name(str);
12552                 if (!mime_type)
12553                         goto ERROR;
12554
12555                 /* link queue and decoder. so, it will be queue - decoder. */
12556                 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, pad)) {
12557                         gst_object_unref(GST_OBJECT(pad));
12558                         LOGE("failed to link(%s) to pad(%s)\n", GST_ELEMENT_NAME(sinkelement), padname);
12559
12560                         /* reconstitute supportable codec */
12561                         if (strstr(mime_type, "video"))
12562                                 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
12563                         else if (strstr(mime_type, "audio"))
12564                                 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
12565                         goto ERROR;
12566                 }
12567
12568                 if (strstr(mime_type, "video")) {
12569                         player->videodec_linked = 1;
12570                         LOGI("player->videodec_linked set to 1\n");
12571
12572                 } else if (strstr(mime_type, "audio")) {
12573                         player->audiodec_linked = 1;
12574                         LOGI("player->auddiodec_linked set to 1\n");
12575                 }
12576
12577                 gst_object_unref(GST_OBJECT(pad));
12578                 gst_caps_unref(GST_CAPS(srccaps));
12579                 srccaps = NULL;
12580         }
12581
12582         if (!MMPLAYER_IS_HTTP_PD(player)) {
12583                 if ((g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser"))) {
12584                         if (MMPLAYER_IS_HTTP_STREAMING(player)) {
12585                                 gint64 dur_bytes = 0L;
12586                                 muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
12587
12588                                 if (!mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
12589                                         LOGD("creating http streaming buffering queue\n");
12590
12591                                         queue = gst_element_factory_make("queue2", "queue2");
12592                                         if (!queue) {
12593                                                 LOGE("failed to create buffering queue element\n");
12594                                                 goto ERROR;
12595                                         }
12596
12597                                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY)) {
12598                                                 LOGE("failed to set state READY to buffering queue\n");
12599                                                 goto ERROR;
12600                                         }
12601
12602                                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue)) {
12603                                                 LOGE("failed to add buffering queue\n");
12604                                                 goto ERROR;
12605                                         }
12606
12607                                         qsinkpad = gst_element_get_static_pad(queue, "sink");
12608                                         qsrcpad = gst_element_get_static_pad(queue, "src");
12609
12610                                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad)) {
12611                                                 LOGE("failed to link buffering queue\n");
12612                                                 goto ERROR;
12613                                         }
12614                                         srcpad = qsrcpad;
12615
12616
12617                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
12618                                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue;
12619
12620                                         if (!MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {
12621                                                 if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
12622                                                         LOGE("fail to get duration.\n");
12623
12624                                                 if (dur_bytes > 0) {
12625                                                         if (MMPLAYER_USE_FILE_FOR_BUFFERING(player)) {
12626                                                                 type = MUXED_BUFFER_TYPE_FILE;
12627                                                         } else {
12628                                                                 type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
12629                                                                 if (player->streamer)
12630                                                                         player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
12631                                                         }
12632                                                 } else {
12633                                                         dur_bytes = 0;
12634                                                 }
12635                                         }
12636
12637                                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
12638                                         if (!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux")) {
12639                                                 __mm_player_streaming_set_queue2(player->streamer,
12640                                                         queue,
12641                                                         TRUE,
12642                                                         player->ini.http_max_size_bytes,
12643                                                         player->ini.http_buffering_time,
12644                                                         1.0,
12645                                                         player->ini.http_buffering_limit,
12646                                                         type,
12647                                                         player->http_file_buffering_path,
12648                                                         (guint64)dur_bytes);
12649                                         }
12650                                 }
12651                         }
12652                 }
12653         }
12654         /* if it is not decoder or */
12655         /* in decoder case any of the video/audio still need to link*/
12656         if (!g_strrstr(klass, "Decoder")) {
12657                 pad = gst_element_get_static_pad(sinkelement, padname);
12658                 if (!pad) {
12659                         LOGW("failed to get pad(%s) from %s. retrying with [sink]\n",
12660                                         padname, GST_ELEMENT_NAME(sinkelement));
12661
12662                         pad = gst_element_get_static_pad(sinkelement, "sink");
12663
12664                         if (!pad) {
12665                                 LOGE("failed to get pad(sink) from %s. \n",
12666                                         GST_ELEMENT_NAME(sinkelement));
12667                                 goto ERROR;
12668                         }
12669                 }
12670
12671                 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, pad)) {
12672                         gst_object_unref(GST_OBJECT(pad));
12673                         LOGE("failed to link(%s) to pad(%s)\n", GST_ELEMENT_NAME(sinkelement), padname);
12674                         goto ERROR;
12675                 }
12676
12677                 gst_object_unref(GST_OBJECT(pad));
12678         }
12679
12680         for (; templlist != NULL; templlist = templlist->next) {
12681                 padtemplate = templlist->data;
12682
12683                 LOGD("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
12684
12685                 if (padtemplate->direction != GST_PAD_SRC ||
12686                         padtemplate->presence == GST_PAD_REQUEST)
12687                         continue;
12688
12689                 switch (padtemplate->presence) {
12690                 case GST_PAD_ALWAYS:
12691                         {
12692                                 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
12693                                 GstCaps *caps = gst_pad_query_caps(srcpad, NULL);
12694
12695                                 /* Check whether caps has many types */
12696                                 if (!gst_caps_is_fixed(caps)) {
12697                                         LOGD("always pad but, caps has many types");
12698                                         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
12699                                         has_many_types = TRUE;
12700                                         break;
12701                                 }
12702
12703                                 if (!__mmplayer_try_to_plug(player, srcpad, caps)) {
12704                                         gst_object_unref(GST_OBJECT(srcpad));
12705                                         gst_caps_unref(GST_CAPS(caps));
12706
12707                                         LOGE("failed to plug something after %s\n", GST_ELEMENT_NAME(sinkelement));
12708                                         goto ERROR;
12709                                 }
12710
12711                                 gst_caps_unref(GST_CAPS(caps));
12712                                 gst_object_unref(GST_OBJECT(srcpad));
12713
12714                         }
12715                         break;
12716
12717
12718                 case GST_PAD_SOMETIMES:
12719                         has_dynamic_pads = TRUE;
12720                         break;
12721
12722                 default:
12723                         break;
12724                 }
12725         }
12726
12727         /* check if player can do start continually */
12728         MMPLAYER_CHECK_CMD_IF_EXIT(player);
12729
12730         if (has_dynamic_pads) {
12731                 player->have_dynamic_pad = TRUE;
12732                 MMPLAYER_SIGNAL_CONNECT(player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
12733                         G_CALLBACK(__mmplayer_add_new_pad), player);
12734
12735                 /* for streaming, more then one typefind will used for each elementary stream
12736                  * so this doesn't mean the whole pipeline completion
12737                  */
12738                 if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
12739                         MMPLAYER_SIGNAL_CONNECT(player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
12740                                 G_CALLBACK(__mmplayer_pipeline_complete), player);
12741                 }
12742         }
12743
12744         if (has_many_types) {
12745                 GstPad *pad = NULL;
12746
12747                 player->has_many_types = has_many_types;
12748
12749                 pad = gst_element_get_static_pad(sinkelement, "src");
12750                 MMPLAYER_SIGNAL_CONNECT(player, pad, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
12751                 gst_object_unref(GST_OBJECT(pad));
12752         }
12753
12754
12755         /* check if player can do start continually */
12756         MMPLAYER_CHECK_CMD_IF_EXIT(player);
12757
12758         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED)) {
12759                 LOGE("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME(sinkelement));
12760                 goto ERROR;
12761         }
12762
12763         if (queue) {
12764                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED)) {
12765                         LOGE("failed to set state PAUSED to queue\n");
12766                         goto ERROR;
12767                 }
12768
12769                 queue = NULL;
12770
12771                 gst_object_unref(GST_OBJECT(qsrcpad));
12772                 qsrcpad = NULL;
12773         }
12774
12775         if (parser) {
12776                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(parser, GST_STATE_PAUSED)) {
12777                         LOGE("failed to set state PAUSED to queue\n");
12778                         goto ERROR;
12779                 }
12780
12781                 parser = NULL;
12782
12783                 gst_object_unref(GST_OBJECT(pssrcpad));
12784                 pssrcpad = NULL;
12785         }
12786
12787         MMPLAYER_FLEAVE();
12788
12789         return TRUE;
12790
12791 ERROR:
12792
12793         if (queue) {
12794                 gst_object_unref(GST_OBJECT(qsrcpad));
12795
12796                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
12797                  * You need to explicitly set elements to the NULL state before
12798                  * dropping the final reference, to allow them to clean up.
12799                  */
12800                 gst_element_set_state(queue, GST_STATE_NULL);
12801                 /* And, it still has a parent "player".
12802                  * You need to let the parent manage the object instead of unreffing the object directly.
12803                  */
12804
12805                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
12806                 //gst_object_unref(queue);
12807         }
12808
12809         if (srccaps)
12810                 gst_caps_unref(GST_CAPS(srccaps));
12811
12812         return FALSE;
12813 }
12814
12815 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
12816 {
12817         const gchar *klass;
12818
12819         /* we only care about element factories */
12820         if (!GST_IS_ELEMENT_FACTORY(feature))
12821                 return FALSE;
12822
12823         /* only parsers, demuxers and decoders */
12824                 klass = gst_element_factory_get_metadata(GST_ELEMENT_FACTORY(feature), GST_ELEMENT_METADATA_KLASS);
12825
12826         if (g_strrstr(klass, "Demux") == NULL &&
12827                         g_strrstr(klass, "Codec/Decoder") == NULL &&
12828                         g_strrstr(klass, "Depayloader") == NULL &&
12829                         g_strrstr(klass, "Parse") == NULL)
12830                 return FALSE;
12831         return TRUE;
12832 }
12833
12834
12835 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
12836 {
12837         mm_player_t* player = (mm_player_t*) data;
12838         GstCaps *caps = NULL;
12839         GstStructure *str = NULL;
12840         const char *name;
12841
12842         MMPLAYER_FENTER();
12843
12844         MMPLAYER_RETURN_IF_FAIL(pad)
12845         MMPLAYER_RETURN_IF_FAIL(unused)
12846         MMPLAYER_RETURN_IF_FAIL(data)
12847
12848         caps = gst_pad_query_caps(pad, NULL);
12849         if (!caps)
12850                 return;
12851
12852         str = gst_caps_get_structure(caps, 0);
12853         if (!str)
12854                 return;
12855
12856         name = gst_structure_get_name(str);
12857         if (!name)
12858                 return;
12859         LOGD("name=%s\n", name);
12860
12861         if (!__mmplayer_try_to_plug(player, pad, caps)) {
12862                 LOGE("failed to autoplug for type(%s)\n", name);
12863                 gst_caps_unref(caps);
12864                 return;
12865         }
12866
12867         gst_caps_unref(caps);
12868
12869         __mmplayer_pipeline_complete(NULL, (gpointer)player);
12870
12871         MMPLAYER_FLEAVE();
12872
12873         return;
12874 }
12875
12876 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
12877 {
12878         GstStructure *str;
12879         gint version = 0;
12880         const char *stream_type;
12881         gchar *version_field = NULL;
12882
12883         MMPLAYER_FENTER();
12884
12885         MMPLAYER_RETURN_IF_FAIL(player);
12886         MMPLAYER_RETURN_IF_FAIL(caps);
12887
12888         str = gst_caps_get_structure(caps, 0);
12889         if (!str)
12890                 return;
12891
12892         stream_type = gst_structure_get_name(str);
12893         if (!stream_type)
12894                 return;
12895
12896
12897         /* set unlinked mime type for downloadable codec */
12898         if (g_str_has_prefix(stream_type, "video/")) {
12899                 if (g_str_has_prefix(stream_type, "video/mpeg")) {
12900                         gst_structure_get_int(str, MM_PLAYER_MPEG_VNAME, &version);
12901                         version_field = MM_PLAYER_MPEG_VNAME;
12902                 } else if (g_str_has_prefix(stream_type, "video/x-wmv")) {
12903                         gst_structure_get_int(str, MM_PLAYER_WMV_VNAME, &version);
12904                         version_field = MM_PLAYER_WMV_VNAME;
12905
12906                 } else if (g_str_has_prefix(stream_type, "video/x-divx")) {
12907                         gst_structure_get_int(str, MM_PLAYER_DIVX_VNAME, &version);
12908                         version_field = MM_PLAYER_DIVX_VNAME;
12909                 }
12910
12911                 if (version)
12912                         player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
12913                 else
12914                         player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
12915         } else if (g_str_has_prefix(stream_type, "audio/")) {
12916                 if (g_str_has_prefix(stream_type, "audio/mpeg")) {
12917                         // mp3 or aac
12918                         gst_structure_get_int(str, MM_PLAYER_MPEG_VNAME, &version);
12919                         version_field = MM_PLAYER_MPEG_VNAME;
12920                 } else if (g_str_has_prefix(stream_type, "audio/x-wma")) {
12921                         gst_structure_get_int(str, MM_PLAYER_WMA_VNAME, &version);
12922                         version_field = MM_PLAYER_WMA_VNAME;
12923                 }
12924
12925                 if (version)
12926                         player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
12927                 else
12928                         player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
12929         }
12930
12931         MMPLAYER_FLEAVE();
12932 }
12933
12934 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
12935 {
12936         mm_player_t* player = (mm_player_t*) data;
12937         GstCaps *caps = NULL;
12938         GstStructure *str = NULL;
12939         const char *name;
12940
12941         MMPLAYER_FENTER();
12942         MMPLAYER_RETURN_IF_FAIL(player);
12943         MMPLAYER_RETURN_IF_FAIL(pad);
12944
12945         GST_OBJECT_LOCK(pad);
12946         if ((caps = gst_pad_get_current_caps(pad)))
12947                 gst_caps_ref(caps);
12948         GST_OBJECT_UNLOCK(pad);
12949
12950         if (NULL == caps) {
12951                 caps = gst_pad_query_caps(pad, NULL);
12952                 if (!caps) return;
12953         }
12954
12955         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
12956
12957         str = gst_caps_get_structure(caps, 0);
12958         if (!str)
12959                 return;
12960
12961         name = gst_structure_get_name(str);
12962         if (!name)
12963                 return;
12964
12965         player->num_dynamic_pad++;
12966         LOGD("stream count inc : %d\n", player->num_dynamic_pad);
12967
12968         /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
12969           *     If want to play it, remove this code.
12970           */
12971         if (g_strrstr(name, "application")) {
12972                 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag")) {
12973                         /* If id3/ape tag comes, keep going */
12974                         LOGD("application mime exception : id3/ape tag");
12975                 } else {
12976                         /* Otherwise, we assume that this stream is subtile. */
12977                         LOGD(" application mime type pad is closed.");
12978                         return;
12979                 }
12980         } else if (g_strrstr(name, "audio")) {
12981                 gint samplerate = 0, channels = 0;
12982
12983                 if (player->audiodec_linked) {
12984                         gst_caps_unref(caps);
12985                         LOGD("multi tracks. skip to plug");
12986                         return;
12987                 }
12988
12989                 /* set stream information */
12990                 /* if possible, set it here because the caps is not distrubed by resampler. */
12991                 gst_structure_get_int(str, "rate", &samplerate);
12992                 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
12993
12994                 gst_structure_get_int(str, "channels", &channels);
12995                 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
12996
12997                 LOGD("audio samplerate : %d     channels : %d", samplerate, channels);
12998         } else if (g_strrstr(name, "video")) {
12999                 gint stype;
13000                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
13001
13002                 /* don't make video because of not required */
13003                 if (stype == MM_DISPLAY_SURFACE_NULL || stype == MM_DISPLAY_SURFACE_REMOTE) {
13004                         LOGD("no video because it's not required");
13005                         return;
13006                 }
13007
13008                 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
13009         }
13010
13011         if (!__mmplayer_try_to_plug(player, pad, caps)) {
13012                 LOGE("failed to autoplug for type(%s)", name);
13013
13014                 __mmplayer_set_unlinked_mime_type(player, caps);
13015         }
13016
13017         gst_caps_unref(caps);
13018
13019         MMPLAYER_FLEAVE();
13020         return;
13021 }
13022
13023 gboolean
13024 __mmplayer_check_subtitle(mm_player_t* player)
13025 {
13026         MMHandleType attrs = 0;
13027         char *subtitle_uri = NULL;
13028
13029         MMPLAYER_FENTER();
13030
13031         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13032
13033         /* get subtitle attribute */
13034         attrs = MMPLAYER_GET_ATTRS(player);
13035         if (!attrs)
13036                 return FALSE;
13037
13038         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
13039         if (!subtitle_uri || !strlen(subtitle_uri))
13040                 return FALSE;
13041
13042         LOGD("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
13043         player->is_external_subtitle_present = TRUE;
13044
13045         MMPLAYER_FLEAVE();
13046
13047         return TRUE;
13048 }
13049
13050 static gboolean
13051 __mmplayer_can_extract_pcm(mm_player_t* player)
13052 {
13053         MMHandleType attrs = 0;
13054         gboolean sound_extraction = FALSE;
13055
13056         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13057
13058         attrs = MMPLAYER_GET_ATTRS(player);
13059         if (!attrs) {
13060                 LOGE("fail to get attributes.");
13061                 return FALSE;
13062         }
13063
13064         /* get sound_extraction property */
13065         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
13066
13067         if (!sound_extraction) {
13068                 LOGD("checking pcm extraction mode : %d ", sound_extraction);
13069                 return FALSE;
13070         }
13071
13072         return TRUE;
13073 }
13074
13075 static gboolean
13076 __mmplayer_handle_streaming_error(mm_player_t* player, GstMessage * message)
13077 {
13078         LOGD("\n");
13079         MMMessageParamType msg_param;
13080         gchar *msg_src_element = NULL;
13081         GstStructure *s = NULL;
13082         guint error_id = 0;
13083         gchar *error_string = NULL;
13084
13085         MMPLAYER_FENTER();
13086
13087         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13088         MMPLAYER_RETURN_VAL_IF_FAIL(message, FALSE);
13089
13090         s = malloc(sizeof(GstStructure));
13091         memcpy(s, gst_message_get_structure(message), sizeof(GstStructure));
13092
13093         if (!gst_structure_get_uint(s, "error_id", &error_id))
13094                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
13095
13096         switch (error_id) {
13097         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
13098                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
13099                 break;
13100         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
13101                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
13102                 break;
13103         case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
13104                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
13105                 break;
13106         case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
13107                 msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
13108                 break;
13109         case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
13110                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
13111                 break;
13112         case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
13113                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
13114                 break;
13115         case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
13116                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
13117                 break;
13118         case MMPLAYER_STREAMING_ERROR_INVALID_URL:
13119                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
13120                 break;
13121         case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
13122                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
13123                 break;
13124         case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
13125                 msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
13126                 break;
13127         case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
13128                 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
13129                 break;
13130         case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
13131                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
13132                 break;
13133         case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
13134                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
13135                 break;
13136         case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
13137                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
13138                 break;
13139         case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
13140                 msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
13141                 break;
13142         case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
13143                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
13144                 break;
13145         case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
13146                 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
13147                 break;
13148         case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
13149                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
13150                 break;
13151         case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
13152                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
13153                 break;
13154         case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
13155                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
13156                 break;
13157         case MMPLAYER_STREAMING_ERROR_GONE:
13158                 msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
13159                 break;
13160         case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
13161                 msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
13162                 break;
13163         case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
13164                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
13165                 break;
13166         case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
13167                 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
13168                 break;
13169         case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
13170                 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
13171                 break;
13172         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
13173                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
13174                 break;
13175         case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
13176                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
13177                 break;
13178         case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
13179                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
13180                 break;
13181         case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
13182                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
13183                 break;
13184         case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
13185                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
13186                 break;
13187         case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
13188                 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
13189                 break;
13190         case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
13191                 msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
13192                 break;
13193         case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
13194                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
13195                 break;
13196         case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
13197                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
13198                 break;
13199         case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
13200                 msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
13201                 break;
13202         case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
13203                 msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
13204                 break;
13205         case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
13206                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
13207                 break;
13208         case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
13209                 msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
13210                 break;
13211         case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
13212                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
13213                 break;
13214         case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
13215                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
13216                 break;
13217         case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
13218                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
13219                 break;
13220         case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
13221                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
13222                 break;
13223         case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
13224                 msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
13225                 break;
13226         case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
13227                 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
13228                 break;
13229         case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
13230                 msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
13231                 break;
13232         default:
13233                 {
13234                         MMPLAYER_FREEIF(s);
13235                         return MM_ERROR_PLAYER_STREAMING_FAIL;
13236                 }
13237         }
13238
13239         error_string = g_strdup(gst_structure_get_string(s, "error_string"));
13240         if (error_string)
13241                 msg_param.data = (void *) error_string;
13242
13243         if (message->src) {
13244                 msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
13245
13246                 LOGE("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
13247                         msg_src_element, msg_param.code, (char*)msg_param.data);
13248         }
13249
13250         /* post error to application */
13251         if (!player->msg_posted) {
13252                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
13253
13254                 /* don't post more if one was sent already */
13255                 player->msg_posted = TRUE;
13256         } else
13257                 LOGD("skip error post because it's sent already.\n");
13258
13259         MMPLAYER_FREEIF(s);
13260         MMPLAYER_FLEAVE();
13261         g_free(error_string);
13262
13263         return TRUE;
13264
13265 }
13266
13267 static void
13268 __mmplayer_handle_eos_delay(mm_player_t* player, int delay_in_ms)
13269 {
13270         MMPLAYER_RETURN_IF_FAIL(player);
13271
13272
13273         /* post now if delay is zero */
13274         if (delay_in_ms == 0 || player->set_mode.pcm_extraction) {
13275                 LOGD("eos delay is zero. posting EOS now\n");
13276                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
13277
13278                 if (player->set_mode.pcm_extraction)
13279                         __mmplayer_cancel_eos_timer(player);
13280
13281                 return;
13282         }
13283
13284         /* cancel if existing */
13285         __mmplayer_cancel_eos_timer(player);
13286
13287         /* init new timeout */
13288         /* NOTE : consider give high priority to this timer */
13289         LOGD("posting EOS message after [%d] msec\n", delay_in_ms);
13290
13291         player->eos_timer = g_timeout_add(delay_in_ms,
13292                 __mmplayer_eos_timer_cb, player);
13293
13294         player->context.global_default = g_main_context_default();
13295         LOGD("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
13296
13297         /* check timer is valid. if not, send EOS now */
13298         if (player->eos_timer == 0) {
13299                 LOGW("creating timer for delayed EOS has failed. sending EOS now\n");
13300                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
13301         }
13302 }
13303
13304 static void
13305 __mmplayer_cancel_eos_timer(mm_player_t* player)
13306 {
13307         MMPLAYER_RETURN_IF_FAIL(player);
13308
13309         if (player->eos_timer) {
13310                 LOGD("cancel eos timer");
13311                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
13312                 player->eos_timer = 0;
13313         }
13314
13315         return;
13316 }
13317
13318 static gboolean
13319 __mmplayer_eos_timer_cb(gpointer u_data)
13320 {
13321         mm_player_t* player = NULL;
13322         player = (mm_player_t*) u_data;
13323
13324         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13325
13326         if (player->play_count > 1) {
13327                 gint ret_value = 0;
13328                 ret_value = __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
13329                 if (ret_value == MM_ERROR_NONE) {
13330                         MMHandleType attrs = 0;
13331                         attrs = MMPLAYER_GET_ATTRS(player);
13332
13333                         /* we successeded to rewind. update play count and then wait for next EOS */
13334                         player->play_count--;
13335
13336                         mm_attrs_set_int_by_name(attrs, "profile_play_count", player->play_count);
13337                         mmf_attrs_commit(attrs);
13338                 } else {
13339                         LOGE("seeking to 0 failed in repeat play");
13340                 }
13341         } else {
13342                 /* posting eos */
13343                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
13344         }
13345
13346         /* we are returning FALSE as we need only one posting */
13347         return FALSE;
13348 }
13349
13350 static gboolean
13351 __mmplayer_link_decoder(mm_player_t* player, GstPad *srcpad)
13352 {
13353         const gchar* name = NULL;
13354         GstStructure* str = NULL;
13355         GstCaps* srccaps = NULL;
13356
13357         MMPLAYER_FENTER();
13358
13359         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13360         MMPLAYER_RETURN_VAL_IF_FAIL(srcpad, FALSE);
13361
13362         /* to check any of the decoder(video/audio) need to be linked  to parser*/
13363         srccaps = gst_pad_query_caps(srcpad, NULL);
13364         if (!srccaps)
13365                 goto ERROR;
13366
13367         str = gst_caps_get_structure(srccaps, 0);
13368         if (!str)
13369                 goto ERROR;
13370
13371         name = gst_structure_get_name(str);
13372         if (!name)
13373                 goto ERROR;
13374
13375         if (strstr(name, "video")) {
13376                 if (player->videodec_linked) {
13377                     LOGI("Video decoder already linked\n");
13378                         return FALSE;
13379                 }
13380         }
13381         if (strstr(name, "audio")) {
13382                 if (player->audiodec_linked) {
13383                     LOGI("Audio decoder already linked\n");
13384                         return FALSE;
13385                 }
13386         }
13387
13388         gst_caps_unref(srccaps);
13389
13390         MMPLAYER_FLEAVE();
13391
13392         return TRUE;
13393
13394 ERROR:
13395         if (srccaps)
13396                 gst_caps_unref(srccaps);
13397
13398         return FALSE;
13399 }
13400
13401 static gboolean
13402 __mmplayer_link_sink(mm_player_t* player , GstPad *srcpad)
13403 {
13404         const gchar* name = NULL;
13405         GstStructure* str = NULL;
13406         GstCaps* srccaps = NULL;
13407
13408         MMPLAYER_FENTER();
13409
13410         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13411         MMPLAYER_RETURN_VAL_IF_FAIL(srcpad, FALSE);
13412
13413         /* to check any of the decoder(video/audio) need to be linked   to parser*/
13414         srccaps = gst_pad_query_caps(srcpad, NULL);
13415         if (!srccaps)
13416                 goto ERROR;
13417
13418         str = gst_caps_get_structure(srccaps, 0);
13419         if (!str)
13420                 goto ERROR;
13421
13422         name = gst_structure_get_name(str);
13423         if (!name)
13424                 goto ERROR;
13425
13426         if (strstr(name, "video")) {
13427                 if (player->videosink_linked) {
13428                         LOGI("Video Sink already linked\n");
13429                         return FALSE;
13430                 }
13431         }
13432         if (strstr(name, "audio")) {
13433                 if (player->audiosink_linked) {
13434                         LOGI("Audio Sink already linked\n");
13435                         return FALSE;
13436                 }
13437         }
13438         if (strstr(name, "text")) {
13439                 if (player->textsink_linked) {
13440                         LOGI("Text Sink already linked\n");
13441                         return FALSE;
13442                 }
13443         }
13444
13445         gst_caps_unref(srccaps);
13446
13447         MMPLAYER_FLEAVE();
13448
13449         //return (!player->videosink_linked || !player->audiosink_linked);
13450         return TRUE;
13451
13452 ERROR:
13453         if (srccaps)
13454                 gst_caps_unref(srccaps);
13455
13456         return FALSE;
13457 }
13458
13459
13460 /* sending event to one of sinkelements */
13461 static gboolean
13462 __gst_send_event_to_sink(mm_player_t* player, GstEvent* event)
13463 {
13464         GstEvent * event2 = NULL;
13465         GList *sinks = NULL;
13466         gboolean res = FALSE;
13467         MMPLAYER_FENTER();
13468
13469         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13470         MMPLAYER_RETURN_VAL_IF_FAIL(event, FALSE);
13471
13472         /* While adding subtitles in live feeds seek is getting called.
13473            Adding defensive check in framework layer.*/
13474         if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
13475                 if (MMPLAYER_IS_LIVE_STREAMING (player)) {
13476                         LOGE ("Should not send seek event during live playback");
13477                         return TRUE;
13478                 }
13479         }
13480
13481         if (player->play_subtitle && !player->use_textoverlay)
13482                 event2 = gst_event_copy((const GstEvent *)event);
13483
13484         sinks = player->sink_elements;
13485         while (sinks) {
13486                 GstElement *sink = GST_ELEMENT_CAST(sinks->data);
13487
13488                 if (GST_IS_ELEMENT(sink)) {
13489                         /* keep ref to the event */
13490                         gst_event_ref(event);
13491
13492                         if ((res = gst_element_send_event(sink, event))) {
13493                                 LOGD("sending event[%s] to sink element [%s] success!\n",
13494                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
13495
13496                                 /* rtsp case, asyn_done is not called after seek during pause state */
13497                                 if (MMPLAYER_IS_RTSP_STREAMING(player)) {
13498                                         if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
13499                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
13500                                                         LOGD("RTSP seek completed, after pause state..\n");
13501                                                         player->doing_seek = FALSE;
13502                                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
13503                                                 }
13504
13505                                         }
13506                                 }
13507
13508                                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
13509                                         sinks = g_list_next(sinks);
13510                                         continue;
13511                                 } else
13512                                         break;
13513                         }
13514
13515                         LOGD("sending event[%s] to sink element [%s] failed. try with next one.\n",
13516                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
13517                 }
13518
13519                 sinks = g_list_next(sinks);
13520         }
13521
13522 #if 0
13523         if (internal_sub)
13524           request pad name = sink0;
13525         else
13526           request pad name = sink1; // external
13527 #endif
13528
13529         /* Note : Textbin is not linked to the video or audio bin.
13530          * It needs to send the event to the text sink seperatelly.
13531          */
13532          if (player->play_subtitle && !player->use_textoverlay) {
13533                 GstElement *text_sink = GST_ELEMENT_CAST(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
13534
13535                 if (GST_IS_ELEMENT(text_sink)) {
13536                         /* keep ref to the event */
13537                         gst_event_ref(event2);
13538
13539                         if ((res = gst_element_send_event(text_sink, event2)))
13540                                 LOGD("sending event[%s] to subtitle sink element [%s] success!\n",
13541                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
13542                         else
13543                                 LOGE("sending event[%s] to subtitle sink element [%s] failed!\n",
13544                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
13545
13546                         gst_event_unref(event2);
13547                 }
13548          }
13549
13550         gst_event_unref(event);
13551
13552         MMPLAYER_FLEAVE();
13553
13554         return res;
13555 }
13556
13557 static void
13558 __mmplayer_add_sink(mm_player_t* player, GstElement* sink)
13559 {
13560         MMPLAYER_FENTER();
13561
13562         MMPLAYER_RETURN_IF_FAIL(player);
13563         MMPLAYER_RETURN_IF_FAIL(sink);
13564
13565         player->sink_elements =
13566                 g_list_append(player->sink_elements, sink);
13567
13568         MMPLAYER_FLEAVE();
13569 }
13570
13571 static void
13572 __mmplayer_del_sink(mm_player_t* player, GstElement* sink)
13573 {
13574         MMPLAYER_FENTER();
13575
13576         MMPLAYER_RETURN_IF_FAIL(player);
13577         MMPLAYER_RETURN_IF_FAIL(sink);
13578
13579         player->sink_elements =
13580                         g_list_remove(player->sink_elements, sink);
13581
13582         MMPLAYER_FLEAVE();
13583 }
13584
13585 static gboolean
13586 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
13587                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
13588                         gint64 cur, GstSeekType stop_type, gint64 stop)
13589 {
13590         GstEvent* event = NULL;
13591         gboolean result = FALSE;
13592
13593         MMPLAYER_FENTER();
13594
13595         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13596
13597         if (player->pipeline && player->pipeline->textbin)
13598                 __mmplayer_drop_subtitle(player, FALSE);
13599
13600         event = gst_event_new_seek(rate, format, flags, cur_type,
13601                 cur, stop_type, stop);
13602
13603         result = __gst_send_event_to_sink(player, event);
13604
13605         MMPLAYER_FLEAVE();
13606
13607         return result;
13608 }
13609
13610 /* NOTE : be careful with calling this api. please refer to below glib comment
13611  * glib comment : Note that there is a bug in GObject that makes this function much
13612  * less useful than it might seem otherwise. Once gobject is disposed, the callback
13613  * will no longer be called, but, the signal handler is not currently disconnected.
13614  * If the instance is itself being freed at the same time than this doesn't matter,
13615  * since the signal will automatically be removed, but if instance persists,
13616  * then the signal handler will leak. You should not remove the signal yourself
13617  * because in a future versions of GObject, the handler will automatically be
13618  * disconnected.
13619  *
13620  * It's possible to work around this problem in a way that will continue to work
13621  * with future versions of GObject by checking that the signal handler is still
13622  * connected before disconnected it:
13623  *
13624  *  if (g_signal_handler_is_connected(instance, id))
13625  *    g_signal_handler_disconnect(instance, id);
13626  */
13627 static void
13628 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
13629 {
13630         GList* sig_list = NULL;
13631         MMPlayerSignalItem* item = NULL;
13632
13633         MMPLAYER_FENTER();
13634
13635         MMPLAYER_RETURN_IF_FAIL(player);
13636
13637         LOGD("release signals type : %d", type);
13638
13639         if ((type < MM_PLAYER_SIGNAL_TYPE_AUTOPLUG) || (type >= MM_PLAYER_SIGNAL_TYPE_ALL)) {
13640                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
13641                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
13642                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
13643                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
13644                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
13645                 return;
13646         }
13647
13648         sig_list = player->signals[type];
13649
13650         for (; sig_list; sig_list = sig_list->next) {
13651                 item = sig_list->data;
13652
13653                 if (item && item->obj && GST_IS_ELEMENT(item->obj)) {
13654                         if (g_signal_handler_is_connected(item->obj, item->sig))
13655                                 g_signal_handler_disconnect(item->obj, item->sig);
13656                 }
13657
13658                 MMPLAYER_FREEIF(item);
13659         }
13660
13661         g_list_free(player->signals[type]);
13662         player->signals[type] = NULL;
13663
13664         MMPLAYER_FLEAVE();
13665
13666         return;
13667 }
13668
13669 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
13670 {
13671         mm_player_t* player = 0;
13672         int prev_display_surface_type = 0;
13673         void *prev_display_overlay = NULL;
13674         const gchar *klass = NULL;
13675         gchar *cur_videosink_name = NULL;
13676         int ret = 0;
13677         int i = 0;
13678         int num_of_dec = 2; /* DEC1, DEC2 */
13679
13680         MMPLAYER_FENTER();
13681
13682         MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
13683         MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
13684
13685         player = MM_PLAYER_CAST(handle);
13686
13687         if (surface_type < MM_DISPLAY_SURFACE_OVERLAY || surface_type >= MM_DISPLAY_SURFACE_NUM) {
13688                 LOGE("Not support this surface type(%d) for changing vidoesink", surface_type);
13689                 MMPLAYER_FLEAVE();
13690                 return MM_ERROR_INVALID_ARGUMENT;
13691         }
13692
13693         /* load previous attributes */
13694         if (player->attrs) {
13695                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &prev_display_surface_type);
13696                 mm_attrs_get_data_by_name(player->attrs, "display_overlay", &prev_display_overlay);
13697                 LOGD("[0: Video surface, 4: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
13698                 if (prev_display_surface_type == surface_type) {
13699                         LOGD("incoming display surface type is same as previous one, do nothing..");
13700                         MMPLAYER_FLEAVE();
13701                         return MM_ERROR_NONE;
13702                 }
13703         } else {
13704                 LOGE("failed to load attributes");
13705                 MMPLAYER_FLEAVE();
13706                 return MM_ERROR_PLAYER_INTERNAL;
13707         }
13708
13709         /* check videosink element is created */
13710         if (!player->pipeline || !player->pipeline->videobin ||
13711                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
13712                 LOGD("videosink element is not yet ready");
13713
13714                 /* videobin is not created yet, so we just set attributes related to display surface */
13715                 LOGD("store display attribute for given surface type(%d)", surface_type);
13716                 mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
13717                 mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
13718                 if (mmf_attrs_commit(player->attrs)) {
13719                         LOGE("failed to commit attribute");
13720                         MMPLAYER_FLEAVE();
13721                         return MM_ERROR_PLAYER_INTERNAL;
13722                 }
13723                 MMPLAYER_FLEAVE();
13724                 return MM_ERROR_NONE;
13725         } else {
13726                 /* get player command status */
13727                 if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE)) {
13728                         LOGE("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command", player->cmd);
13729                         MMPLAYER_FLEAVE();
13730                         return MM_ERROR_PLAYER_INVALID_STATE;
13731                 }
13732
13733                 /* surface change */
13734                 for (i = 0 ; i < num_of_dec ; i++) {
13735                         if (player->pipeline->mainbin &&
13736                                 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) {
13737                                 GstElementFactory *decfactory;
13738                                 decfactory = gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst);
13739
13740                                 klass = gst_element_factory_get_metadata(decfactory, GST_ELEMENT_METADATA_KLASS);
13741                                 if ((g_strrstr(klass, "Codec/Decoder/Video"))) {
13742                                         if ((prev_display_surface_type == MM_DISPLAY_SURFACE_OVERLAY) && (surface_type == MM_DISPLAY_SURFACE_REMOTE)) {
13743                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, "fakesink", surface_type, display_overlay);
13744                                                 if (ret) {
13745                                                         goto ERROR_CASE;
13746                                                 } else {
13747                                                         LOGW("success to changing display surface(%d)", surface_type);
13748                                                         MMPLAYER_FLEAVE();
13749                                                         return MM_ERROR_NONE;
13750                                                 }
13751                                         } else if ((prev_display_surface_type == MM_DISPLAY_SURFACE_REMOTE) && (surface_type == MM_DISPLAY_SURFACE_OVERLAY)) {
13752                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_overlay, surface_type, display_overlay);
13753                                                 if (ret) {
13754                                                         goto ERROR_CASE;
13755                                                 } else {
13756                                                         LOGW("success to changing display surface(%d)", surface_type);
13757                                                         MMPLAYER_FLEAVE();
13758                                                         return MM_ERROR_NONE;
13759                                                 }
13760                                         } else {
13761                                                 LOGE("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface", surface_type, cur_videosink_name);
13762                                                 ret = MM_ERROR_PLAYER_INTERNAL;
13763                                                 goto ERROR_CASE;
13764                                         }
13765                                 }
13766                         }
13767                 }
13768         }
13769
13770 ERROR_CASE:
13771         /* rollback to previous attributes */
13772         mm_attrs_set_int_by_name(player->attrs, "display_surface_type", prev_display_surface_type);
13773         mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(void*));
13774         if (mmf_attrs_commit(player->attrs)) {
13775                 LOGE("failed to commit attributes to rollback");
13776                 MMPLAYER_FLEAVE();
13777                 return MM_ERROR_PLAYER_INTERNAL;
13778         }
13779         MMPLAYER_FLEAVE();
13780         return ret;
13781 }
13782
13783 /* NOTE : It does not support some use cases, eg using colorspace converter */
13784 int
13785 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
13786 {
13787         GstPad *src_pad_dec = NULL;
13788         GstPad *sink_pad_videosink = NULL;
13789         GstPad *sink_pad_videobin = NULL;
13790         GstClock *clock = NULL;
13791         MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
13792         int ret = MM_ERROR_NONE;
13793         gboolean is_audiobin_created = TRUE;
13794
13795         MMPLAYER_FENTER();
13796
13797         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
13798         MMPLAYER_RETURN_VAL_IF_FAIL(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
13799         MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
13800
13801         LOGD("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
13802         LOGD("surface type(%d), display overlay(%x)", surface_type, display_overlay);
13803
13804         /* get information whether if audiobin is created */
13805         if (!player->pipeline->audiobin ||
13806                      !player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
13807                 LOGW("audiobin is null, this video content may not have audio data");
13808                 is_audiobin_created = FALSE;
13809         }
13810
13811         /* get current state of player */
13812         previous_state = MMPLAYER_CURRENT_STATE(player);
13813         LOGD("previous state(%d)", previous_state);
13814
13815
13816         /* get src pad of decoder and block it */
13817         src_pad_dec = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
13818         if (!src_pad_dec) {
13819                 LOGE("failed to get src pad from decode in mainbin");
13820                 return MM_ERROR_PLAYER_INTERNAL;
13821         }
13822
13823         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING) {
13824                 LOGW("trying to block pad(video)");
13825 //              if (!gst_pad_set_blocked(src_pad_dec, TRUE))
13826                 gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
13827                         NULL, NULL, NULL);
13828                 {
13829                         LOGE("failed to set block pad(video)");
13830                         return MM_ERROR_PLAYER_INTERNAL;
13831                 }
13832                 LOGW("pad is blocked(video)");
13833         } else {
13834                 /* no data flows, so no need to do pad_block */
13835                 if (player->doing_seek)
13836                         LOGW("not completed seek(%d), do nothing", player->doing_seek);
13837
13838                 LOGD("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
13839         }
13840
13841         /* remove pad */
13842         if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
13843                 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin)))) {
13844                 LOGE("failed to remove previous ghost_pad for videobin");
13845                 return MM_ERROR_PLAYER_INTERNAL;
13846         }
13847
13848         /* change state of videobin to NULL */
13849         LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
13850         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
13851         if (ret != GST_STATE_CHANGE_SUCCESS) {
13852                 LOGE("failed to change state of videobin to NULL");
13853                 return MM_ERROR_PLAYER_INTERNAL;
13854         }
13855
13856         /* unlink between decoder and videobin and remove previous videosink from videobin */
13857         GST_ELEMENT_UNLINK(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
13858         if (!gst_bin_remove(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst))) {
13859                 LOGE("failed to remove former videosink from videobin");
13860                 return MM_ERROR_PLAYER_INTERNAL;
13861         }
13862
13863         __mmplayer_del_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
13864
13865         /* create a new videosink and add it to videobin */
13866         player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, videosink_element);
13867         if (!player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
13868                 LOGE("failed to create videosink element\n");
13869                 MMPLAYER_FLEAVE();
13870                 return MM_ERROR_PLAYER_INTERNAL;
13871         }
13872         gst_bin_add(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
13873         __mmplayer_add_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
13874         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
13875
13876         /* save attributes */
13877         if (player->attrs) {
13878                 /* set a new display surface type */
13879                 mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
13880                 /* set a new diplay overlay */
13881                 switch (surface_type) {
13882                 case MM_DISPLAY_SURFACE_OVERLAY:
13883                         LOGD("save attributes related to video display surface : id = %d", *(int*)display_overlay);
13884                         mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
13885                         break;
13886                 default:
13887                         LOGE("invalid type(%d) for changing display surface", surface_type);
13888                         MMPLAYER_FLEAVE();
13889                         return MM_ERROR_INVALID_ARGUMENT;
13890                 }
13891                 if (mmf_attrs_commit(player->attrs)) {
13892                         LOGE("failed to commit");
13893                         MMPLAYER_FLEAVE();
13894                         return MM_ERROR_PLAYER_INTERNAL;
13895                 }
13896         } else {
13897                 LOGE("player->attrs is null, failed to save attributes");
13898                 MMPLAYER_FLEAVE();
13899                 return MM_ERROR_PLAYER_INTERNAL;
13900         }
13901
13902         /* update video param */
13903         if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "update_all_param")) {
13904                 LOGE("failed to update video param");
13905                 return MM_ERROR_PLAYER_INTERNAL;
13906         }
13907
13908         /* change state of videobin to READY */
13909         LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
13910         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
13911         if (ret != GST_STATE_CHANGE_SUCCESS) {
13912                 LOGE("failed to change state of videobin to READY");
13913                 return MM_ERROR_PLAYER_INTERNAL;
13914         }
13915
13916         /* change ghostpad */
13917         sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
13918         if (!sink_pad_videosink) {
13919                 LOGE("failed to get sink pad from videosink element");
13920                 return MM_ERROR_PLAYER_INTERNAL;
13921         }
13922         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
13923         if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE)) {
13924                 LOGE("failed to set active to ghost_pad");
13925                 return MM_ERROR_PLAYER_INTERNAL;
13926         }
13927         if (FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
13928                 LOGE("failed to change ghostpad for videobin");
13929                 return MM_ERROR_PLAYER_INTERNAL;
13930         }
13931         gst_object_unref(sink_pad_videosink);
13932
13933         /* link decoder with videobin */
13934         sink_pad_videobin = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
13935         if (!sink_pad_videobin) {
13936                 LOGE("failed to get sink pad from videobin");
13937                 return MM_ERROR_PLAYER_INTERNAL;
13938         }
13939         if (GST_PAD_LINK_OK != GST_PAD_LINK(src_pad_dec, sink_pad_videobin)) {
13940                 LOGE("failed to link");
13941                 return MM_ERROR_PLAYER_INTERNAL;
13942         }
13943         gst_object_unref(sink_pad_videobin);
13944
13945         /* clock setting for a new videosink plugin */
13946         /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
13947                         so we set it from audiosink plugin or pipeline(system clock) */
13948         if (!is_audiobin_created) {
13949                 LOGW("audiobin is not created, get clock from pipeline..");
13950                 clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
13951         } else {
13952                 clock = GST_ELEMENT_CLOCK(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
13953         }
13954         if (clock) {
13955                 GstClockTime now;
13956                 GstClockTime base_time;
13957                 LOGD("set the clock to videosink");
13958                 gst_element_set_clock(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
13959                 clock = GST_ELEMENT_CLOCK(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
13960                 if (clock) {
13961                         LOGD("got clock of videosink");
13962                         now = gst_clock_get_time(clock);
13963                         base_time = GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
13964                         LOGD("at time %" GST_TIME_FORMAT ", base %"
13965                                         GST_TIME_FORMAT, GST_TIME_ARGS(now), GST_TIME_ARGS(base_time));
13966                 } else {
13967                         LOGE("failed to get clock of videosink after setting clock");
13968                         return MM_ERROR_PLAYER_INTERNAL;
13969                 }
13970         } else
13971                 LOGW("failed to get clock, maybe it is the time before first playing");
13972
13973         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING) {
13974                 /* change state of videobin to PAUSED */
13975                 LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
13976                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
13977                 if (ret != GST_STATE_CHANGE_FAILURE) {
13978                         LOGW("change state of videobin to PLAYING, ret(%d)", ret);
13979                 } else {
13980                         LOGE("failed to change state of videobin to PLAYING");
13981                         return MM_ERROR_PLAYER_INTERNAL;
13982                 }
13983
13984                 /* release blocked and unref src pad of video decoder */
13985                 #if 0
13986                 if (!gst_pad_set_blocked(src_pad_dec, FALSE)) {
13987                         LOGE("failed to set pad blocked FALSE(video)");
13988                         return MM_ERROR_PLAYER_INTERNAL;
13989                 }
13990                 #endif
13991                 LOGW("pad is unblocked(video)");
13992         } else {
13993                 if (player->doing_seek)
13994                         LOGW("not completed seek(%d)", player->doing_seek);
13995                 /* change state of videobin to PAUSED */
13996                 LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
13997                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
13998                 if (ret != GST_STATE_CHANGE_FAILURE) {
13999                         LOGW("change state of videobin to PAUSED, ret(%d)", ret);
14000                 } else {
14001                         LOGE("failed to change state of videobin to PLAYING");
14002                         return MM_ERROR_PLAYER_INTERNAL;
14003                 }
14004
14005                 /* already skipped pad block */
14006                 LOGD("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
14007         }
14008
14009         /* do get/set position for new videosink plugin */
14010         {
14011                 unsigned long position = 0;
14012                 gint64 pos_msec = 0;
14013
14014                 LOGD("do get/set position for new videosink plugin");
14015                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position)) {
14016                         LOGE("failed to get position");
14017                         return MM_ERROR_PLAYER_INTERNAL;
14018                 }
14019 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
14020                 /* accurate seek */
14021                 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE)) {
14022                         LOGE("failed to set position");
14023                         return MM_ERROR_PLAYER_INTERNAL;
14024                 }
14025 #else
14026                 /* key unit seek */
14027                 pos_msec = position * G_GINT64_CONSTANT(1000000);
14028                 ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
14029                                 GST_FORMAT_TIME, (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
14030                                                         GST_SEEK_TYPE_SET, pos_msec,
14031                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
14032                 if (!ret) {
14033                         LOGE("failed to set position");
14034                         return MM_ERROR_PLAYER_INTERNAL;
14035                 }
14036 #endif
14037         }
14038
14039         if (src_pad_dec)
14040                 gst_object_unref(src_pad_dec);
14041         LOGD("success to change sink");
14042
14043         MMPLAYER_FLEAVE();
14044
14045         return MM_ERROR_NONE;
14046 }
14047
14048
14049 /* Note : if silent is true, then subtitle would not be displayed. :*/
14050 int _mmplayer_set_subtitle_silent(MMHandleType hplayer, int silent)
14051 {
14052         mm_player_t* player = (mm_player_t*) hplayer;
14053
14054         MMPLAYER_FENTER();
14055
14056         /* check player handle */
14057         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14058
14059         player->set_mode.subtitle_off = silent;
14060
14061         LOGD("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
14062
14063         MMPLAYER_FLEAVE();
14064
14065         return MM_ERROR_NONE;
14066 }
14067
14068 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
14069 {
14070         MMPlayerGstElement* mainbin = NULL;
14071         MMPlayerGstElement* textbin = NULL;
14072         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
14073         GstState current_state = GST_STATE_VOID_PENDING;
14074         GstState element_state = GST_STATE_VOID_PENDING;
14075         GstState element_pending_state = GST_STATE_VOID_PENDING;
14076         gint64 time = 0;
14077         GstEvent *event = NULL;
14078         int result = MM_ERROR_NONE;
14079
14080         GstClock *curr_clock = NULL;
14081         GstClockTime base_time, start_time, curr_time;
14082
14083
14084         MMPLAYER_FENTER();
14085
14086         /* check player handle */
14087         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline , MM_ERROR_PLAYER_NOT_INITIALIZED);
14088
14089         if (!(player->pipeline->mainbin) || !(player->pipeline->textbin)) {
14090                 LOGE("Pipeline is not in proper state\n");
14091                 result = MM_ERROR_PLAYER_NOT_INITIALIZED;
14092                 goto EXIT;
14093         }
14094
14095         mainbin = player->pipeline->mainbin;
14096         textbin = player->pipeline->textbin;
14097
14098         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
14099
14100         // sync clock with current pipeline
14101         curr_clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
14102         curr_time = gst_clock_get_time(curr_clock);
14103
14104         base_time = gst_element_get_base_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
14105         start_time = gst_element_get_start_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
14106
14107         LOGD("base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
14108                 GST_TIME_ARGS(base_time), GST_TIME_ARGS(start_time), GST_TIME_ARGS(curr_time));
14109
14110         if (current_state > GST_STATE_READY) {
14111                 // sync state with current pipeline
14112                 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
14113                 gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_PAUSED);
14114                 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
14115
14116                 ret = gst_element_get_state(mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
14117                 if (GST_STATE_CHANGE_FAILURE == ret)
14118                         LOGE("fail to state change.\n");
14119         }
14120
14121         gst_element_set_base_time(textbin[MMPLAYER_T_BIN].gst, base_time);
14122         gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
14123
14124         if (curr_clock) {
14125                 gst_element_set_clock(textbin[MMPLAYER_T_BIN].gst, curr_clock);
14126                 gst_object_unref(curr_clock);
14127         }
14128
14129         // seek to current position
14130         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
14131                 result = MM_ERROR_PLAYER_INVALID_STATE;
14132                 LOGE("gst_element_query_position failed, invalid state\n");
14133                 goto EXIT;
14134         }
14135
14136         LOGD("seek time = %lld, rate = %f\n", time, player->playback_rate);
14137         event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
14138         if (event) {
14139                 __gst_send_event_to_sink(player, event);
14140         } else {
14141                 result = MM_ERROR_PLAYER_INTERNAL;
14142                 LOGE("gst_event_new_seek failed\n");
14143                 goto EXIT;
14144         }
14145
14146         // sync state with current pipeline
14147         gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
14148         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
14149         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
14150
14151 EXIT:
14152         return result;
14153 }
14154
14155 static int
14156 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
14157 {
14158         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
14159         GstState current_state = GST_STATE_VOID_PENDING;
14160
14161         MMHandleType attrs = 0;
14162         MMPlayerGstElement* mainbin = NULL;
14163         MMPlayerGstElement* textbin = NULL;
14164
14165         gchar* subtitle_uri = NULL;
14166         int result = MM_ERROR_NONE;
14167         const gchar *charset = NULL;
14168
14169         MMPLAYER_FENTER();
14170
14171         /* check player handle */
14172         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14173         MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT);
14174
14175         if (!(player->pipeline) || !(player->pipeline->mainbin)) {
14176                 result = MM_ERROR_PLAYER_INVALID_STATE;
14177                 LOGE("Pipeline is not in proper state\n");
14178                 goto EXIT;
14179         }
14180
14181         mainbin = player->pipeline->mainbin;
14182         textbin = player->pipeline->textbin;
14183
14184         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
14185         if (current_state < GST_STATE_READY) {
14186                 result = MM_ERROR_PLAYER_INVALID_STATE;
14187                 LOGE("Pipeline is not in proper state\n");
14188                 goto EXIT;
14189         }
14190
14191         attrs = MMPLAYER_GET_ATTRS(player);
14192         if (!attrs) {
14193                 LOGE("cannot get content attribute\n");
14194                 result = MM_ERROR_PLAYER_INTERNAL;
14195                 goto EXIT;
14196         }
14197
14198         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
14199         if (!subtitle_uri || strlen(subtitle_uri) < 1) {
14200                 LOGE("subtitle uri is not proper filepath\n");
14201                 result = MM_ERROR_PLAYER_INVALID_URI;
14202                 goto EXIT;
14203         }
14204
14205         if (!util_get_storage_info(filepath, &player->storage_info[MMPLAYER_PATH_TEXT])) {
14206                 LOGE("failed to get storage info of subtitle path");
14207                 result = MM_ERROR_PLAYER_INVALID_URI;
14208                 goto EXIT;
14209         }
14210
14211         LOGD("old subtitle file path is [%s]\n", subtitle_uri);
14212         LOGD("new subtitle file path is [%s]\n", filepath);
14213
14214         if (!strcmp(filepath, subtitle_uri)) {
14215                 LOGD("No need to swtich subtitle, as input filepath is same as current filepath\n");
14216                 goto EXIT;
14217         } else {
14218                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
14219                 if (mmf_attrs_commit(player->attrs)) {
14220                         LOGE("failed to commit.\n");
14221                         goto EXIT;
14222                 }
14223         }
14224
14225         //gst_pad_set_blocked_async(src-srcpad, TRUE)
14226
14227         ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
14228         if (ret != GST_STATE_CHANGE_SUCCESS) {
14229                 LOGE("failed to change state of textbin to READY");
14230                 result = MM_ERROR_PLAYER_INTERNAL;
14231                 goto EXIT;
14232         }
14233
14234         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_READY);
14235         if (ret != GST_STATE_CHANGE_SUCCESS) {
14236                 LOGE("failed to change state of subparse to READY");
14237                 result = MM_ERROR_PLAYER_INTERNAL;
14238                 goto EXIT;
14239         }
14240
14241         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
14242         if (ret != GST_STATE_CHANGE_SUCCESS) {
14243                 LOGE("failed to change state of filesrc to READY");
14244                 result = MM_ERROR_PLAYER_INTERNAL;
14245                 goto EXIT;
14246         }
14247
14248         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_TEXT);
14249
14250         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
14251
14252         charset = util_get_charset(filepath);
14253         if (charset) {
14254                 LOGD("detected charset is %s\n", charset);
14255                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
14256         }
14257
14258         result = _mmplayer_sync_subtitle_pipeline(player);
14259
14260 EXIT:
14261         MMPLAYER_FLEAVE();
14262         return result;
14263 }
14264
14265 /* API to switch between external subtitles */
14266 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
14267 {
14268         int result = MM_ERROR_NONE;
14269         mm_player_t* player = (mm_player_t*)hplayer;
14270
14271         MMPLAYER_FENTER();
14272
14273         /* check player handle */
14274         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14275
14276         if (!player->pipeline) {
14277                 // IDLE state
14278                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
14279                 if (mmf_attrs_commit(player->attrs)) {
14280                         LOGE("failed to commit.\n");
14281                         result = MM_ERROR_PLAYER_INTERNAL;
14282                 }
14283         } else {
14284                 // cur state <> IDLE(READY, PAUSE, PLAYING..)
14285                 if (filepath == NULL)
14286                         return MM_ERROR_COMMON_INVALID_ARGUMENT;
14287
14288                 if (!__mmplayer_check_subtitle(player)) {
14289                         mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
14290                         if (mmf_attrs_commit(player->attrs)) {
14291                                 LOGE("failed to commit.\n");
14292                                 result = MM_ERROR_PLAYER_INTERNAL;
14293                         }
14294
14295                         if (MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player))
14296                                 LOGE("fail to create subtitle src\n");
14297
14298                         result = _mmplayer_sync_subtitle_pipeline(player);
14299                 } else
14300                         result = __mmplayer_change_external_subtitle_language(player, filepath);
14301
14302                 player->is_external_subtitle_added_now = TRUE;
14303         }
14304
14305         MMPLAYER_FLEAVE();
14306         return result;
14307 }
14308
14309 static int
14310 __mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index)
14311 {
14312         int result = MM_ERROR_NONE;
14313         gchar* change_pad_name = NULL;
14314         GstPad* sinkpad = NULL;
14315         MMPlayerGstElement* mainbin = NULL;
14316         enum MainElementID elemId = MMPLAYER_M_NUM;
14317         GstCaps* caps = NULL;
14318         gint total_track_num = 0;
14319
14320         MMPLAYER_FENTER();
14321
14322         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin,
14323                                                                                                         MM_ERROR_PLAYER_NOT_INITIALIZED);
14324
14325         LOGD("Change Track(%d) to %d\n", type, index);
14326
14327         mainbin = player->pipeline->mainbin;
14328
14329         if (type == MM_PLAYER_TRACK_TYPE_AUDIO) {
14330                 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
14331         } else if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
14332                 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
14333         } else {
14334                 /* Changing Video Track is not supported. */
14335                 LOGE("Track Type Error\n");
14336                 goto EXIT;
14337         }
14338
14339         if (mainbin[elemId].gst == NULL) {
14340                 result = MM_ERROR_PLAYER_NO_OP;
14341                 LOGD("Req track doesn't exist\n");
14342                 goto EXIT;
14343         }
14344
14345         total_track_num = player->selector[type].total_track_num;
14346         if (total_track_num <= 0) {
14347                 result = MM_ERROR_PLAYER_NO_OP;
14348                 LOGD("Language list is not available \n");
14349                 goto EXIT;
14350         }
14351
14352         if ((index < 0) || (index >= total_track_num)) {
14353                 result = MM_ERROR_INVALID_ARGUMENT;
14354                 LOGD("Not a proper index : %d \n", index);
14355                 goto EXIT;
14356         }
14357
14358         /*To get the new pad from the selector*/
14359         change_pad_name = g_strdup_printf("sink_%u", index);
14360         if (change_pad_name == NULL) {
14361                 result = MM_ERROR_PLAYER_INTERNAL;
14362                 LOGD("Pad does not exists\n");
14363                 goto EXIT;
14364         }
14365
14366         LOGD("new active pad name: %s\n", change_pad_name);
14367
14368         sinkpad = gst_element_get_static_pad(mainbin[elemId].gst, change_pad_name);
14369         if (sinkpad == NULL) {
14370                 LOGD("sinkpad is NULL");
14371                 result = MM_ERROR_PLAYER_INTERNAL;
14372                 goto EXIT;
14373         }
14374
14375         LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
14376         g_object_set(mainbin[elemId].gst, "active-pad", sinkpad, NULL);
14377
14378         caps = gst_pad_get_current_caps(sinkpad);
14379         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
14380
14381         if (sinkpad)
14382                 gst_object_unref(sinkpad);
14383
14384         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
14385                 __mmplayer_set_audio_attrs(player, caps);
14386
14387 EXIT:
14388
14389         MMPLAYER_FREEIF(change_pad_name);
14390         return result;
14391 }
14392
14393 int _mmplayer_change_track_language(MMHandleType hplayer, MMPlayerTrackType type, int index)
14394 {
14395         int result = MM_ERROR_NONE;
14396         mm_player_t* player = NULL;
14397         MMPlayerGstElement* mainbin = NULL;
14398
14399         gint current_active_index = 0;
14400
14401         GstState current_state = GST_STATE_VOID_PENDING;
14402         GstEvent* event = NULL;
14403         gint64 time = 0;
14404
14405         MMPLAYER_FENTER();
14406
14407         player = (mm_player_t*)hplayer;
14408         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14409
14410         if (!player->pipeline) {
14411                 LOGE("Track %d pre setting -> %d\n", type, index);
14412
14413                 player->selector[type].active_pad_index = index;
14414                 goto EXIT;
14415         }
14416
14417         mainbin = player->pipeline->mainbin;
14418
14419         current_active_index = player->selector[type].active_pad_index;
14420
14421         /*If index is same as running index no need to change the pad*/
14422         if (current_active_index == index)
14423                 goto EXIT;
14424
14425         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
14426                 result = MM_ERROR_PLAYER_INVALID_STATE;
14427                 goto EXIT;
14428         }
14429
14430         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
14431         if (current_state < GST_STATE_PAUSED) {
14432                 result = MM_ERROR_PLAYER_INVALID_STATE;
14433                 LOGW("Pipeline not in porper state\n");
14434                 goto EXIT;
14435         }
14436
14437         result = __mmplayer_change_selector_pad(player, type, index);
14438         if (result != MM_ERROR_NONE) {
14439                 LOGE("change selector pad error\n");
14440                 goto EXIT;
14441         }
14442
14443         player->selector[type].active_pad_index = index;
14444
14445         if (current_state == GST_STATE_PLAYING) {
14446                 event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
14447                 if (event) {
14448                         __gst_send_event_to_sink(player, event);
14449                 } else {
14450                         result = MM_ERROR_PLAYER_INTERNAL;
14451                         goto EXIT;
14452                 }
14453         }
14454
14455 EXIT:
14456         return result;
14457 }
14458
14459 int _mmplayer_get_subtitle_silent(MMHandleType hplayer, int* silent)
14460 {
14461         mm_player_t* player = (mm_player_t*) hplayer;
14462
14463         MMPLAYER_FENTER();
14464
14465         /* check player handle */
14466         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14467
14468         *silent = player->set_mode.subtitle_off;
14469
14470         LOGD("subtitle is %s.\n", silent ? "ON" : "OFF");
14471
14472         MMPLAYER_FLEAVE();
14473
14474         return MM_ERROR_NONE;
14475 }
14476
14477 gboolean
14478 __is_ms_buff_src(mm_player_t* player)
14479 {
14480         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
14481
14482         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_MS_BUFF) ? TRUE : FALSE;
14483 }
14484
14485 gboolean
14486 __has_suffix(mm_player_t* player, const gchar* suffix)
14487 {
14488         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
14489         MMPLAYER_RETURN_VAL_IF_FAIL(suffix, FALSE);
14490
14491         gboolean ret = FALSE;
14492         gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
14493         gchar* t_suffix = g_ascii_strdown(suffix, -1);
14494
14495         if (g_str_has_suffix(player->profile.uri, suffix))
14496                 ret = TRUE;
14497
14498         MMPLAYER_FREEIF(t_url);
14499         MMPLAYER_FREEIF(t_suffix);
14500
14501         return ret;
14502 }
14503
14504 int
14505 _mmplayer_set_display_zoom(MMHandleType hplayer, float level, int x, int y)
14506 {
14507         mm_player_t* player = (mm_player_t*) hplayer;
14508
14509         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14510
14511         MMPLAYER_VIDEO_SINK_CHECK(player);
14512
14513         LOGD("setting display zoom level = %f, offset = %d, %d", level, x, y);
14514
14515         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", level, "zoom-pos-x", x, "zoom-pos-y", y, NULL);
14516
14517         return MM_ERROR_NONE;
14518 }
14519 int
14520 _mmplayer_get_display_zoom(MMHandleType hplayer, float *level, int *x, int *y)
14521 {
14522
14523         mm_player_t* player = (mm_player_t*) hplayer;
14524         float _level = 0.0;
14525         int _x = 0;
14526         int _y = 0;
14527
14528         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14529
14530         MMPLAYER_VIDEO_SINK_CHECK(player);
14531
14532         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", &_level, "zoom-pos-x", &_x, "zoom-pos-y", &_y, NULL);
14533
14534         LOGD("display zoom level = %f, start off x = %d, y = %d", _level, _x, _y);
14535
14536         *level = _level;
14537         *x = _x;
14538         *y = _y;
14539
14540         return MM_ERROR_NONE;
14541 }
14542
14543 int
14544 _mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
14545 {
14546         mm_player_t* player = (mm_player_t*) hplayer;
14547
14548         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14549
14550         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL) {
14551                 MMPLAYER_PRINT_STATE(player);
14552                 LOGE("wrong-state : can't set the download mode to parse");
14553                 return MM_ERROR_PLAYER_INVALID_STATE;
14554         }
14555
14556         LOGD("set video hub download mode to %s", (mode) ? "ON" : "OFF");
14557         player->video_hub_download_mode = mode;
14558
14559         return MM_ERROR_NONE;
14560 }
14561
14562 int
14563 _mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
14564 {
14565         mm_player_t* player = (mm_player_t*) hplayer;
14566
14567         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14568
14569         LOGD("enable sync handler : %s", (enable) ? "ON" : "OFF");
14570         player->sync_handler = enable;
14571
14572         return MM_ERROR_NONE;
14573 }
14574
14575 int
14576 _mmplayer_set_video_share_master_clock(MMHandleType hplayer,
14577                                         long long clock,
14578                                         long long clock_delta,
14579                                         long long video_time,
14580                                         long long media_clock,
14581                                         long long audio_time)
14582 {
14583         mm_player_t* player = (mm_player_t*) hplayer;
14584         MMPlayerGstElement* mainbin = NULL;
14585         GstClockTime start_time_audio = 0, start_time_video = 0;
14586         GstClockTimeDiff base_time = 0, new_base_time = 0;
14587         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
14588         gint64 api_delta = 0;
14589         gint64 position = 0, position_delta = 0;
14590         gint64 adj_base_time = 0;
14591         GstClock *curr_clock = NULL;
14592         GstClockTime curr_time = 0;
14593         gboolean query_ret = TRUE;
14594         int result = MM_ERROR_NONE;
14595
14596         MMPLAYER_FENTER();
14597
14598         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
14599         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
14600         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
14601
14602         // LOGD("in(us) : %lld, %lld, %lld, %lld, %lld", clock, clock_delta, video_time, media_clock, audio_time);
14603
14604         if ((video_time < 0) || (player->doing_seek)) {
14605                 LOGD("skip setting master clock.  %lld", video_time);
14606                 goto EXIT;
14607         }
14608
14609         mainbin = player->pipeline->mainbin;
14610
14611         curr_clock = gst_pipeline_get_clock(GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
14612         curr_time = gst_clock_get_time(curr_clock);
14613
14614         current_state = MMPLAYER_CURRENT_STATE(player);
14615
14616         if (current_state == MM_PLAYER_STATE_PLAYING)
14617                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
14618
14619         if ((current_state != MM_PLAYER_STATE_PLAYING) ||
14620                 (!query_ret)) {
14621                 position = player->last_position;
14622                 LOGD("query fail. %lld", position);
14623         }
14624
14625         clock *= GST_USECOND;
14626         clock_delta *= GST_USECOND;
14627
14628         api_delta = clock - curr_time;
14629         if ((player->video_share_api_delta == 0) || (player->video_share_api_delta > api_delta))
14630                 player->video_share_api_delta = api_delta;
14631         else
14632                 clock_delta += (api_delta - player->video_share_api_delta);
14633
14634         if ((player->video_share_clock_delta == 0) || (player->video_share_clock_delta > clock_delta)) {
14635                 player->video_share_clock_delta = (gint64)clock_delta;
14636
14637                 position_delta = (position/GST_USECOND) - video_time;
14638                 position_delta *= GST_USECOND;
14639
14640                 adj_base_time = position_delta;
14641                 LOGD("video_share_clock_delta = %lld, adj = %lld", player->video_share_clock_delta, adj_base_time);
14642
14643         } else {
14644                 gint64 new_play_time = 0;
14645                 gint64 network_delay = 0;
14646
14647                 video_time *= GST_USECOND;
14648
14649                 network_delay = clock_delta - player->video_share_clock_delta;
14650                 new_play_time = video_time + network_delay;
14651
14652                 adj_base_time = position - new_play_time;
14653
14654                 LOGD("%lld(delay) = %lld - %lld / %lld(adj) = %lld(slave_pos) - %lld(master_pos) - %lld(delay)",
14655                         network_delay, clock_delta, player->video_share_clock_delta, adj_base_time, position, video_time, network_delay);
14656         }
14657
14658         /* Adjust Current Stream Time with base_time of sink
14659          * 1. Set Start time to CLOCK NONE, to control the base time by MSL
14660          * 2. Set new base time
14661          *    if adj_base_time is positive value, the stream time will be decreased.
14662          * 3. If seek event is occurred, the start time will be reset. */
14663         if ((player->pipeline->audiobin) &&
14664                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst)) {
14665                 start_time_audio = gst_element_get_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
14666
14667                 if (start_time_audio != GST_CLOCK_TIME_NONE) {
14668                         LOGD("audio sink : gst_element_set_start_time -> NONE");
14669                         gst_element_set_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, GST_CLOCK_TIME_NONE);
14670                 }
14671
14672                 base_time = gst_element_get_base_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
14673         }
14674
14675         if ((player->pipeline->videobin) &&
14676                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst)) {
14677                 start_time_video = gst_element_get_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
14678
14679                 if (start_time_video != GST_CLOCK_TIME_NONE) {
14680                         LOGD("video sink : gst_element_set_start_time -> NONE");
14681                         gst_element_set_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst, GST_CLOCK_TIME_NONE);
14682                 }
14683
14684                 // if videobin exist, get base_time from videobin.
14685                 base_time = gst_element_get_base_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
14686         }
14687
14688         new_base_time = base_time + adj_base_time;
14689
14690         if ((player->pipeline->audiobin) &&
14691                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
14692                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), (GstClockTime)new_base_time);
14693
14694         if ((player->pipeline->videobin) &&
14695                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
14696                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), (GstClockTime)new_base_time);
14697
14698 EXIT:
14699         MMPLAYER_FLEAVE();
14700
14701         return result;
14702 }
14703
14704 int
14705 _mmplayer_get_video_share_master_clock(MMHandleType hplayer,
14706                                         long long *video_time,
14707                                         long long *media_clock,
14708                                         long long *audio_time)
14709 {
14710         mm_player_t* player = (mm_player_t*) hplayer;
14711         MMPlayerGstElement* mainbin = NULL;
14712         GstClock *curr_clock = NULL;
14713         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
14714         gint64 position = 0;
14715         gboolean query_ret = TRUE;
14716
14717         MMPLAYER_FENTER();
14718
14719         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
14720         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
14721         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
14722
14723         MMPLAYER_RETURN_VAL_IF_FAIL(video_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
14724         MMPLAYER_RETURN_VAL_IF_FAIL(media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT);
14725         MMPLAYER_RETURN_VAL_IF_FAIL(audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
14726
14727         mainbin = player->pipeline->mainbin;
14728
14729         curr_clock = gst_pipeline_get_clock(GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
14730
14731         current_state = MMPLAYER_CURRENT_STATE(player);
14732
14733         if (current_state != MM_PLAYER_STATE_PAUSED)
14734                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
14735
14736         if ((current_state == MM_PLAYER_STATE_PAUSED) ||
14737                 (!query_ret))
14738                 position = player->last_position;
14739
14740         *media_clock = *video_time = *audio_time = (position/GST_USECOND);
14741
14742         LOGD("media_clock: %lld, video_time: %lld(us)", *media_clock, *video_time);
14743
14744         if (curr_clock)
14745                 gst_object_unref(curr_clock);
14746
14747         MMPLAYER_FLEAVE();
14748
14749         return MM_ERROR_NONE;
14750 }
14751
14752 int
14753 _mmplayer_get_video_rotate_angle(MMHandleType hplayer, int *angle)
14754 {
14755         mm_player_t* player = (mm_player_t*) hplayer;
14756         int org_angle = 0;
14757
14758         MMPLAYER_FENTER();
14759
14760         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14761         MMPLAYER_RETURN_VAL_IF_FAIL(angle, MM_ERROR_COMMON_INVALID_ARGUMENT);
14762
14763         if (player->v_stream_caps) {
14764                 GstStructure *str = NULL;
14765
14766                 str = gst_caps_get_structure(player->v_stream_caps, 0);
14767                 if (!gst_structure_get_int(str, "orientation", &org_angle))
14768                         LOGD("missing 'orientation' field in video caps");
14769         }
14770
14771         LOGD("orientation: %d", org_angle);
14772         *angle = org_angle;
14773
14774         MMPLAYER_FLEAVE();
14775         return MM_ERROR_NONE;
14776 }
14777
14778 static gboolean
14779 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
14780 {
14781         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
14782         MMPLAYER_RETURN_VAL_IF_FAIL(element, FALSE);
14783
14784         gchar *factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
14785         gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
14786
14787         int idx = 0;
14788
14789         for (idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++) {
14790                 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx])) {
14791                         LOGD("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
14792                         mm_player_dump_t *dump_s;
14793                         dump_s = g_malloc(sizeof(mm_player_dump_t));
14794
14795                         if (dump_s == NULL) {
14796                                 LOGE("malloc fail");
14797                                 return FALSE;
14798                         }
14799
14800                         dump_s->dump_element_file = NULL;
14801                         dump_s->dump_pad = NULL;
14802                         dump_s->dump_pad = gst_element_get_static_pad(element, "sink");
14803
14804                         if (dump_s->dump_pad) {
14805                                 memset(dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
14806                                 snprintf(dump_file_name, PLAYER_INI_MAX_STRLEN*2, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
14807                                 dump_s->dump_element_file = fopen(dump_file_name, "w+");
14808                                 dump_s->probe_handle_id = gst_pad_add_probe(dump_s->dump_pad, GST_PAD_PROBE_TYPE_BUFFER, __mmplayer_dump_buffer_probe_cb, dump_s->dump_element_file, NULL);
14809                                 /* add list for removed buffer probe and close FILE */
14810                                 player->dump_list = g_list_append(player->dump_list, dump_s);
14811                                 LOGD("%s sink pad added buffer probe for dump", factory_name);
14812                                 return TRUE;
14813                         } else {
14814                                 g_free(dump_s);
14815                                 dump_s = NULL;
14816                                 LOGE("failed to get %s sink pad added", factory_name);
14817                         }
14818
14819
14820                 }
14821         }
14822         return FALSE;
14823 }
14824
14825 static GstPadProbeReturn
14826 __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data)
14827 {
14828         FILE *dump_data = (FILE *) u_data;
14829 //      int written = 0;
14830         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
14831         GstMapInfo probe_info = GST_MAP_INFO_INIT;
14832
14833         MMPLAYER_RETURN_VAL_IF_FAIL(dump_data, FALSE);
14834
14835         gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
14836
14837 //      LOGD("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
14838
14839         fwrite(probe_info.data, 1, probe_info.size , dump_data);
14840
14841         return GST_PAD_PROBE_OK;
14842 }
14843
14844 static void
14845 __mmplayer_release_dump_list(GList *dump_list)
14846 {
14847         if (dump_list) {
14848                 GList *d_list = dump_list;
14849                 for (; d_list; d_list = g_list_next(d_list)) {
14850                         mm_player_dump_t *dump_s = d_list->data;
14851                         if (dump_s->dump_pad) {
14852                                 if (dump_s->probe_handle_id)
14853                                         gst_pad_remove_probe(dump_s->dump_pad, dump_s->probe_handle_id);
14854                         }
14855                         if (dump_s->dump_element_file) {
14856                                 fclose(dump_s->dump_element_file);
14857                                 dump_s->dump_element_file = NULL;
14858                         }
14859                         MMPLAYER_FREEIF(dump_s);
14860                 }
14861                 g_list_free(dump_list);
14862                 dump_list = NULL;
14863         }
14864 }
14865
14866 int
14867 _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
14868 {
14869         mm_player_t* player = (mm_player_t*) hplayer;
14870
14871         MMPLAYER_FENTER();
14872
14873         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
14874         MMPLAYER_RETURN_VAL_IF_FAIL(exist, MM_ERROR_INVALID_ARGUMENT);
14875
14876         *exist = player->has_closed_caption;
14877
14878         MMPLAYER_FLEAVE();
14879
14880         return MM_ERROR_NONE;
14881 }
14882
14883 void * _mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer)
14884 {
14885         void * ret = NULL
14886         MMPLAYER_FENTER();
14887         /* increase ref count of gst buffer */
14888         if (buffer)
14889                 ret = gst_buffer_ref((GstBuffer *)buffer);
14890
14891         MMPLAYER_FLEAVE();
14892         return ret;
14893 }
14894
14895 void _mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer)
14896 {
14897         MMPLAYER_FENTER();
14898         if (buffer) {
14899                 gst_buffer_unref((GstBuffer *)buffer);
14900                 buffer = NULL;
14901         }
14902         MMPLAYER_FLEAVE();
14903 }
14904
14905 void
14906 __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data)
14907 {
14908         mm_player_t *player  = (mm_player_t*)user_data;
14909         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
14910         guint64 current_level_bytes = 0;
14911
14912         MMPLAYER_RETURN_IF_FAIL(player);
14913
14914         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
14915
14916         LOGI("app-src: feed audio(%llu)\n", current_level_bytes);
14917         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
14918
14919         if (player->media_stream_buffer_status_cb[type])
14920                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param);
14921         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
14922
14923 }
14924
14925 void
14926 __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data)
14927 {
14928         mm_player_t *player  = (mm_player_t*)user_data;
14929         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
14930         guint64 current_level_bytes = 0;
14931
14932         MMPLAYER_RETURN_IF_FAIL(player);
14933
14934         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
14935
14936         LOGI("app-src: feed video(%llu)\n", current_level_bytes);
14937
14938         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
14939         if (player->media_stream_buffer_status_cb[type])
14940                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param);
14941         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
14942 }
14943
14944 void
14945 __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data)
14946 {
14947         mm_player_t *player  = (mm_player_t*)user_data;
14948         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
14949         guint64 current_level_bytes = 0;
14950
14951         MMPLAYER_RETURN_IF_FAIL(player);
14952
14953         LOGI("app-src: feed subtitle\n");
14954
14955         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
14956
14957         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
14958         if (player->media_stream_buffer_status_cb[type])
14959                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param);
14960
14961         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
14962 }
14963
14964 void
14965 __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data)
14966 {
14967         mm_player_t *player  = (mm_player_t*)user_data;
14968         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
14969         guint64 current_level_bytes = 0;
14970
14971         MMPLAYER_RETURN_IF_FAIL(player);
14972
14973         LOGI("app-src: audio buffer is full.\n");
14974
14975         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
14976
14977         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
14978
14979         if (player->media_stream_buffer_status_cb[type])
14980                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param);
14981
14982         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
14983 }
14984
14985 void
14986 __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data)
14987 {
14988         mm_player_t *player  = (mm_player_t*)user_data;
14989         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
14990         guint64 current_level_bytes = 0;
14991
14992         MMPLAYER_RETURN_IF_FAIL(player);
14993
14994         LOGI("app-src: video buffer is full.\n");
14995
14996         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
14997
14998         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
14999         if (player->media_stream_buffer_status_cb[type])
15000                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param);
15001
15002         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
15003 }
15004
15005 gboolean
15006 __gst_seek_audio_data(GstElement * appsrc, guint64 position, gpointer user_data)
15007 {
15008         mm_player_t *player  = (mm_player_t*)user_data;
15009         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
15010
15011         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
15012
15013         LOGD("app-src: seek audio data %llu\n", position);
15014         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
15015
15016         if (player->media_stream_seek_data_cb[type])
15017                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
15018         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
15019
15020         return TRUE;
15021 }
15022
15023 gboolean
15024 __gst_seek_video_data(GstElement * appsrc, guint64 position, gpointer user_data)
15025 {
15026         mm_player_t *player  = (mm_player_t*)user_data;
15027         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
15028
15029         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
15030
15031         LOGD("app-src: seek video data %llu\n", position);
15032         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
15033         if (player->media_stream_seek_data_cb[type])
15034                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
15035         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
15036
15037         return TRUE;
15038 }
15039
15040 gboolean
15041 __gst_seek_subtitle_data(GstElement * appsrc, guint64 position, gpointer user_data)
15042 {
15043         mm_player_t *player  = (mm_player_t*)user_data;
15044         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
15045
15046         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
15047
15048         LOGD("app-src: seek subtitle data\n");
15049         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
15050
15051         if (player->media_stream_seek_data_cb[type])
15052                 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
15053         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
15054
15055         return TRUE;
15056 }
15057
15058 int
15059 _mmplayer_set_pcm_spec(MMHandleType hplayer, int samplerate, int channel)
15060 {
15061         mm_player_t* player = (mm_player_t*) hplayer;
15062
15063         MMPLAYER_FENTER();
15064
15065         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15066
15067         player->pcm_samplerate = samplerate;
15068         player->pcm_channel = channel;
15069
15070         MMPLAYER_FLEAVE();
15071         return MM_ERROR_NONE;
15072 }
15073
15074 int _mmplayer_get_timeout(MMHandleType hplayer, int *timeout)
15075 {
15076         mm_player_t* player = (mm_player_t*) hplayer;
15077
15078         MMPLAYER_FENTER();
15079
15080         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15081         MMPLAYER_RETURN_VAL_IF_FAIL(timeout, MM_ERROR_COMMON_INVALID_ARGUMENT);
15082
15083         if (MMPLAYER_IS_STREAMING(player))
15084                 *timeout = player->ini.live_state_change_timeout;
15085         else
15086                 *timeout = player->ini.localplayback_state_change_timeout;
15087
15088         LOGD("timeout = %d\n", *timeout);
15089
15090         MMPLAYER_FLEAVE();
15091         return MM_ERROR_NONE;
15092 }
15093
15094 int _mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int *extra_num)
15095 {
15096         mm_player_t* player = (mm_player_t*) hplayer;
15097
15098         MMPLAYER_FENTER();
15099
15100         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15101         MMPLAYER_RETURN_VAL_IF_FAIL(num && extra_num, MM_ERROR_COMMON_INVALID_ARGUMENT);
15102
15103         *num = player->video_num_buffers;
15104         *extra_num = player->video_extra_num_buffers;
15105
15106         LOGD("state %d, num %d(%d)\n", MMPLAYER_CURRENT_STATE(player), *num, *extra_num);
15107
15108         MMPLAYER_FLEAVE();
15109         return MM_ERROR_NONE;
15110 }
15111
15112 static void
15113 __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type)
15114 {
15115         int i = 0;
15116         MMPLAYER_FENTER();
15117         MMPLAYER_RETURN_IF_FAIL(player);
15118
15119         for (i=0; i<MMPLAYER_PATH_MAX; i++) {
15120
15121                 if (path_type == MMPLAYER_PATH_MAX || path_type == i) {
15122                         player->storage_info[i].type = STORAGE_TYPE_INTERNAL;
15123                         player->storage_info[i].state = STORAGE_STATE_MOUNTED;
15124                         player->storage_info[i].id = -1;
15125
15126                         if (path_type != MMPLAYER_PATH_MAX)
15127                                 break;
15128                 }
15129         }
15130
15131         MMPLAYER_FLEAVE();
15132 }
15133
15134 int _mmplayer_manage_external_storage_state(MMHandleType hplayer, int state)
15135 {
15136         int ret = MM_ERROR_NONE;
15137         mm_player_t* player = (mm_player_t*) hplayer;
15138         MMMessageParamType msg_param = {0, };
15139
15140         MMPLAYER_FENTER();
15141         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
15142
15143         LOGD("storage state : %d", state);
15144
15145         if (state != STORAGE_STATE_UNMOUNTABLE && state != STORAGE_STATE_REMOVED)
15146                 return MM_ERROR_NONE;
15147
15148         if ((player->storage_info[MMPLAYER_PATH_VOD].type == STORAGE_TYPE_EXTERNAL) ||
15149                 (player->storage_info[MMPLAYER_PATH_TEXT].type == STORAGE_TYPE_EXTERNAL)) {
15150                 LOGW("external storage is removed.");
15151
15152                 if (player->msg_posted == FALSE) {
15153                         memset(&msg_param, 0, sizeof(MMMessageParamType));
15154                         msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
15155                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
15156                         player->msg_posted = TRUE;
15157                 }
15158
15159                 /* unrealize the player */
15160                 ret = _mmplayer_unrealize(hplayer);
15161                 if (ret != MM_ERROR_NONE)
15162                         LOGE("failed to unrealize");
15163         }
15164
15165         MMPLAYER_FLEAVE();
15166         return ret;
15167 }
15168