4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
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>
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 /*===========================================================================================
27 ========================================================================================== */
30 #include <gst/app/gstappsrc.h>
31 #include <gst/video/videooverlay.h>
33 #include <gst/wayland/wayland.h>
35 #include <gst/audio/gstaudiobasesink.h>
44 #include <mm_attrs_private.h>
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"
57 #define MM_SMOOTH_STREAMING
59 /*===========================================================================================
61 | LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE |
63 ========================================================================================== */
65 /*---------------------------------------------------------------------------
66 | GLOBAL CONSTANT DEFINITIONS: |
67 ---------------------------------------------------------------------------*/
69 /*---------------------------------------------------------------------------
70 | IMPORTED VARIABLE DECLARATIONS: |
71 ---------------------------------------------------------------------------*/
73 /*---------------------------------------------------------------------------
74 | IMPORTED FUNCTION DECLARATIONS: |
75 ---------------------------------------------------------------------------*/
77 /*---------------------------------------------------------------------------
79 ---------------------------------------------------------------------------*/
80 #define TRICK_PLAY_MUTE_THRESHOLD_MAX 2.0
81 #define TRICK_PLAY_MUTE_THRESHOLD_MIN 0.0
83 #define MM_VOLUME_FACTOR_DEFAULT 1.0
84 #define MM_VOLUME_FACTOR_MIN 0
85 #define MM_VOLUME_FACTOR_MAX 1.0
87 #define MM_PLAYER_FADEOUT_TIME_DEFAULT 700000 // 700 msec
89 #define MM_PLAYER_MPEG_VNAME "mpegversion"
90 #define MM_PLAYER_DIVX_VNAME "divxversion"
91 #define MM_PLAYER_WMV_VNAME "wmvversion"
92 #define MM_PLAYER_WMA_VNAME "wmaversion"
94 #define DEFAULT_PLAYBACK_RATE 1.0
95 #define PLAYBACK_RATE_EX_AUDIO_MIN 0.5
96 #define PLAYBACK_RATE_EX_AUDIO_MAX 2.0
97 #define PLAYBACK_RATE_EX_VIDEO_MIN 0.5
98 #define PLAYBACK_RATE_EX_VIDEO_MAX 1.5
100 #define GST_QUEUE_DEFAULT_TIME 4
101 #define GST_QUEUE_HLS_TIME 8
103 #define DEFAULT_AUDIO_CH 0
105 #define MMPLAYER_USE_FILE_FOR_BUFFERING(player) (((player)->profile.uri_type != MM_PLAYER_URI_TYPE_HLS) && (player->ini.http_file_buffer_path) && (strlen(player->ini.http_file_buffer_path) > 0) )
107 #define LAZY_PAUSE_TIMEOUT_MSEC 700
108 #define MM_PLAYER_NAME "mmplayer"
110 #define SMOOTH_STREAMING_DEMUX "mssdemux"
112 * g_array_index(a,t,i) does not calculate gst private structure.
113 * It replaces the g_array_index(a,t,i)
115 #define g_array_undef_struct_idx_p(a,t,i) ((t *)(void *)((a)->data + ((i) * (a)->len)))
117 //#define ENABLE_DRMSRC
119 /*---------------------------------------------------------------------------
120 | LOCAL CONSTANT DEFINITIONS: |
121 ---------------------------------------------------------------------------*/
123 /*---------------------------------------------------------------------------
124 | LOCAL DATA TYPE DEFINITIONS: |
125 ---------------------------------------------------------------------------*/
127 /*---------------------------------------------------------------------------
128 | GLOBAL VARIABLE DEFINITIONS: |
129 ---------------------------------------------------------------------------*/
131 /*---------------------------------------------------------------------------
132 | LOCAL VARIABLE DEFINITIONS: |
133 ---------------------------------------------------------------------------*/
135 /*---------------------------------------------------------------------------
136 | LOCAL FUNCTION PROTOTYPES: |
137 ---------------------------------------------------------------------------*/
138 static int __mmplayer_set_state(mm_player_t* player, int state);
139 static int __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
140 static int __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
141 static int __mmplayer_gst_create_text_pipeline(mm_player_t* player);
142 static int __mmplayer_gst_create_subtitle_src(mm_player_t* player);
143 static int __mmplayer_gst_create_pipeline(mm_player_t* player);
144 static int __mmplayer_gst_destroy_pipeline(mm_player_t* player);
145 static int __mmplayer_gst_element_link_bucket(GList* element_bucket);
147 static gboolean __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data);
148 static GstPadProbeReturn __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data);
149 static void __mmplayer_gst_decode_pad_added(GstElement* elem, GstPad* pad, gpointer data);
150 static void __mmplayer_gst_decode_no_more_pads(GstElement* elem, gpointer data);
151 static void __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gpointer data);
152 static void __mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad* pad, GstCaps *caps, gpointer data);
153 static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad* pad, GstCaps * caps, gpointer data);
154 static gint __mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad* pad, GstCaps * caps, GstElementFactory* factory, gpointer data);
155 //static GValueArray* __mmplayer_gst_decode_autoplug_factories(GstElement *bin, GstPad* pad, GstCaps * caps, gpointer data);
156 static GValueArray* __mmplayer_gst_decode_autoplug_sort(GstElement *bin, GstPad* pad, GstCaps * caps, GValueArray *factories, gpointer data);
157 static void __mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad* new_pad, gpointer data);
158 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
159 static void __mmplayer_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
160 static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
161 static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
163 static void __mmplayer_typefind_have_type( GstElement *tf, guint probability, GstCaps *caps, gpointer data);
164 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
165 static void __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data);
166 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
167 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
168 static gboolean __mmplayer_is_omx_decoder_type(mm_player_t* player); // mp3
169 static void __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
170 //static void __mmplayer_check_video_zero_cpoy(mm_player_t* player, GstElementFactory* factory);
172 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
173 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
174 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
176 static void __mmplayer_gst_rtp_no_more_pads (GstElement *element, gpointer data);
177 //static void __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
178 static void __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
179 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player );
180 static gboolean __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
183 static void __mmplayer_init_factories(mm_player_t* player);
184 static void __mmplayer_release_factories(mm_player_t* player);
185 static void __mmplayer_release_misc(mm_player_t* player);
186 static void __mmplayer_release_misc_post(mm_player_t* player);
187 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
189 static int __mmplayer_gst_set_state (mm_player_t* player, GstElement * pipeline, GstState state, gboolean async, gint timeout );
190 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
191 static gboolean __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
193 int __mmplayer_switch_audio_sink (mm_player_t* player);
194 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
195 static int __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
196 static GstPadProbeReturn __mmplayer_audio_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
197 static GstPadProbeReturn __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
198 static GstPadProbeReturn __mmplayer_subtitle_adjust_position_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
199 static int __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index);
201 static gboolean __mmplayer_dump_pipeline_state( mm_player_t* player );
202 static gboolean __mmplayer_check_subtitle( mm_player_t* player );
203 static gboolean __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error );
204 static gboolean __mmplayer_handle_streaming_error ( mm_player_t* player, GstMessage * message );
205 static void __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms );
206 static void __mmplayer_cancel_eos_timer( mm_player_t* player );
207 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
208 static gboolean __mmplayer_link_decoder( mm_player_t* player,GstPad *srcpad);
209 static gboolean __mmplayer_link_sink( mm_player_t* player,GstPad *srcpad);
210 static int __mmplayer_handle_missed_plugin(mm_player_t* player);
211 static int __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
212 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
213 static void __mmplayer_add_sink( mm_player_t* player, GstElement* sink);
214 static void __mmplayer_del_sink( mm_player_t* player, GstElement* sink);
215 static void __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
216 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force);
217 static gpointer __mmplayer_next_play_thread(gpointer data);
218 static gpointer __mmplayer_repeat_thread(gpointer data);
219 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
222 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
223 //static gboolean __mmplayer_dump_buffer_probe_cb(GstPad *pad, GstBuffer *buffer, gpointer u_data);
224 static void __mmplayer_release_dump_list (GList *dump_list);
226 static int __gst_realize(mm_player_t* player);
227 static int __gst_unrealize(mm_player_t* player);
228 static int __gst_start(mm_player_t* player);
229 static int __gst_stop(mm_player_t* player);
230 static int __gst_pause(mm_player_t* player, gboolean async);
231 static int __gst_resume(mm_player_t* player, gboolean async);
232 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
233 GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
234 gint64 cur, GstSeekType stop_type, gint64 stop );
235 static int __gst_pending_seek ( mm_player_t* player );
237 static int __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called);
238 static int __gst_get_position(mm_player_t* player, int format, unsigned long *position);
239 static int __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
240 static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
241 static int __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
243 static gint __gst_handle_core_error( mm_player_t* player, int code );
244 static gint __gst_handle_library_error( mm_player_t* player, int code );
245 static gint __gst_handle_resource_error( mm_player_t* player, int code );
246 static gint __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message );
247 static gint __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error);
248 static gboolean __gst_send_event_to_sink( mm_player_t* player, GstEvent* event );
250 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
251 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
254 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
255 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
257 static void __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
258 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
261 const gchar * __get_state_name ( int state );
262 static gboolean __is_streaming( mm_player_t* player );
263 static gboolean __is_rtsp_streaming( mm_player_t* player );
264 static gboolean __is_wfd_streaming( mm_player_t* player );
265 static gboolean __is_live_streaming ( mm_player_t* player );
266 static gboolean __is_http_streaming( mm_player_t* player );
267 static gboolean __is_http_live_streaming( mm_player_t* player );
268 static gboolean __is_dash_streaming( mm_player_t* player );
269 static gboolean __is_smooth_streaming( mm_player_t* player );
270 static gboolean __is_http_progressive_down(mm_player_t* player);
272 static gboolean __is_es_buff_src(mm_player_t* player);
274 static gboolean __has_suffix(mm_player_t * player, const gchar * suffix);
276 static GstBusSyncReply __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data);
278 static int __mmplayer_realize_streaming_ext(mm_player_t* player);
279 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
280 static int __mmplayer_start_streaming_ext(mm_player_t *player);
281 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
282 static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
283 static void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id);
285 static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
286 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
287 static void __mmplayer_check_pipeline(mm_player_t* player);
288 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
289 static void __mmplayer_deactivate_old_path(mm_player_t *player);
290 #if 0 // We'll need this in future.
291 static int __mmplayer_gst_switching_element(mm_player_t *player, GstElement *search_from, const gchar *removal_name, const gchar *new_element_name);
294 static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg);
295 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
296 static gboolean __mmplayer_can_do_interrupt(mm_player_t *player);
298 /* device change post proc */
299 void __mmplayer_device_change_post_process(gpointer user);
300 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score);
301 void __mmplayer_inc_cb_score(mm_player_t* player);
302 void __mmplayer_post_proc_reset(mm_player_t* player);
303 void __mmplayer_device_change_trigger_post_process(mm_player_t* player);
304 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
305 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name);
308 static void __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data);
309 static void __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data);
310 static void __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data);
311 static void __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data);
312 static void __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data);
313 static gboolean __gst_seek_audio_data (GstElement * appsrc, guint64 position, gpointer user_data);
314 static gboolean __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data);
315 static gboolean __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data);
317 /*===========================================================================================
319 | FUNCTION DEFINITIONS |
321 ========================================================================================== */
325 print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
329 count = gst_tag_list_get_tag_size (list, tag);
331 debug_log("count = %d", count);
333 for (i = 0; i < count; i++) {
336 if (gst_tag_get_type (tag) == G_TYPE_STRING) {
337 if (!gst_tag_list_get_string_index (list, tag, i, &str))
338 g_assert_not_reached ();
341 g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
345 g_print (" %15s: %s\n", gst_tag_get_nick (tag), str);
347 g_print (" : %s\n", str);
355 /* implementing player FSM */
356 /* FIXIT : We need to handle state transition also at here since start api is no more sync */
358 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
360 MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
361 MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
362 // MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
363 // MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
365 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
367 //debug_log("incomming command : %d \n", command );
369 current_state = MMPLAYER_CURRENT_STATE(player);
370 pending_state = MMPLAYER_PENDING_STATE(player);
371 // target_state = MMPLAYER_TARGET_STATE(player);
372 // prev_state = MMPLAYER_PREV_STATE(player);
374 MMPLAYER_PRINT_STATE(player);
378 case MMPLAYER_COMMAND_CREATE:
380 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
382 if ( current_state == MM_PLAYER_STATE_NULL ||
383 current_state == MM_PLAYER_STATE_READY ||
384 current_state == MM_PLAYER_STATE_PAUSED ||
385 current_state == MM_PLAYER_STATE_PLAYING )
390 case MMPLAYER_COMMAND_DESTROY:
392 /* destroy can called anytime */
394 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
398 case MMPLAYER_COMMAND_REALIZE:
400 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
402 if ( pending_state != MM_PLAYER_STATE_NONE )
408 /* need ready state to realize */
409 if ( current_state == MM_PLAYER_STATE_READY )
412 if ( current_state != MM_PLAYER_STATE_NULL )
418 case MMPLAYER_COMMAND_UNREALIZE:
420 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
422 if ( current_state == MM_PLAYER_STATE_NULL )
427 case MMPLAYER_COMMAND_START:
429 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
431 if ( pending_state == MM_PLAYER_STATE_NONE )
433 if ( current_state == MM_PLAYER_STATE_PLAYING )
435 else if ( current_state != MM_PLAYER_STATE_READY &&
436 current_state != MM_PLAYER_STATE_PAUSED )
439 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
443 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
445 debug_log("player is going to paused state, just change the pending state as playing");
454 case MMPLAYER_COMMAND_STOP:
456 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
458 if ( current_state == MM_PLAYER_STATE_READY )
461 /* need playing/paused state to stop */
462 if ( current_state != MM_PLAYER_STATE_PLAYING &&
463 current_state != MM_PLAYER_STATE_PAUSED )
468 case MMPLAYER_COMMAND_PAUSE:
470 if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
473 if (player->doing_seek)
474 goto NOT_COMPLETED_SEEK;
476 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
478 if ( pending_state == MM_PLAYER_STATE_NONE )
480 if ( current_state == MM_PLAYER_STATE_PAUSED )
482 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
485 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
489 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
491 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
492 debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
500 case MMPLAYER_COMMAND_RESUME:
503 if (player->doing_seek)
504 goto NOT_COMPLETED_SEEK;
506 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
508 if ( pending_state == MM_PLAYER_STATE_NONE )
510 if ( current_state == MM_PLAYER_STATE_PLAYING )
512 else if ( current_state != MM_PLAYER_STATE_PAUSED )
515 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
519 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
521 debug_log("player is going to paused state, just change the pending state as playing");
533 player->cmd = command;
535 return MM_ERROR_NONE;
538 debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
539 MMPLAYER_STATE_GET_NAME(current_state), command);
540 return MM_ERROR_PLAYER_INVALID_STATE;
543 debug_warning("not completed seek");
544 return MM_ERROR_PLAYER_DOING_SEEK;
547 debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
548 return MM_ERROR_PLAYER_NO_OP;
551 debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
552 return MM_ERROR_PLAYER_NO_OP;
556 __mmplayer_gst_set_state (mm_player_t* player, GstElement * element, GstState state, gboolean async, gint timeout) // @
558 GstState element_state = GST_STATE_VOID_PENDING;
559 GstState element_pending_state = GST_STATE_VOID_PENDING;
560 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
564 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
565 return_val_if_fail ( element, MM_ERROR_INVALID_ARGUMENT );
567 debug_log("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
570 ret = gst_element_set_state(element, state);
572 if ( ret == GST_STATE_CHANGE_FAILURE )
574 debug_error("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
576 /* dump state of all element */
577 __mmplayer_dump_pipeline_state( player );
579 return MM_ERROR_PLAYER_INTERNAL;
582 /* return here so state transition to be done in async mode */
585 debug_log("async state transition. not waiting for state complete.\n");
586 return MM_ERROR_NONE;
589 /* wait for state transition */
590 ret = gst_element_get_state( element, &element_state, &element_pending_state, timeout * GST_SECOND );
592 if ( ret == GST_STATE_CHANGE_FAILURE || ( state != element_state ) )
594 debug_error("failed to change [%s] element state to [%s] within %d sec\n",
595 GST_ELEMENT_NAME(element),
596 gst_element_state_get_name(state), timeout );
598 debug_error(" [%s] state : %s pending : %s \n",
599 GST_ELEMENT_NAME(element),
600 gst_element_state_get_name(element_state),
601 gst_element_state_get_name(element_pending_state) );
603 /* dump state of all element */
604 __mmplayer_dump_pipeline_state( player );
606 return MM_ERROR_PLAYER_INTERNAL;
609 debug_log("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
613 return MM_ERROR_NONE;
617 __mmplayer_videostream_cb(GstElement *element, void *data,
618 int width, int height, gpointer user_data) // @
620 mm_player_t* player = (mm_player_t*)user_data;
622 return_if_fail ( player );
626 if (player->is_drm_file)
628 MMMessageParamType msg_param = { 0, };
629 debug_warning("not supported in drm file");
630 msg_param.code = MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
631 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
633 else if ( !player->set_mode.media_packet_video_stream && player->video_stream_cb)
635 MMPlayerVideoStreamDataType stream;
637 /* clear stream data structure */
638 memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
640 stream.data[0] = data;
641 stream.length_total = width * height * 4; // for rgb 32bit
642 stream.height = height;
643 stream.width = width;
644 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
651 __mmplayer_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer data)
653 mm_player_t* player = (mm_player_t*)data;
655 return_if_fail ( player );
659 if (player->video_frame_render_error_cb )
663 int surface_type = 0;
664 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
665 switch (surface_type)
667 case MM_DISPLAY_SURFACE_X_EXT:
668 player->video_frame_render_error_cb((unsigned int*)error_id, player->video_frame_render_error_cb_user_param);
669 debug_log("display surface type(X_EXT) : render error callback(%p) is finished", player->video_frame_render_error_cb);
672 debug_error("video_frame_render_error_cb was set, but this surface type(%d) is not supported", surface_type);
678 debug_error("could not get surface type");
683 debug_warning("video_frame_render_error_cb was not set");
690 __mmplayer_device_change_post_process(gpointer user)
692 mm_player_t* player = (mm_player_t*)user;
693 unsigned long position = 0;
694 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
695 MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
700 ! player->pipeline ||
701 ! player->pipeline->mainbin ||
702 ! player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
707 current_state = MMPLAYER_CURRENT_STATE(player);
708 pending_state = MMPLAYER_PENDING_STATE(player);
710 if (player->post_proc.need_pause_and_resume)
712 debug_log("pausing");
713 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
714 ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
715 gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED);
718 /* seek should be done within pause and resume */
719 if (player->post_proc.need_seek)
721 debug_log("seeking");
722 __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position);
723 debug_log(">> seek to current position = %ld ms", position);
724 __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE);
727 if (player->post_proc.need_pause_and_resume)
729 debug_log("resuming");
730 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
731 ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
732 gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING);
736 if (player->post_proc.need_async)
738 debug_log("setting async");
740 /* TODO : need some comment here */
741 if (player->pipeline->textbin && player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst)
742 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
747 __mmplayer_post_proc_reset(player);
751 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score)
753 return_if_fail(player);
754 player->post_proc.required_cb_score = score;
755 debug_log("set required score to : %d", score);
758 void __mmplayer_inc_cb_score(mm_player_t* player)
760 return_if_fail(player);
761 player->post_proc.cb_score++;
762 debug_log("post proc cb score increased to %d", player->post_proc.cb_score);
765 void __mmplayer_post_proc_reset(mm_player_t* player)
767 return_if_fail(player);
769 /* check if already triggered */
770 if (player->post_proc.id)
772 /* TODO : need to consider multiple main context. !!!! */
773 if (FALSE == g_source_remove(player->post_proc.id) )
775 debug_error("failed to remove exist post_proc item");
777 player->post_proc.id = 0;
780 memset(&player->post_proc, 0, sizeof(mm_player_post_proc_t));
782 /* set default required cb score 1 as only audio device has changed in this case.
783 if display status is changed with audio device, required cb score is set 2 in display status callback.
784 this logic bases on the assumption which audio device callback is called after calling display status callback. */
785 player->post_proc.required_cb_score = 1;
789 __mmplayer_device_change_trigger_post_process(mm_player_t* player)
791 return_if_fail(player);
794 if ( player->post_proc.cb_score < player->post_proc.required_cb_score )
796 /* wait for next turn */
797 debug_log("wait for next turn. required cb score : %d current score : %d\n",
798 player->post_proc.required_cb_score, player->post_proc.cb_score);
802 /* check if already triggered */
803 if (player->post_proc.id)
805 /* TODO : need to consider multiple main context. !!!! */
806 if (FALSE == g_source_remove(player->post_proc.id) )
808 debug_error("failed to remove exist post_proc item");
810 player->post_proc.id = 0;
813 player->post_proc.id = g_idle_add((GSourceFunc)__mmplayer_device_change_post_process, (gpointer)player);
816 /* NOTE : Sound module has different latency according to output device So,
817 * synchronization problem can be happened whenever device is changed.
818 * To avoid this issue, we do reset avsystem or seek as workaroud.
821 __mmplayer_sound_device_info_changed_cb_func (MMSoundDevice_t device_h, int changed_info_type, void *user_data)
824 mm_sound_device_type_e device_type;
825 mm_player_t* player = (mm_player_t*) user_data;
827 return_if_fail( player );
829 debug_warning("device_info_changed_cb is called, device_h[0x%x], changed_info_type[%d]\n", device_h, changed_info_type);
831 __mmplayer_inc_cb_score(player);
833 /* get device type with device_h*/
834 ret = mm_sound_get_device_type(device_h, &device_type);
836 debug_error("failed to mm_sound_get_device_type()\n");
839 /* do pause and resume only if video is playing */
840 if ( player->videodec_linked && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING )
844 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
845 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
846 case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
847 case MM_SOUND_DEVICE_TYPE_HDMI:
848 case MM_SOUND_DEVICE_TYPE_MIRRORING:
850 player->post_proc.need_pause_and_resume = TRUE;
855 debug_log("do nothing");
858 debug_warning("dispatched");
860 __mmplayer_device_change_trigger_post_process(player);
863 /* This function should be called after the pipeline goes PAUSED or higher
866 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
868 static gboolean has_duration = FALSE;
869 static gboolean has_video_attrs = FALSE;
870 static gboolean has_audio_attrs = FALSE;
871 static gboolean has_bitrate = FALSE;
872 gboolean missing_only = FALSE;
873 gboolean all = FALSE;
875 GstStructure* p = NULL;
876 MMHandleType attrs = 0;
878 gint stream_service_type = STREAMING_SERVICE_NONE;
883 return_val_if_fail ( player, FALSE );
885 /* check player state here */
886 if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
887 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING )
889 /* give warning now only */
890 debug_warning("be careful. content attributes may not available in this state ");
893 /* get content attribute first */
894 attrs = MMPLAYER_GET_ATTRS(player);
897 debug_error("cannot get content attribute");
901 /* get update flag */
903 if ( flag & ATTR_MISSING_ONLY )
906 debug_log("updating missed attr only");
909 if ( flag & ATTR_ALL )
912 has_duration = FALSE;
913 has_video_attrs = FALSE;
914 has_audio_attrs = FALSE;
917 debug_log("updating all attrs");
920 if ( missing_only && all )
922 debug_warning("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
923 missing_only = FALSE;
926 if ( (flag & ATTR_DURATION) || (!has_duration && missing_only) || all )
928 debug_log("try to update duration");
929 has_duration = FALSE;
931 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
933 player->duration = dur_nsec;
934 debug_warning("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
937 /* try to get streaming service type */
938 stream_service_type = __mmplayer_get_stream_service_type( player );
939 mm_attrs_set_int_by_name ( attrs, "streaming_type", stream_service_type );
941 /* check duration is OK */
942 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
944 /* FIXIT : find another way to get duration here. */
945 debug_error("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
950 mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
955 if ( (flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all )
957 /* update audio params
958 NOTE : We need original audio params and it can be only obtained from src pad of audio
959 decoder. Below code only valid when we are not using 'resampler' just before
962 debug_log("try to update audio attrs");
963 has_audio_attrs = FALSE;
965 if ( player->pipeline->audiobin &&
966 player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
968 GstCaps *caps_a = NULL;
970 gint samplerate = 0, channels = 0;
972 pad = gst_element_get_static_pad(
973 player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
977 caps_a = gst_pad_get_current_caps( pad );
981 p = gst_caps_get_structure (caps_a, 0);
983 mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
985 gst_structure_get_int (p, "rate", &samplerate);
986 mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
988 gst_structure_get_int (p, "channels", &channels);
989 mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
991 secure_debug_log("samplerate : %d channels : %d", samplerate, channels);
993 gst_caps_unref( caps_a );
996 has_audio_attrs = TRUE;
1000 debug_warning("not ready to get audio caps");
1003 gst_object_unref( pad );
1007 debug_warning("failed to get pad from audiosink");
1012 if ( (flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all )
1014 debug_log("try to update video attrs");
1015 has_video_attrs = FALSE;
1017 if ( player->pipeline->videobin &&
1018 player->pipeline->videobin[MMPLAYER_V_SINK].gst )
1020 GstCaps *caps_v = NULL;
1025 pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
1028 caps_v = gst_pad_get_current_caps( pad );
1030 /* Use v_stream_caps, if fail to get video_sink sink pad*/
1031 if (!caps_v && player->v_stream_caps)
1033 caps_v = player->v_stream_caps;
1034 gst_caps_ref(caps_v);
1039 p = gst_caps_get_structure (caps_v, 0);
1040 gst_structure_get_int (p, "width", &width);
1041 mm_attrs_set_int_by_name(attrs, "content_video_width", width);
1043 gst_structure_get_int (p, "height", &height);
1044 mm_attrs_set_int_by_name(attrs, "content_video_height", height);
1046 gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
1048 secure_debug_log("width : %d height : %d", width, height );
1050 gst_caps_unref( caps_v );
1055 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
1056 secure_debug_log("fps : %d", tmpNu / tmpDe);
1059 has_video_attrs = TRUE;
1063 debug_log("no negitiated caps from videosink");
1065 gst_object_unref( pad );
1070 debug_log("no videosink sink pad");
1076 if ( (flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all )
1078 has_bitrate = FALSE;
1080 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
1081 if (player->duration)
1083 guint64 data_size = 0;
1085 if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1087 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1089 if (stat(path, &sb) == 0)
1091 data_size = (guint64)sb.st_size;
1094 else if (MMPLAYER_IS_HTTP_STREAMING(player))
1096 data_size = player->http_content_size;
1098 debug_log("try to update bitrate : data_size = %lld", data_size);
1102 guint64 bitrate = 0;
1103 guint64 msec_dur = 0;
1105 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
1106 bitrate = data_size * 8 * 1000 / msec_dur;
1107 secure_debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
1108 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
1113 if (MMPLAYER_IS_RTSP_STREAMING(player))
1115 if(player->total_bitrate)
1117 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
1125 if ( mmf_attrs_commit ( attrs ) )
1127 debug_error("failed to update attributes\n");
1136 gint __mmplayer_get_stream_service_type( mm_player_t* player )
1138 gint streaming_type = STREAMING_SERVICE_NONE;
1142 return_val_if_fail ( player &&
1144 player->pipeline->mainbin &&
1145 player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
1148 /* streaming service type if streaming */
1149 if ( ! MMPLAYER_IS_STREAMING(player) )
1150 return STREAMING_SERVICE_NONE;
1152 if (MMPLAYER_IS_HTTP_STREAMING(player))
1154 streaming_type = (player->duration == 0) ?
1155 STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
1158 switch ( streaming_type )
1160 case STREAMING_SERVICE_LIVE:
1161 debug_log("it's live streaming");
1163 case STREAMING_SERVICE_VOD:
1164 debug_log("it's vod streaming");
1166 case STREAMING_SERVICE_NONE:
1167 debug_error("should not get here");
1170 debug_error("should not get here");
1173 player->streaming_type = streaming_type;
1176 return streaming_type;
1180 /* this function sets the player state and also report
1181 * it to applicaton by calling callback function
1184 __mmplayer_set_state(mm_player_t* player, int state) // @
1186 MMMessageParamType msg = {0, };
1187 int asm_result = MM_ERROR_NONE;
1188 gboolean post_bos = FALSE;
1189 gboolean interrupted_by_asm = FALSE;
1190 int ret = MM_ERROR_NONE;
1192 return_val_if_fail ( player, FALSE );
1194 if ( MMPLAYER_CURRENT_STATE(player) == state )
1196 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
1197 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1201 /* update player states */
1202 MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
1203 MMPLAYER_CURRENT_STATE(player) = state;
1205 /* FIXIT : it's better to do like below code
1206 if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player) )
1207 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1208 and add more code to handling PENDING_STATE.
1210 if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
1211 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1214 MMPLAYER_PRINT_STATE(player);
1216 /* do some FSM stuffs before posting new state to application */
1217 interrupted_by_asm = player->sm.by_asm_cb;
1219 switch ( MMPLAYER_CURRENT_STATE(player) )
1221 case MM_PLAYER_STATE_NULL:
1222 case MM_PLAYER_STATE_READY:
1224 if (player->cmd == MMPLAYER_COMMAND_STOP)
1226 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP, FALSE);
1227 if ( asm_result != MM_ERROR_NONE )
1229 debug_error("failed to set asm state to stop\n");
1230 return MM_ERROR_POLICY_INTERNAL;
1236 case MM_PLAYER_STATE_PAUSED:
1238 if ( ! player->sent_bos )
1241 #define MMPLAYER_MAX_SOUND_PRIORITY 3
1243 /* it's first time to update all content attrs. */
1244 _mmplayer_update_content_attrs( player, ATTR_ALL );
1245 /* set max sound priority to keep own sound and not to mute other's one */
1246 mm_attrs_get_int_by_name(player->attrs, "content_video_found", &found);
1249 mm_attrs_get_int_by_name(player->attrs, "content_audio_found", &found);
1252 debug_log("set max audio priority");
1253 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "priority", MMPLAYER_MAX_SOUND_PRIORITY, NULL);
1259 /* add audio callback probe if condition is satisfied */
1260 if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
1262 __mmplayer_configure_audio_callback(player);
1263 /* FIXIT : handle return value */
1266 if (!MMPLAYER_IS_STREAMING(player) || (player->streamer && !player->streamer->is_buffering))
1268 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE, FALSE);
1271 debug_error("failed to set asm state to PAUSE\n");
1272 return MM_ERROR_POLICY_INTERNAL;
1278 case MM_PLAYER_STATE_PLAYING:
1280 /* try to get content metadata */
1281 if ( ! player->sent_bos )
1283 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
1284 * c-api since c-api doesn't use _start() anymore. It may not work propery with
1285 * legacy mmfw-player api */
1286 _mmplayer_update_content_attrs( player, ATTR_MISSING_ONLY);
1289 if ( (player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME) )
1291 if (!player->sent_bos)
1293 __mmplayer_handle_missed_plugin ( player );
1296 /* update ASM state for video and streaming buffering */
1297 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING, TRUE);
1298 if (asm_result != MM_ERROR_NONE)
1300 if (player->pipeline->videobin)
1302 MMMessageParamType msg = {0, };
1304 debug_error("failed to go ahead because of video conflict\n");
1306 msg.union_type = MM_MSG_UNION_CODE;
1307 msg.code = MM_ERROR_POLICY_INTERRUPTED;
1308 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
1310 _mmplayer_unrealize((MMHandleType)player);
1314 debug_error("failed to play by ASM error : 0x%X\n", asm_result);
1315 _mmplayer_pause((MMHandleType)player);
1319 return MM_ERROR_POLICY_INTERNAL;
1323 if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
1325 /* initialize because auto resume is done well. */
1326 player->resumed_by_rewind = FALSE;
1327 player->playback_rate = 1.0;
1330 if ( !player->sent_bos )
1332 /* check audio codec field is set or not
1333 * we can get it from typefinder or codec's caps.
1335 gchar *audio_codec = NULL;
1336 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
1338 /* The codec format can't be sent for audio only case like amr, mid etc.
1339 * Because, parser don't make related TAG.
1340 * So, if it's not set yet, fill it with found data.
1342 if ( ! audio_codec )
1344 if ( g_strrstr(player->type, "audio/midi"))
1346 audio_codec = g_strdup("MIDI");
1349 else if ( g_strrstr(player->type, "audio/x-amr"))
1351 audio_codec = g_strdup("AMR");
1353 else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
1355 audio_codec = g_strdup("AAC");
1359 audio_codec = g_strdup("unknown");
1361 mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1363 MMPLAYER_FREEIF(audio_codec);
1364 mmf_attrs_commit(player->attrs);
1365 debug_log("set audio codec type with caps\n");
1373 case MM_PLAYER_STATE_NONE:
1375 debug_warning("invalid target state, there is nothing to do.\n");
1380 /* post message to application */
1381 if (MMPLAYER_TARGET_STATE(player) == state)
1383 /* fill the message with state of player */
1384 msg.state.previous = MMPLAYER_PREV_STATE(player);
1385 msg.state.current = MMPLAYER_CURRENT_STATE(player);
1387 debug_log ("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
1389 /* state changed by asm callback */
1390 if ( interrupted_by_asm )
1392 msg.union_type = MM_MSG_UNION_CODE;
1393 msg.code = player->sm.event_src;
1394 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
1396 /* state changed by usecase */
1399 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
1404 debug_log ("intermediate state, do nothing.\n");
1405 MMPLAYER_PRINT_STATE(player);
1411 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
1412 player->sent_bos = TRUE;
1419 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
1421 return_val_if_fail( player, FALSE );
1423 if ( !player->msg_cb )
1428 //debug_log("Message (type : %d) will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
1430 player->msg_cb(msgtype, param, player->msg_cb_param);
1435 static gpointer __mmplayer_next_play_thread(gpointer data)
1437 mm_player_t* player = (mm_player_t*) data;
1438 MMPlayerGstElement *mainbin = NULL;
1440 return_val_if_fail ( player, NULL );
1442 g_mutex_lock(&player->next_play_thread_mutex);
1443 while ( ! player->next_play_thread_exit )
1445 debug_log("next play thread started. waiting for signal.\n");
1446 g_cond_wait(&player->next_play_thread_cond, &player->next_play_thread_mutex );
1448 debug_log("re building pipeline for next play.\n");
1450 if ( player->next_play_thread_exit )
1452 if(player->pp_rebuilding)
1454 player->pp_rebuilding = false;
1455 MMPLAYER_PLAYBACK_UNLOCK(player);
1457 debug_log("exiting next play thread\n");
1461 mainbin = player->pipeline->mainbin;
1463 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
1464 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
1465 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
1466 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
1467 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
1469 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
1471 g_mutex_unlock(&player->next_play_thread_mutex);
1476 static gpointer __mmplayer_repeat_thread(gpointer data)
1478 mm_player_t* player = (mm_player_t*) data;
1479 gboolean ret_value = FALSE;
1480 MMHandleType attrs = 0;
1483 return_val_if_fail ( player, NULL );
1485 g_mutex_lock(&player->repeat_thread_mutex);
1486 while ( ! player->repeat_thread_exit )
1488 debug_log("repeat thread started. waiting for signal.\n");
1489 g_cond_wait(&player->repeat_thread_cond, &player->repeat_thread_mutex );
1491 if ( player->repeat_thread_exit )
1493 debug_log("exiting repeat thread\n");
1499 g_mutex_lock(&player->cmd_lock);
1501 attrs = MMPLAYER_GET_ATTRS(player);
1503 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1505 debug_error("can not get play count\n");
1509 if ( player->section_repeat )
1511 ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1515 if ( player->playback_rate < 0.0 )
1517 player->resumed_by_rewind = TRUE;
1518 _mmplayer_set_mute((MMHandleType)player, 0);
1519 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1522 ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
1523 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1524 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1527 player->sent_bos = FALSE;
1532 debug_error("failed to set position to zero for rewind\n");
1536 /* decrease play count */
1539 /* we successeded to rewind. update play count and then wait for next EOS */
1542 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1544 /* commit attribute */
1545 if ( mmf_attrs_commit ( attrs ) )
1547 debug_error("failed to commit attribute\n");
1552 g_mutex_unlock(&player->cmd_lock);
1555 g_mutex_unlock(&player->repeat_thread_mutex);
1560 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
1562 MMHandleType attrs = 0;
1563 guint64 data_size = 0;
1565 unsigned long pos_msec = 0;
1568 return_if_fail( player && player->pipeline && player->pipeline->mainbin);
1570 __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_msec); // update last_position
1572 attrs = MMPLAYER_GET_ATTRS(player);
1575 debug_error("fail to get attributes.\n");
1579 if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1581 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1583 if (stat(path, &sb) == 0)
1585 data_size = (guint64)sb.st_size;
1588 else if (MMPLAYER_IS_HTTP_STREAMING(player))
1590 data_size = player->http_content_size;
1593 __mm_player_streaming_buffering( player->streamer,
1596 player->last_position,
1599 __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
1606 __mmplayer_handle_buffering_message ( mm_player_t* player )
1608 MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1609 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1610 MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1611 MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1613 return_if_fail ( player );
1615 prev_state = MMPLAYER_PREV_STATE(player);
1616 current_state = MMPLAYER_CURRENT_STATE(player);
1617 target_state = MMPLAYER_TARGET_STATE(player);
1618 pending_state = MMPLAYER_PENDING_STATE(player);
1620 if (MMPLAYER_IS_LIVE_STREAMING(player))
1623 if ( !player->streamer->is_buffering )
1625 debug_log( "player state : prev %s, current %s, pending %s, target %s \n",
1626 MMPLAYER_STATE_GET_NAME(prev_state),
1627 MMPLAYER_STATE_GET_NAME(current_state),
1628 MMPLAYER_STATE_GET_NAME(pending_state),
1629 MMPLAYER_STATE_GET_NAME(target_state));
1631 /* NOTE : if buffering has done, player has to go to target state. */
1632 switch ( target_state )
1634 case MM_PLAYER_STATE_PAUSED :
1636 switch ( pending_state )
1638 case MM_PLAYER_STATE_PLAYING:
1640 __gst_pause ( player, TRUE );
1644 case MM_PLAYER_STATE_PAUSED:
1646 debug_log("player is already going to paused state, there is nothing to do.\n");
1650 case MM_PLAYER_STATE_NONE:
1651 case MM_PLAYER_STATE_NULL:
1652 case MM_PLAYER_STATE_READY:
1655 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1662 case MM_PLAYER_STATE_PLAYING :
1664 switch ( pending_state )
1666 case MM_PLAYER_STATE_NONE:
1668 if (current_state != MM_PLAYER_STATE_PLAYING)
1669 __gst_resume ( player, TRUE );
1673 case MM_PLAYER_STATE_PAUSED:
1675 /* NOTE: It should be worked as asynchronously.
1676 * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1678 __gst_resume ( player, TRUE );
1682 case MM_PLAYER_STATE_PLAYING:
1684 debug_log("player is already going to playing state, there is nothing to do.\n");
1688 case MM_PLAYER_STATE_NULL:
1689 case MM_PLAYER_STATE_READY:
1692 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1699 case MM_PLAYER_STATE_NULL :
1700 case MM_PLAYER_STATE_READY :
1701 case MM_PLAYER_STATE_NONE :
1704 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1711 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1712 * it's for stopping the pipeline clock to prevent dropping the data in sink element.
1714 switch ( pending_state )
1716 case MM_PLAYER_STATE_NONE:
1718 if (current_state != MM_PLAYER_STATE_PAUSED)
1720 debug_log("set pause state during buffering\n");
1721 __gst_pause ( player, TRUE );
1723 // to cover the weak-signal environment.
1724 if (MMPLAYER_IS_RTSP_STREAMING(player))
1726 unsigned long position = 0;
1727 gint64 pos_msec = 0;
1729 debug_log("[RTSP] seek to the buffering start point\n");
1731 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
1733 debug_error("failed to get position\n");
1738 pos_msec = position * G_GINT64_CONSTANT(1000000);
1740 __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
1741 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1742 pos_msec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1748 case MM_PLAYER_STATE_PLAYING:
1750 __gst_pause ( player, TRUE );
1754 case MM_PLAYER_STATE_PAUSED:
1759 case MM_PLAYER_STATE_NULL:
1760 case MM_PLAYER_STATE_READY:
1763 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1771 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
1773 MMPlayerGstElement *textbin;
1776 return_if_fail ( player &&
1778 player->pipeline->textbin);
1780 return_if_fail (player->pipeline->textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst);
1782 textbin = player->pipeline->textbin;
1786 debug_log("Drop subtitle text after getting EOS\n");
1788 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
1789 g_object_set(textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1791 player->is_subtitle_force_drop = TRUE;
1795 if (player->is_subtitle_force_drop == TRUE)
1797 debug_log("Enable subtitle data path without drop\n");
1799 // player->display_stat = util_get_is_connected_external_display();
1801 g_object_set(textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1802 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
1804 debug_log ("non-connected with external display");
1806 player->is_subtitle_force_drop = FALSE;
1812 __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
1814 mm_player_t* player = (mm_player_t*) data;
1815 gboolean ret = TRUE;
1816 static gboolean async_done = FALSE;
1818 return_val_if_fail ( player, FALSE );
1819 return_val_if_fail ( msg && GST_IS_MESSAGE(msg), FALSE );
1821 switch ( GST_MESSAGE_TYPE( msg ) )
1823 case GST_MESSAGE_UNKNOWN:
1824 debug_log("unknown message received\n");
1827 case GST_MESSAGE_EOS:
1829 MMHandleType attrs = 0;
1832 debug_log("GST_MESSAGE_EOS received\n");
1834 /* NOTE : EOS event is comming multiple time. watch out it */
1835 /* check state. we only process EOS when pipeline state goes to PLAYING */
1836 if ( ! (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) )
1838 debug_log("EOS received on non-playing state. ignoring it\n");
1842 __mmplayer_drop_subtitle(player, TRUE);
1844 if ( (player->audio_stream_cb) && (player->set_mode.pcm_extraction) && (!player->audio_stream_render_cb_ex))
1848 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1850 debug_log("release audio callback\n");
1852 /* release audio callback */
1853 gst_pad_remove_probe (pad, player->audio_cb_probe_id);
1854 player->audio_cb_probe_id = 0;
1855 /* audio callback should be free because it can be called even though probe remove.*/
1856 player->audio_stream_cb = NULL;
1857 player->audio_stream_cb_user_param = NULL;
1861 /* rewind if repeat count is greater then zero */
1862 /* get play count */
1863 attrs = MMPLAYER_GET_ATTRS(player);
1867 gboolean smooth_repeat = FALSE;
1869 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1870 mm_attrs_get_int_by_name(attrs, "profile_smooth_repeat", &smooth_repeat);
1872 player->play_count = count;
1874 debug_log("remaining play count: %d, playback rate: %f\n", count, player->playback_rate);
1876 if ( count > 1 || count == -1 || player->playback_rate < 0.0 ) /* default value is 1 */
1878 if ( smooth_repeat )
1880 debug_log("smooth repeat enabled. seeking operation will be excuted in new thread\n");
1882 g_cond_signal( &player->repeat_thread_cond );
1890 if ( player->section_repeat )
1892 ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1896 if ( player->playback_rate < 0.0 )
1898 player->resumed_by_rewind = TRUE;
1899 _mmplayer_set_mute((MMHandleType)player, 0);
1900 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1903 __mmplayer_handle_eos_delay( player, player->ini.delay_before_repeat );
1906 player->sent_bos = FALSE;
1909 if ( MM_ERROR_NONE != ret_value )
1911 debug_error("failed to set position to zero for rewind\n");
1914 /* not posting eos when repeating */
1920 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-eos" );
1922 /* post eos message to application */
1923 __mmplayer_handle_eos_delay( player, player->ini.eos_delay );
1925 /* reset last position */
1926 player->last_position = 0;
1930 case GST_MESSAGE_ERROR:
1932 GError *error = NULL;
1933 gchar* debug = NULL;
1935 /* generating debug info before returning error */
1936 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-error" );
1938 /* get error code */
1939 gst_message_parse_error( msg, &error, &debug );
1941 if ( gst_structure_has_name ( gst_message_get_structure(msg), "streaming_error" ) )
1943 /* Note : the streaming error from the streaming source is handled
1944 * using __mmplayer_handle_streaming_error.
1946 __mmplayer_handle_streaming_error ( player, msg );
1948 /* dump state of all element */
1949 __mmplayer_dump_pipeline_state( player );
1953 /* traslate gst error code to msl error code. then post it
1954 * to application if needed
1956 __mmplayer_handle_gst_error( player, msg, error );
1960 debug_error ("error debug : %s", debug);
1965 if (MMPLAYER_IS_HTTP_PD(player))
1967 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
1970 MMPLAYER_FREEIF( debug );
1971 g_error_free( error );
1975 case GST_MESSAGE_WARNING:
1978 GError* error = NULL;
1980 gst_message_parse_warning(msg, &error, &debug);
1982 debug_log("warning : %s\n", error->message);
1983 debug_log("debug : %s\n", debug);
1985 MMPLAYER_POST_MSG( player, MM_MESSAGE_WARNING, NULL );
1987 MMPLAYER_FREEIF( debug );
1988 g_error_free( error );
1992 case GST_MESSAGE_TAG:
1994 debug_log("GST_MESSAGE_TAG\n");
1995 if ( ! __mmplayer_gst_extract_tag_from_msg( player, msg ) )
1997 debug_warning("failed to extract tags from gstmessage\n");
2002 case GST_MESSAGE_BUFFERING:
2004 MMMessageParamType msg_param = {0, };
2005 int asm_result = MM_ERROR_NONE;
2007 if (!MMPLAYER_IS_STREAMING(player))
2010 /* ignore the prev buffering message */
2011 if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (player->streamer->is_buffering_done == TRUE))
2013 gint buffer_percent = 0;
2015 gst_message_parse_buffering (msg, &buffer_percent);
2017 if (buffer_percent == MAX_BUFFER_PERCENT)
2019 debug_log ("Ignored all the previous buffering msg! (got %d%%)\n", buffer_percent);
2020 player->streamer->is_buffering_done = FALSE;
2026 /* update ASM state to ASM_STATE_PLAYING */
2027 /* fixed ASM_STATE_WAITING -> ASM_STATE_PLAYING for Samsunlink issue*/
2028 if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED))
2030 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_WAITING, TRUE);
2031 if ( asm_result != MM_ERROR_NONE )
2033 debug_warning("failed to set asm state to waiting, but keep going...\n");
2037 __mmplayer_update_buffer_setting(player, msg);
2039 __mmplayer_handle_buffering_message ( player );
2041 msg_param.connection.buffering = player->streamer->buffering_percent;
2042 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param );
2043 if (MMPLAYER_IS_RTSP_STREAMING(player) && (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT))
2045 if (player->doing_seek)
2047 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2049 player->doing_seek = FALSE;
2050 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2052 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2061 case GST_MESSAGE_STATE_CHANGED:
2063 MMPlayerGstElement *mainbin;
2064 const GValue *voldstate, *vnewstate, *vpending;
2065 GstState oldstate, newstate, pending;
2067 if ( ! ( player->pipeline && player->pipeline->mainbin ) )
2069 debug_error("player pipeline handle is null");
2073 mainbin = player->pipeline->mainbin;
2075 /* we only handle messages from pipeline */
2076 if( msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst )
2079 /* get state info from msg */
2080 voldstate = gst_structure_get_value (gst_message_get_structure(msg), "old-state");
2081 vnewstate = gst_structure_get_value (gst_message_get_structure(msg), "new-state");
2082 vpending = gst_structure_get_value (gst_message_get_structure(msg), "pending-state");
2084 oldstate = (GstState)voldstate->data[0].v_int;
2085 newstate = (GstState)vnewstate->data[0].v_int;
2086 pending = (GstState)vpending->data[0].v_int;
2088 debug_log("state changed [%s] : %s ---> %s final : %s\n",
2089 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
2090 gst_element_state_get_name( (GstState)oldstate ),
2091 gst_element_state_get_name( (GstState)newstate ),
2092 gst_element_state_get_name( (GstState)pending ) );
2094 if (oldstate == newstate)
2096 debug_log("pipeline reports state transition to old state");
2102 case GST_STATE_VOID_PENDING:
2105 case GST_STATE_NULL:
2108 case GST_STATE_READY:
2111 case GST_STATE_PAUSED:
2113 gboolean prepare_async = FALSE;
2114 gboolean is_drm = FALSE;
2116 if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
2117 __mmplayer_configure_audio_callback(player);
2119 if ( ! player->sent_bos && oldstate == GST_STATE_READY) // managed prepare async case
2121 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
2122 debug_log("checking prepare mode for async transition - %d", prepare_async);
2125 if ( MMPLAYER_IS_STREAMING(player) || prepare_async )
2127 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
2129 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
2131 __mm_player_streaming_set_content_bitrate(player->streamer,
2132 player->total_maximum_bitrate, player->total_bitrate);
2136 /* NOTE : should consider streaming case */
2137 /* check if drm file */
2138 if ((player->pipeline->mainbin[MMPLAYER_M_SRC].gst) &&
2139 (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm")))
2141 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
2145 player->is_drm_file = TRUE;
2151 case GST_STATE_PLAYING:
2153 /* for audio tunning */
2155 if (player->can_support_codec == 0x03) {
2157 mm_attrs_get_int_by_name(player->attrs, "sound_volume_type", &volume_type);
2158 volume_type |= MM_SOUND_VOLUME_GAIN_VIDEO;
2159 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "volumetype", volume_type, NULL);
2162 if ( MMPLAYER_IS_STREAMING(player) ) // managed prepare async case when buffering is completed
2164 // pending state should be reset oyherwise, it's still playing even though it's resumed after bufferging.
2165 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
2166 (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
2168 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING);
2172 if (player->src_changed)
2174 _mmplayer_update_content_attrs(player, ATTR_ALL);
2175 player->src_changed = FALSE;
2178 if (player->doing_seek && async_done)
2180 player->doing_seek = FALSE;
2182 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2193 case GST_MESSAGE_CLOCK_LOST:
2195 GstClock *clock = NULL;
2196 gst_message_parse_clock_lost (msg, &clock);
2197 debug_log("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2198 g_print ("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2200 if (((player->ini.provide_clock_for_music) && (!player->videodec_linked)) ||
2201 ((player->ini.provide_clock_for_movie) && (player->videodec_linked)))
2203 debug_log ("Provide clock is TRUE, do pause->resume\n");
2204 __gst_pause(player, FALSE);
2205 __gst_resume(player, FALSE);
2210 case GST_MESSAGE_NEW_CLOCK:
2212 GstClock *clock = NULL;
2213 gst_message_parse_new_clock (msg, &clock);
2214 debug_log("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2218 case GST_MESSAGE_ELEMENT:
2220 const gchar *structure_name;
2222 MMHandleType attrs = 0;
2224 attrs = MMPLAYER_GET_ATTRS(player);
2227 debug_error("cannot get content attribute");
2232 if(gst_message_get_structure(msg) == NULL)
2235 structure_name = gst_structure_get_name(gst_message_get_structure(msg));
2236 if(!strcmp(structure_name, "Language_list"))
2238 const GValue *lang_list = NULL;
2239 lang_list = gst_structure_get_value (gst_message_get_structure(msg), "lang_list");
2240 if(lang_list != NULL)
2242 count = g_list_length((GList *)g_value_get_pointer (lang_list));
2244 debug_log("Total audio tracks (from parser) = %d \n",count);
2248 if (!strcmp (structure_name, "Ext_Sub_Language_List"))
2250 const GValue *lang_list = NULL;
2251 MMPlayerLangStruct *temp = NULL;
2253 lang_list = gst_structure_get_value (gst_message_get_structure(msg), "lang_list");
2254 if (lang_list != NULL)
2256 count = g_list_length ((GList *)g_value_get_pointer (lang_list));
2259 player->subtitle_language_list = (GList *)g_value_get_pointer (lang_list);
2260 mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
2261 if (mmf_attrs_commit (attrs))
2262 debug_error("failed to commit.\n");
2263 debug_log("Total subtitle tracks = %d \n", count);
2267 temp = g_list_nth_data (player->subtitle_language_list, count - 1);
2268 debug_log ("value of lang_key is %s and lang_code is %s",
2269 temp->language_key, temp->language_code);
2275 /* custom message */
2276 if (!strcmp (structure_name, "audio_codec_not_supported")) {
2277 MMMessageParamType msg_param = {0,};
2278 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
2279 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
2284 case GST_MESSAGE_DURATION_CHANGED:
2286 debug_log("GST_MESSAGE_DURATION_CHANGED\n");
2287 ret = __mmplayer_gst_handle_duration(player, msg);
2290 debug_warning("failed to update duration");
2296 case GST_MESSAGE_ASYNC_START:
2298 debug_log("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2302 case GST_MESSAGE_ASYNC_DONE:
2304 debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2306 /* we only handle messages from pipeline */
2307 if( msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
2310 if (player->doing_seek)
2312 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2314 player->doing_seek = FALSE;
2315 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2317 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2319 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2320 (player->streamer) &&
2321 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
2322 (player->streamer->is_buffering == FALSE))
2324 GstQuery *query = NULL;
2325 gboolean busy = FALSE;
2328 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer)
2330 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
2331 if ( gst_element_query (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query ) )
2333 gst_query_parse_buffering_percent ( query, &busy, &percent);
2335 gst_query_unref (query);
2337 debug_log("buffered percent(%s): %d\n",
2338 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
2343 player->streamer->is_buffering = FALSE;
2344 __mmplayer_handle_buffering_message(player);
2354 #if 0 /* delete unnecessary logs */
2355 case GST_MESSAGE_REQUEST_STATE: debug_log("GST_MESSAGE_REQUEST_STATE\n"); break;
2356 case GST_MESSAGE_STEP_START: debug_log("GST_MESSAGE_STEP_START\n"); break;
2357 case GST_MESSAGE_QOS: debug_log("GST_MESSAGE_QOS\n"); break;
2358 case GST_MESSAGE_PROGRESS: debug_log("GST_MESSAGE_PROGRESS\n"); break;
2359 case GST_MESSAGE_ANY: debug_log("GST_MESSAGE_ANY\n"); break;
2360 case GST_MESSAGE_INFO: debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2361 case GST_MESSAGE_STATE_DIRTY: debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2362 case GST_MESSAGE_STEP_DONE: debug_log("GST_MESSAGE_STEP_DONE\n"); break;
2363 case GST_MESSAGE_CLOCK_PROVIDE: debug_log("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
2364 case GST_MESSAGE_STRUCTURE_CHANGE: debug_log("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
2365 case GST_MESSAGE_STREAM_STATUS: debug_log("GST_MESSAGE_STREAM_STATUS\n"); break;
2366 case GST_MESSAGE_APPLICATION: debug_log("GST_MESSAGE_APPLICATION\n"); break;
2367 case GST_MESSAGE_SEGMENT_START: debug_log("GST_MESSAGE_SEGMENT_START\n"); break;
2368 case GST_MESSAGE_SEGMENT_DONE: debug_log("GST_MESSAGE_SEGMENT_DONE\n"); break;
2369 case GST_MESSAGE_LATENCY: debug_log("GST_MESSAGE_LATENCY\n"); break;
2376 /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
2377 * gst_element_post_message api takes ownership of the message.
2379 //gst_message_unref( msg );
2385 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
2391 return_val_if_fail(player, FALSE);
2392 return_val_if_fail(msg, FALSE);
2394 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2395 (msg->src) && (msg->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst))
2397 debug_log("msg src : [%s]", GST_ELEMENT_NAME(GST_ELEMENT_CAST(msg->src)));
2399 if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes))
2401 debug_log("data total size of http content: %lld", bytes);
2402 player->http_content_size = bytes;
2407 /* handling audio clip which has vbr. means duration is keep changing */
2408 _mmplayer_update_content_attrs (player, ATTR_DURATION );
2418 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg) // @
2421 /* macro for better code readability */
2422 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
2423 if (gst_tag_list_get_string(tag_list, gsttag, &string)) \
2425 if (string != NULL)\
2427 secure_debug_log ( "update tag string : %s\n", string); \
2428 mm_attrs_set_string_by_name(attribute, playertag, string); \
2434 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
2435 GstSample *sample = NULL;\
2436 if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample))\
2438 GstMapInfo info = GST_MAP_INFO_INIT;\
2439 buffer = gst_sample_get_buffer(sample);\
2440 if (!gst_buffer_map(buffer, &info, GST_MAP_READ)){\
2441 debug_log("failed to get image data from tag");\
2444 secure_debug_log ( "update album cover data : %p, size : %d\n", info.data, info.size);\
2445 MMPLAYER_FREEIF(player->album_art); \
2446 player->album_art = (gchar *)g_malloc(info.size); \
2447 if (player->album_art) \
2449 memcpy(player->album_art, info.data, info.size); \
2450 mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, info.size); \
2451 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) \
2453 msg_param.data = (void *)player->album_art; \
2454 msg_param.size = info.size; \
2455 MMPLAYER_POST_MSG (player, MM_MESSAGE_IMAGE_BUFFER, &msg_param); \
2456 secure_debug_log ( "post message image buffer data : %p, size : %d\n", info.data, info.size); \
2459 gst_buffer_unmap(buffer, &info); \
2462 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
2463 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint))\
2467 if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) \
2469 if (player->updated_bitrate_count == 0) \
2470 mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
2471 if (player->updated_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2473 player->bitrate[player->updated_bitrate_count] = v_uint;\
2474 player->total_bitrate += player->bitrate[player->updated_maximum_bitrate_count]; \
2475 player->updated_bitrate_count++; \
2476 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate);\
2477 secure_debug_log ( "update bitrate %d[bps] of stream #%d.\n", v_uint, player->updated_bitrate_count);\
2480 else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) \
2482 if (player->updated_maximum_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2484 player->maximum_bitrate[player->updated_maximum_bitrate_count] = v_uint;\
2485 player->total_maximum_bitrate += player->maximum_bitrate[player->updated_maximum_bitrate_count]; \
2486 player->updated_maximum_bitrate_count++; \
2487 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate); \
2488 secure_debug_log ( "update maximum bitrate %d[bps] of stream #%d\n", v_uint, player->updated_maximum_bitrate_count);\
2493 mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
2499 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
2500 if (gst_tag_list_get_date(tag_list, gsttag, &date))\
2504 string = g_strdup_printf("%d", g_date_get_year(date));\
2505 mm_attrs_set_string_by_name(attribute, playertag, string);\
2506 secure_debug_log ( "metainfo year : %s\n", string);\
2507 MMPLAYER_FREEIF(string);\
2512 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
2513 if(gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64))\
2517 /* FIXIT : don't know how to store date */\
2523 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
2524 if(gst_tag_list_get_double(tag_list, gsttag, &v_double))\
2528 /* FIXIT : don't know how to store date */\
2534 /* function start */
2535 GstTagList* tag_list = NULL;
2537 MMHandleType attrs = 0;
2539 char *string = NULL;
2543 GstBuffer *buffer = NULL;
2545 MMMessageParamType msg_param = {0, };
2547 /* currently not used. but those are needed for above macro */
2548 //guint64 v_uint64 = 0;
2549 //gdouble v_double = 0;
2551 return_val_if_fail( player && msg, FALSE );
2553 attrs = MMPLAYER_GET_ATTRS(player);
2555 return_val_if_fail( attrs, FALSE );
2557 /* get tag list from gst message */
2558 gst_message_parse_tag(msg, &tag_list);
2560 /* store tags to player attributes */
2561 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
2562 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
2563 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
2564 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
2565 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
2566 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
2567 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
2568 MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
2569 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
2570 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
2571 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
2572 MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
2573 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
2574 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
2575 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
2576 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
2577 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
2578 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
2579 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
2580 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
2581 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
2582 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
2583 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
2584 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
2585 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
2586 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
2587 /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
2588 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
2589 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
2590 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
2591 MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
2592 MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
2593 MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
2594 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
2595 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
2596 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
2597 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
2598 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
2599 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
2600 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
2601 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
2602 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
2603 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
2604 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
2605 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
2606 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, attrs, "content_video_orientation");
2608 if ( mmf_attrs_commit ( attrs ) )
2609 debug_error("failed to commit.\n");
2611 gst_tag_list_free(tag_list);
2617 __mmplayer_gst_rtp_no_more_pads (GstElement *element, gpointer data) // @
2619 mm_player_t* player = (mm_player_t*) data;
2623 /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2624 * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2625 * num_dynamic_pad. and this is no-more-pad situation which means mo more pad will be added.
2626 * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2628 * [1] audio and video will be dumped with filesink.
2629 * [2] autoplugging is done by just using pad caps.
2630 * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
2631 * and the video will be dumped via filesink.
2633 if ( player->num_dynamic_pad == 0 )
2635 debug_log("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
2637 if ( ! __mmplayer_gst_remove_fakesink( player,
2638 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
2640 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
2641 * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
2642 * source element are not same. To overcome this situation, this function will called
2643 * several places and several times. Therefore, this is not an error case.
2649 /* create dot before error-return. for debugging */
2650 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-no-more-pad" );
2652 player->no_more_pad = TRUE;
2658 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink) // @
2660 GstElement* parent = NULL;
2662 return_val_if_fail(player && player->pipeline, FALSE);
2664 /* if we have no fakesink. this meas we are using decodebin2 which doesn'
2665 t need to add extra fakesink */
2666 return_val_if_fail(fakesink, TRUE);
2669 g_mutex_lock(&player->fsink_lock );
2671 if ( ! fakesink->gst )
2676 /* get parent of fakesink */
2677 parent = (GstElement*)gst_object_get_parent( (GstObject*)fakesink->gst );
2680 debug_log("fakesink already removed\n");
2684 gst_element_set_locked_state( fakesink->gst, TRUE );
2686 /* setting the state to NULL never returns async
2687 * so no need to wait for completion of state transiton
2689 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (fakesink->gst, GST_STATE_NULL) )
2691 debug_error("fakesink state change failure!\n");
2693 /* FIXIT : should I return here? or try to proceed to next? */
2697 /* remove fakesink from it's parent */
2698 if ( ! gst_bin_remove( GST_BIN( parent ), fakesink->gst ) )
2700 debug_error("failed to remove fakesink\n");
2702 gst_object_unref( parent );
2707 gst_object_unref( parent );
2709 debug_log("state-holder removed\n");
2711 gst_element_set_locked_state( fakesink->gst, FALSE );
2713 g_mutex_unlock( &player->fsink_lock );
2717 if ( fakesink->gst )
2719 gst_element_set_locked_state( fakesink->gst, FALSE );
2722 g_mutex_unlock( &player->fsink_lock );
2728 __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2730 GstPad *sinkpad = NULL;
2731 GstCaps* caps = NULL;
2732 GstElement* new_element = NULL;
2733 GstStructure* str = NULL;
2734 const gchar* name = NULL;
2736 mm_player_t* player = (mm_player_t*) data;
2740 return_if_fail( element && pad );
2741 return_if_fail( player &&
2743 player->pipeline->mainbin );
2746 /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2747 * num_dynamic_pad will decreased after creating a sinkbin.
2749 player->num_dynamic_pad++;
2750 debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2752 /* perform autoplugging if dump is disabled */
2753 if ( player->ini.rtsp_do_typefinding )
2755 /* create typefind */
2756 new_element = gst_element_factory_make( "typefind", NULL );
2757 if ( ! new_element )
2759 debug_error("failed to create typefind\n");
2763 MMPLAYER_SIGNAL_CONNECT( player,
2764 G_OBJECT(new_element),
2765 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2767 G_CALLBACK(__mmplayer_typefind_have_type),
2770 /* FIXIT : try to remove it */
2771 player->have_dynamic_pad = FALSE;
2773 else /* NOTE : use pad's caps directely. if enabled. what I am assuming is there's no elemnt has dynamic pad */
2775 debug_log("using pad caps to autopluging instead of doing typefind\n");
2777 caps = gst_pad_query_caps( pad, NULL );
2779 MMPLAYER_CHECK_NULL( caps );
2781 /* clear previous result*/
2782 player->have_dynamic_pad = FALSE;
2784 str = gst_caps_get_structure(caps, 0);
2788 debug_error ("cannot get structure from capse.\n");
2792 name = gst_structure_get_name (str);
2795 debug_error ("cannot get mimetype from structure.\n");
2799 if (strstr(name, "video"))
2802 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
2804 if (stype == MM_DISPLAY_SURFACE_NULL)
2806 if (player->v_stream_caps)
2808 gst_caps_unref(player->v_stream_caps);
2809 player->v_stream_caps = NULL;
2812 new_element = gst_element_factory_make("fakesink", NULL);
2813 player->num_dynamic_pad--;
2818 /* clear previous result*/
2819 player->have_dynamic_pad = FALSE;
2821 if ( !__mmplayer_try_to_plug_decodebin(player, pad, caps))
2823 debug_error("failed to autoplug for caps");
2827 /* check if there's dynamic pad*/
2828 if( player->have_dynamic_pad )
2830 debug_error("using pad caps assums there's no dynamic pad !\n");
2831 debug_error("try with enalbing rtsp_do_typefinding\n");
2835 gst_caps_unref( caps );
2841 /* excute new_element if created*/
2844 debug_log("adding new element to pipeline\n");
2846 /* set state to READY before add to bin */
2847 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2849 /* add new element to the pipeline */
2850 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element) )
2852 debug_error("failed to add autoplug element to bin\n");
2856 /* get pad from element */
2857 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2860 debug_error("failed to get sinkpad from autoplug element\n");
2865 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2867 debug_error("failed to link autoplug element\n");
2871 gst_object_unref (sinkpad);
2874 /* run. setting PLAYING here since streamming source is live source */
2875 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2882 STATE_CHANGE_FAILED:
2884 /* FIXIT : take care if new_element has already added to pipeline */
2886 gst_object_unref(GST_OBJECT(new_element));
2889 gst_object_unref(GST_OBJECT(sinkpad));
2892 gst_object_unref(GST_OBJECT(caps));
2894 /* FIXIT : how to inform this error to MSL ????? */
2895 /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2896 * then post an error to application
2902 /* FIXIT : check indent */
2905 __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2907 GstPad *sinkpad = NULL;
2908 GstCaps* caps = NULL;
2909 GstElement* new_element = NULL;
2910 enum MainElementID element_id = MMPLAYER_M_NUM;
2912 mm_player_t* player = (mm_player_t*) data;
2916 return_if_fail( element && pad );
2917 return_if_fail( player &&
2919 player->pipeline->mainbin );
2921 debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2924 debug_log("using pad caps to autopluging instead of doing typefind\n");
2925 caps = gst_pad_query_caps( pad );
2926 MMPLAYER_CHECK_NULL( caps );
2927 /* clear previous result*/
2928 player->have_dynamic_pad = FALSE;
2929 new_element = gst_element_factory_make("rtpmp2tdepay", "wfd_rtp_depay");
2932 debug_error ( "failed to create wfd rtp depay element\n" );
2935 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2936 /* add new element to the pipeline */
2937 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element) )
2939 debug_log("failed to add autoplug element to bin\n");
2942 /* get pad from element */
2943 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2946 debug_log("failed to get sinkpad from autoplug element\n");
2950 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2952 debug_log("failed to link autoplug element\n");
2955 gst_object_unref (sinkpad);
2957 pad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "src" );
2958 caps = gst_pad_query_caps( pad );
2959 MMPLAYER_CHECK_NULL( caps );
2960 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2961 /* create typefind */
2962 new_element = gst_element_factory_make( "typefind", NULL );
2963 if ( ! new_element )
2965 debug_log("failed to create typefind\n");
2969 MMPLAYER_SIGNAL_CONNECT( player,
2970 G_OBJECT(new_element),
2971 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2973 G_CALLBACK(__mmplayer_typefind_have_type),
2976 player->have_dynamic_pad = FALSE;
2979 /* excute new_element if created*/
2982 debug_log("adding new element to pipeline\n");
2984 /* set state to READY before add to bin */
2985 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2987 /* add new element to the pipeline */
2988 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element) )
2990 debug_log("failed to add autoplug element to bin\n");
2994 /* get pad from element */
2995 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2998 debug_log("failed to get sinkpad from autoplug element\n");
3003 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
3005 debug_log("failed to link autoplug element\n");
3009 gst_object_unref (sinkpad);
3012 /* run. setting PLAYING here since streamming source is live source */
3013 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
3016 /* store handle to futher manipulation */
3017 player->pipeline->mainbin[element_id].id = element_id;
3018 player->pipeline->mainbin[element_id].gst = new_element;
3024 STATE_CHANGE_FAILED:
3026 /* FIXIT : take care if new_element has already added to pipeline */
3028 gst_object_unref(GST_OBJECT(new_element));
3031 gst_object_unref(GST_OBJECT(sinkpad));
3034 gst_object_unref(GST_OBJECT(caps));
3036 /* FIXIT : how to inform this error to MSL ????? */
3037 /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
3038 * then post an error to application
3043 static GstPadProbeReturn
3044 __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
3046 debug_log ("pad blocked callback, blocked");
3047 return GST_PAD_PROBE_OK;
3051 __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data)
3053 mm_player_t* player = NULL;
3054 GstElement* pipeline = NULL;
3055 GstElement* selector = NULL;
3056 GstElement* fakesink = NULL;
3057 GstCaps* caps = NULL;
3058 GstStructure* str = NULL;
3059 const gchar* name = NULL;
3060 GstPad* sinkpad = NULL;
3061 GstPad* srcpad = NULL;
3062 gboolean first_track = FALSE;
3064 enum MainElementID elemId = MMPLAYER_M_NUM;
3065 MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
3068 player = (mm_player_t*)data;
3070 return_if_fail (elem && pad);
3071 return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3073 //debug_log ("pad-added signal handling\n");
3075 pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3077 /* get mimetype from caps */
3078 caps = gst_pad_query_caps (pad, NULL);
3081 debug_error ("cannot get caps from pad.\n");
3085 str = gst_caps_get_structure (caps, 0);
3088 debug_error ("cannot get structure from capse.\n");
3092 name = gst_structure_get_name (str);
3095 debug_error ("cannot get mimetype from structure.\n");
3099 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3100 //debug_log ("detected mimetype : %s\n", name);
3102 if (strstr(name, "video"))
3105 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
3107 /* don't make video because of not required, and not support multiple track */
3108 if (stype == MM_DISPLAY_SURFACE_NULL)
3110 debug_log ("no video sink by null surface or multiple track");
3111 gchar *caps_str = gst_caps_to_string(caps);
3112 if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
3114 player->set_mode.video_zc = TRUE;
3116 MMPLAYER_FREEIF( caps_str );
3118 if (player->v_stream_caps)
3120 gst_caps_unref(player->v_stream_caps);
3121 player->v_stream_caps = NULL;
3124 debug_log ("create fakesink instead of videobin");
3127 fakesink = gst_element_factory_make ("fakesink", NULL);
3128 if (fakesink == NULL)
3130 debug_error ("ERROR : fakesink create error\n");
3134 player->video_fakesink = fakesink;
3136 gst_bin_add (GST_BIN(pipeline), fakesink);
3139 sinkpad = gst_element_get_static_pad (fakesink, "sink");
3141 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3143 debug_warning ("failed to link fakesink\n");
3144 gst_object_unref (GST_OBJECT(fakesink));
3148 if (player->set_mode.media_packet_video_stream)
3149 player->video_cb_probe_id = gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER, __mmplayer_video_stream_probe, player, NULL);
3151 g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
3152 g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
3153 gst_element_set_state (fakesink, GST_STATE_PAUSED);
3157 #ifdef _USE_M_V_INPUT_SELECTOR_
3158 debug_log ("video selector \n");
3159 elemId = MMPLAYER_M_V_INPUT_SELECTOR;
3160 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
3162 __mmplayer_gst_decode_callback (elem, pad, player);
3167 if (strstr(name, "audio"))
3169 gint samplerate = 0;
3172 if (MMPLAYER_IS_ES_BUFF_SRC(player))
3174 __mmplayer_gst_decode_callback (elem, pad, player);
3178 debug_log ("audio selector \n");
3179 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
3180 stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
3182 gst_structure_get_int (str, "rate", &samplerate);
3183 gst_structure_get_int (str, "channels", &channels);
3185 if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
3187 fakesink = gst_element_factory_make ("fakesink", NULL);
3188 if (fakesink == NULL)
3190 debug_error ("ERROR : fakesink create error\n");
3194 gst_bin_add (GST_BIN(pipeline), fakesink);
3197 sinkpad = gst_element_get_static_pad (fakesink, "sink");
3199 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3201 debug_warning ("failed to link fakesink\n");
3202 gst_object_unref (GST_OBJECT(fakesink));
3206 g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
3207 g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
3208 gst_element_set_state (fakesink, GST_STATE_PAUSED);
3213 else if (strstr(name, "text"))
3215 debug_log ("text selector \n");
3216 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
3217 stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
3221 debug_error ("wrong elem id \n");
3225 #ifndef _USE_M_V_INPUT_SELECTOR_ //if not defined
3226 if(strstr(name, "video"))
3229 selector = player->pipeline->mainbin[elemId].gst;
3231 if (selector == NULL)
3233 selector = gst_element_factory_make ("input-selector", NULL);
3234 debug_log ("Creating input-selector\n");
3235 if (selector == NULL)
3237 debug_error ("ERROR : input-selector create error\n");
3240 g_object_set (selector, "sync-streams", TRUE, NULL);
3242 gst_bin_add (GST_BIN(pipeline), selector);
3243 gst_element_set_state (selector, GST_STATE_PAUSED);
3245 player->pipeline->mainbin[elemId].id = elemId;
3246 player->pipeline->mainbin[elemId].gst = selector;
3249 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK; // default
3251 srcpad = gst_element_get_static_pad (selector, "src");
3253 // debug_log ("blocking %" GST_PTR_FORMAT, srcpad);
3254 // gst_pad_set_blocked_async (srcpad, TRUE, __mmplayer_gst_selector_blocked, NULL);
3255 // gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3256 // __mmplayer_gst_selector_blocked, NULL, NULL);
3261 debug_log ("input-selector is already created.\n");
3262 selector = player->pipeline->mainbin[elemId].gst;
3266 debug_log ("Calling request pad with selector %p \n", selector);
3267 sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3269 debug_log ("got pad %s:%s from selector", GST_DEBUG_PAD_NAME (sinkpad));
3271 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3273 debug_warning ("failed to link selector\n");
3274 gst_object_unref (GST_OBJECT(selector));
3280 debug_log ("this is first track --> active track \n");
3281 g_object_set (selector, "active-pad", sinkpad, NULL);
3284 _mmplayer_track_update_info(player, stream_type, sinkpad);
3292 gst_caps_unref (caps);
3297 gst_object_unref (GST_OBJECT(sinkpad));
3303 gst_object_unref (GST_OBJECT(srcpad));
3310 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
3312 GstPad* srcpad = NULL;
3313 MMHandleType attrs = 0;
3314 gint active_index = 0;
3316 // [link] input-selector :: textbin
3317 srcpad = gst_element_get_static_pad (text_selector, "src");
3320 debug_error("failed to get srcpad from selector\n");
3324 debug_log ("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
3326 active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
3327 if ((active_index != DEFAULT_TRACK) &&
3328 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE))
3330 debug_warning("failed to change text track\n");
3331 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
3334 player->no_more_pad = TRUE;
3335 __mmplayer_gst_decode_callback (text_selector, srcpad, player);
3337 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3338 // gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3340 debug_log("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3342 if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
3343 player->has_closed_caption = TRUE;
3345 attrs = MMPLAYER_GET_ATTRS(player);
3348 mm_attrs_set_int_by_name(attrs, "content_text_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3349 if (mmf_attrs_commit (attrs))
3350 debug_error("failed to commit.\n");
3354 debug_error("cannot get content attribute");
3359 gst_object_unref ( GST_OBJECT(srcpad) );
3364 int _mmplayer_gst_set_audio_channel(MMHandleType hplayer, MMPlayerAudioChannel ch_idx)
3366 int result = MM_ERROR_NONE;
3368 mm_player_t* player = (mm_player_t*)hplayer;
3369 MMPlayerGstElement* mainbin = NULL;
3370 gchar* change_pad_name = NULL;
3371 GstPad* sinkpad = NULL;
3372 GstCaps* caps = NULL;
3376 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3378 debug_log ("Change Audio mode to %d\n", ch_idx);
3379 player->use_deinterleave = TRUE;
3381 if ((!player->pipeline) || (!player->pipeline->mainbin))
3383 debug_log ("pre setting : %d\n", ch_idx);
3385 player->audio_mode.active_pad_index = ch_idx;
3389 mainbin = player->pipeline->mainbin;
3391 if (mainbin[MMPLAYER_M_A_SELECTOR].gst == NULL)
3393 if (player->max_audio_channels < 2)
3395 debug_log ("mono channel track only\n");
3399 debug_warning ("selector doesn't exist\n");
3400 return result; /* keep playing */
3403 debug_log ("total_ch_num : %d\n", player->audio_mode.total_track_num);
3405 if (player->audio_mode.total_track_num < 2)
3407 debug_warning ("there is no another audio path\n");
3408 return result; /* keep playing */
3411 if ((ch_idx < 0) || (ch_idx >= player->audio_mode.total_track_num))
3413 debug_warning ("Not a proper ch_idx : %d \n", ch_idx);
3414 return result; /* keep playing */
3417 /*To get the new pad from the selector*/
3418 change_pad_name = g_strdup_printf ("sink%d", ch_idx);
3419 if (change_pad_name == NULL)
3421 debug_warning ("Pad does not exists\n");
3422 goto ERROR; /* keep playing */
3425 debug_log ("new active pad name: %s\n", change_pad_name);
3427 sinkpad = gst_element_get_static_pad (mainbin[MMPLAYER_M_A_SELECTOR].gst, change_pad_name);
3428 if (sinkpad == NULL)
3430 //result = MM_ERROR_PLAYER_INTERNAL;
3431 goto ERROR; /* keep playing */
3434 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3435 g_object_set (mainbin[MMPLAYER_M_A_SELECTOR].gst, "active-pad", sinkpad, NULL);
3437 caps = gst_pad_get_current_caps(sinkpad);
3438 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3440 __mmplayer_set_audio_attrs (player, caps);
3441 player->audio_mode.active_pad_index = ch_idx;
3446 gst_object_unref (sinkpad);
3448 MMPLAYER_FREEIF(change_pad_name);
3457 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
3459 mm_player_t* player = (mm_player_t*)data;
3460 GstElement* selector = NULL;
3461 GstElement* queue = NULL;
3463 GstPad* srcpad = NULL;
3464 GstPad* sinkpad = NULL;
3465 gchar* caps_str= NULL;
3468 return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3470 caps_str = gst_caps_to_string(gst_pad_get_current_caps(pad));
3471 debug_log ("deinterleave new caps : %s\n", caps_str);
3472 MMPLAYER_FREEIF(caps_str);
3474 if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL)
3476 debug_error ("ERROR : queue create error\n");
3480 g_object_set(G_OBJECT(queue),
3481 "max-size-buffers", 10,
3482 "max-size-bytes", 0,
3483 "max-size-time", (guint64)0,
3486 selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3490 debug_error("there is no audio channel selector.\n");
3494 srcpad = gst_element_get_static_pad (queue, "src");
3495 sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3497 debug_log ("link (%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
3499 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3501 debug_warning ("failed to link deinterleave - selector\n");
3505 gst_element_set_state (queue, GST_STATE_PAUSED);
3506 player->audio_mode.total_track_num++;
3512 gst_object_unref ( GST_OBJECT(srcpad) );
3518 gst_object_unref ( GST_OBJECT(sinkpad) );
3527 __mmplayer_gst_deinterleave_no_more_pads (GstElement *elem, gpointer data)
3529 mm_player_t* player = NULL;
3530 GstElement* selector = NULL;
3531 GstPad* sinkpad = NULL;
3532 gint active_index = 0;
3533 gchar* change_pad_name = NULL;
3534 GstCaps* caps = NULL; // no need to unref
3537 player = (mm_player_t*) data;
3539 selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3543 debug_error("there is no audio channel selector.\n");
3547 active_index = player->audio_mode.active_pad_index;
3549 if (active_index != DEFAULT_AUDIO_CH)
3551 gint audio_ch = DEFAULT_AUDIO_CH;
3553 /*To get the new pad from the selector*/
3554 change_pad_name = g_strdup_printf ("sink%d", active_index);
3555 if (change_pad_name != NULL)
3557 sinkpad = gst_element_get_static_pad (selector, change_pad_name);
3558 if (sinkpad != NULL)
3560 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3561 g_object_set (selector, "active-pad", sinkpad, NULL);
3563 audio_ch = active_index;
3565 caps = gst_pad_get_current_caps(sinkpad);
3566 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3568 __mmplayer_set_audio_attrs (player, caps);
3572 player->audio_mode.active_pad_index = audio_ch;
3573 debug_log("audio LR info (0:stereo) = %d\n", player->audio_mode.active_pad_index);
3579 gst_object_unref (sinkpad);
3586 __mmplayer_gst_build_deinterleave_path (GstElement *elem, GstPad *pad, gpointer data)
3588 mm_player_t* player = NULL;
3589 MMPlayerGstElement *mainbin = NULL;
3591 GstElement* tee = NULL;
3592 GstElement* stereo_queue = NULL;
3593 GstElement* mono_queue = NULL;
3594 GstElement* conv = NULL;
3595 GstElement* filter = NULL;
3596 GstElement* deinterleave = NULL;
3597 GstElement* selector = NULL;
3599 GstPad* srcpad = NULL;
3600 GstPad* selector_srcpad = NULL;
3601 GstPad* sinkpad = NULL;
3602 GstCaps* caps = NULL;
3607 player = (mm_player_t*) data;
3609 return_if_fail( elem && pad );
3610 return_if_fail( player && player->pipeline && player->pipeline->mainbin );
3612 mainbin = player->pipeline->mainbin;
3615 if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL)
3617 debug_error ("ERROR : tee create error\n");
3621 mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
3622 mainbin[MMPLAYER_M_A_TEE].gst = tee;
3624 gst_element_set_state (tee, GST_STATE_PAUSED);
3627 srcpad = gst_element_get_request_pad (tee, "src_%u");
3628 if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3630 debug_error ("ERROR : stereo queue create error\n");
3634 g_object_set(G_OBJECT(stereo_queue),
3635 "max-size-buffers", 10,
3636 "max-size-bytes", 0,
3637 "max-size-time", (guint64)0,
3640 player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
3641 player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
3645 gst_object_unref (GST_OBJECT(srcpad));
3649 srcpad = gst_element_get_request_pad (tee, "src_%u");
3651 if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3653 debug_error ("ERROR : mono queue create error\n");
3657 g_object_set(G_OBJECT(mono_queue),
3658 "max-size-buffers", 10,
3659 "max-size-bytes", 0,
3660 "max-size-time", (guint64)0,
3663 player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3664 player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3666 gst_element_set_state (stereo_queue, GST_STATE_PAUSED);
3667 gst_element_set_state (mono_queue, GST_STATE_PAUSED);
3670 srcpad = gst_element_get_static_pad (mono_queue, "src");
3671 if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL)
3673 debug_error ("ERROR : audioconvert create error\n");
3677 player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3678 player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3683 gst_object_unref (GST_OBJECT(srcpad));
3686 srcpad = gst_element_get_static_pad (conv, "src");
3688 if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL)
3690 debug_error ("ERROR : capsfilter create error\n");
3694 player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3695 player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3697 caps = gst_caps_from_string( "audio/x-raw-int, "
3698 "width = (int) 16, "
3699 "depth = (int) 16, "
3700 "channels = (int) 2");
3702 g_object_set (GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL );
3703 gst_caps_unref( caps );
3705 gst_element_set_state (conv, GST_STATE_PAUSED);
3706 gst_element_set_state (filter, GST_STATE_PAUSED);
3711 gst_object_unref (GST_OBJECT(srcpad));
3714 srcpad = gst_element_get_static_pad (filter, "src");
3716 if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL)
3718 debug_error ("ERROR : deinterleave create error\n");
3722 g_object_set (deinterleave, "keep-positions", TRUE, NULL);
3724 MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3725 G_CALLBACK (__mmplayer_gst_deinterleave_pad_added), player);
3727 MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3728 G_CALLBACK (__mmplayer_gst_deinterleave_no_more_pads), player);
3730 player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3731 player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3734 selector = gst_element_factory_make ("input-selector", "audio-channel-selector");
3735 if (selector == NULL)
3737 debug_error ("ERROR : audio-selector create error\n");
3741 g_object_set (selector, "sync-streams", TRUE, NULL);
3742 gst_bin_add (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3744 player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3745 player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3747 selector_srcpad = gst_element_get_static_pad (selector, "src");
3749 debug_log ("blocking %" GST_PTR_FORMAT, selector_srcpad);
3750 //gst_pad_set_blocked_async (selector_srcpad, TRUE, __mmplayer_gst_selector_blocked, NULL);
3751 gst_pad_add_probe(selector_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3752 __mmplayer_gst_selector_blocked, NULL, NULL);
3756 gst_object_unref (GST_OBJECT(srcpad));
3760 srcpad = gst_element_get_static_pad(stereo_queue, "src");
3761 sinkpad = gst_element_get_request_pad (selector, "sink_%u");
3763 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3765 debug_warning ("failed to link queue_stereo - selector\n");
3769 player->audio_mode.total_track_num++;
3771 g_object_set (selector, "active-pad", sinkpad, NULL);
3772 gst_element_set_state (deinterleave, GST_STATE_PAUSED);
3773 gst_element_set_state (selector, GST_STATE_PAUSED);
3775 __mmplayer_gst_decode_callback (selector, selector_srcpad, player);
3777 debug_log ("unblocking %" GST_PTR_FORMAT, selector_srcpad);
3778 // gst_pad_set_blocked_async (selector_srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3783 gst_object_unref (GST_OBJECT(sinkpad));
3789 gst_object_unref (GST_OBJECT(srcpad));
3793 if (selector_srcpad)
3795 gst_object_unref (GST_OBJECT(selector_srcpad));
3796 selector_srcpad = NULL;
3804 __mmplayer_gst_decode_no_more_pads (GstElement *elem, gpointer data)
3806 mm_player_t* player = NULL;
3807 GstPad* srcpad = NULL;
3808 #ifdef _USE_M_V_INPUT_SELECTOR_
3809 GstElement* video_selector = NULL;
3811 GstElement* audio_selector = NULL;
3812 GstElement* text_selector = NULL;
3813 MMHandleType attrs = 0;
3814 gint active_index = 0;
3815 gint64 dur_bytes = 0L;
3817 player = (mm_player_t*) data;
3819 debug_log("no-more-pad signal handling\n");
3821 if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3822 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
3824 debug_warning("no need to go more");
3826 if (player->pp_rebuilding)
3828 player->pp_rebuilding = FALSE;
3829 MMPLAYER_PLAYBACK_UNLOCK(player);
3835 if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3836 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3837 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3838 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
3840 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
3842 if (NULL == player->streamer)
3844 debug_warning("invalid state for buffering");
3848 gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
3849 guint buffer_bytes = init_buffering_time * ESTIMATED_BUFFER_UNIT;
3851 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
3852 debug_log("[Decodebin2] set use-buffering on Q2 (pre buffer time: %d sec, buffer size : %d)\n", (gint)init_buffering_time, buffer_bytes);
3854 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
3856 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
3857 debug_error("fail to get duration.\n");
3859 // enable use-buffering on queue2 instead of multiqueue (ex)audio only streaming
3860 // use file information was already set on Q2 when it was created.
3861 __mm_player_streaming_set_queue2(player->streamer,
3862 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
3863 TRUE, // use_buffering
3865 init_buffering_time,
3867 player->ini.http_buffering_limit, // high percent
3870 ((dur_bytes>0)?((guint64)dur_bytes):0));
3872 #ifdef _USE_M_V_INPUT_SELECTOR_
3873 video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
3875 audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
3876 text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3877 #ifdef _USE_M_V_INPUT_SELECTOR_
3880 // the first track can be played only. not support track changing yet.
3881 // [link] input-selector :: videobin
3882 srcpad = gst_element_get_static_pad (video_selector, "src");
3885 debug_error("failed to get srcpad from video selector\n");
3889 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3890 if ((!text_selector) && (!audio_selector))
3891 player->no_more_pad = TRUE;
3893 __mmplayer_gst_decode_callback (video_selector, srcpad, player);
3895 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3896 // gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3898 debug_log("Total video tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].total_track_num);
3900 gst_object_unref ( GST_OBJECT(srcpad) );
3905 if ((player->pipeline->videobin) && (player->pipeline->videobin[MMPLAYER_V_BIN].gst))
3907 debug_log ("There is no video track : remove videobin");
3909 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN );
3910 __mmplayer_del_sink ( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
3912 MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->videobin, MMPLAYER_V_BIN );
3913 MMPLAYER_FREEIF ( player->pipeline->videobin )
3919 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
3920 if ((active_index != DEFAULT_TRACK) &&
3921 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE))
3923 debug_warning("failed to change audio track\n");
3924 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
3927 // [link] input-selector :: audiobin
3928 srcpad = gst_element_get_static_pad (audio_selector, "src");
3931 debug_error("failed to get srcpad from selector\n");
3935 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3937 player->no_more_pad = TRUE;
3939 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2))
3941 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3942 // gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3944 __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
3948 __mmplayer_gst_decode_callback (audio_selector, srcpad, player);
3950 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3951 // gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3954 debug_log("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3956 attrs = MMPLAYER_GET_ATTRS(player);
3959 mm_attrs_set_int_by_name(attrs, "content_audio_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3960 if (mmf_attrs_commit (attrs))
3961 debug_error("failed to commit.\n");
3965 debug_error("cannot get content attribute");
3970 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst))
3972 debug_log ("There is no audio track : remove audiobin");
3974 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN );
3975 __mmplayer_del_sink ( player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst );
3977 MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->audiobin, MMPLAYER_A_BIN );
3978 MMPLAYER_FREEIF ( player->pipeline->audiobin )
3981 if (player->num_dynamic_pad == 0)
3983 __mmplayer_pipeline_complete (NULL, player);
3988 if (!MMPLAYER_IS_ES_BUFF_SRC(player))
3993 __mmplayer_handle_text_decode_path(player, text_selector);
4002 gst_object_unref ( GST_OBJECT(srcpad) );
4006 if (player->pp_rebuilding)
4008 player->pp_rebuilding = FALSE;
4009 MMPLAYER_PLAYBACK_UNLOCK(player);
4014 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // @
4016 mm_player_t* player = NULL;
4017 MMHandleType attrs = 0;
4018 GstElement* pipeline = NULL;
4019 GstCaps* caps = NULL;
4020 gchar* caps_str = NULL;
4021 GstStructure* str = NULL;
4022 const gchar* name = NULL;
4023 GstPad* sinkpad = NULL;
4024 GstElement* sinkbin = NULL;
4025 gboolean reusing = FALSE;
4026 GstElement *text_selector = NULL;
4029 player = (mm_player_t*) data;
4031 return_if_fail( elem && pad );
4032 return_if_fail(player && player->pipeline && player->pipeline->mainbin);
4034 pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
4036 attrs = MMPLAYER_GET_ATTRS(player);
4039 debug_error("cannot get content attribute\n");
4043 /* get mimetype from caps */
4044 caps = gst_pad_query_caps( pad, NULL );
4047 debug_error("cannot get caps from pad.\n");
4050 caps_str = gst_caps_to_string(caps);
4052 str = gst_caps_get_structure( caps, 0 );
4055 debug_error("cannot get structure from capse.\n");
4059 name = gst_structure_get_name(str);
4062 debug_error("cannot get mimetype from structure.\n");
4066 //debug_log("detected mimetype : %s\n", name);
4068 if (strstr(name, "audio"))
4070 if (player->pipeline->audiobin == NULL)
4072 if (MM_ERROR_NONE != __mmplayer_gst_create_audio_pipeline(player))
4074 debug_error("failed to create audiobin. continuing without audio\n");
4078 sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
4079 debug_log("creating audiosink bin success\n");
4084 sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
4085 debug_log("reusing audiobin\n");
4086 _mmplayer_update_content_attrs( player, ATTR_AUDIO);
4089 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
4090 mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
4092 player->audiosink_linked = 1;
4094 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
4097 debug_error("failed to get pad from sinkbin\n");
4101 else if (strstr(name, "video"))
4103 if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
4105 player->set_mode.video_zc = TRUE;
4108 if (player->pipeline->videobin == NULL)
4110 /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
4111 /* get video surface type */
4112 int surface_type = 0;
4113 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
4115 if (surface_type == MM_DISPLAY_SURFACE_NULL)
4117 debug_log("not make videobin because it dose not want\n");
4121 if (MM_ERROR_NONE != __mmplayer_gst_create_video_pipeline(player, caps, surface_type) )
4123 debug_error("failed to create videobin. continuing without video\n");
4127 sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
4128 debug_log("creating videosink bin success\n");
4133 sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
4134 debug_log("re-using videobin\n");
4135 _mmplayer_update_content_attrs( player, ATTR_VIDEO);
4138 /* FIXIT : track number shouldn't be hardcoded */
4139 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 1);
4140 player->videosink_linked = 1;
4142 /* NOTE : intermediate code before doing H/W subtitle compositon */
4143 if ( player->use_textoverlay && player->play_subtitle )
4145 debug_log("using textoverlay for external subtitle");
4146 /* check text bin has created well */
4147 if ( player->pipeline && player->pipeline->textbin )
4149 /* get sinkpad from textoverlay */
4150 sinkpad = gst_element_get_static_pad(
4151 GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
4155 debug_error("failed to get sink pad from textoverlay");
4159 /* link new pad with textoverlay first */
4160 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
4162 debug_error("failed to get pad from sinkbin\n");
4166 gst_object_unref(sinkpad);
4169 /* alright, override pad to textbin.src for futher link */
4170 pad = gst_element_get_static_pad(
4171 GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
4175 debug_error("failed to get sink pad from textoverlay");
4181 debug_error("should not reach here.");
4186 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
4189 debug_error("failed to get pad from sinkbin\n");
4193 else if (strstr(name, "text"))
4195 if (player->pipeline->textbin == NULL)
4197 MMPlayerGstElement* mainbin = NULL;
4199 if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player))
4201 debug_error("failed to create textbin. continuing without text\n");
4205 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
4206 debug_log("creating textsink bin success\n");
4208 /* FIXIT : track number shouldn't be hardcoded */
4209 mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
4211 player->textsink_linked = 1;
4212 debug_msg("player->textsink_linked set to 1\n");
4214 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "text_sink" );
4217 debug_error("failed to get pad from sinkbin\n");
4221 mainbin = player->pipeline->mainbin;
4223 if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst)
4225 /* input selector */
4226 text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
4227 if ( !text_selector )
4229 debug_error ( "failed to create subtitle input selector element\n" );
4232 g_object_set (text_selector, "sync-streams", TRUE, NULL);
4234 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
4235 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
4238 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_READY))
4240 debug_error("failed to set state(READY) to sinkbin\n");
4244 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector))
4246 debug_warning("failed to add subtitle input selector\n");
4250 debug_log ("created element input-selector");
4255 debug_log ("already having subtitle input selector");
4256 text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
4262 if (!player->textsink_linked)
4264 debug_log("re-using textbin\n");
4267 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
4269 player->textsink_linked = 1;
4270 debug_msg("player->textsink_linked set to 1\n");
4274 debug_log("ignoring internal subtutle since external subtitle is available");
4280 debug_warning("unknown type of elementary stream! ignoring it...\n");
4289 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_READY ) )
4291 debug_error("failed to set state(READY) to sinkbin\n");
4295 /* Added for multi audio support to avoid adding audio bin again*/
4297 if ( FALSE == gst_bin_add( GST_BIN(pipeline), sinkbin ) )
4299 debug_error("failed to add sinkbin to pipeline\n");
4305 if (GST_PAD_LINK_OK != GST_PAD_LINK (pad, sinkpad))
4307 debug_error("failed to get pad from sinkbin\n");
4314 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (sinkbin, GST_STATE_PAUSED))
4316 debug_error("failed to set state(PLAYING) to sinkbin\n");
4322 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_PAUSED))
4324 debug_error("failed to set state(READY) to sinkbin\n");
4330 gst_object_unref (sinkpad);
4334 debug_log ("linking sink bin success\n");
4336 /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
4337 * streaming task. if the task blocked, then buffer will not flow to the next element
4338 * ( autoplugging element ). so this is special hack for streaming. please try to remove it
4340 /* dec stream count. we can remove fakesink if it's zero */
4341 if (player->num_dynamic_pad)
4342 player->num_dynamic_pad--;
4344 debug_log ("no more pads: %d stream count dec : %d (num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
4346 if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
4348 __mmplayer_pipeline_complete (NULL, player);
4351 /* FIXIT : please leave a note why this code is needed */
4352 if(MMPLAYER_IS_WFD_STREAMING( player ))
4354 player->no_more_pad = TRUE;
4359 MMPLAYER_FREEIF(caps_str);
4362 gst_caps_unref( caps );
4365 gst_object_unref(GST_OBJECT(sinkpad));
4367 /* flusing out new attributes */
4368 if ( mmf_attrs_commit ( attrs ) )
4370 debug_error("failed to comit attributes\n");
4377 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
4379 int pro_value = 0; // in the case of expection, default will be returned.
4380 int dest_angle = rotation_angle;
4381 int rotation_type = -1;
4382 #define ROTATION_USING_SINK 0
4383 #define ROTATION_USING_CUSTOM 1
4384 #define ROTATION_USING_FLIP 2
4386 return_val_if_fail(player, FALSE);
4387 return_val_if_fail(value, FALSE);
4388 return_val_if_fail(rotation_angle >= 0, FALSE);
4390 if (rotation_angle >= 360)
4392 dest_angle = rotation_angle - 360;
4395 /* chech if supported or not */
4396 if ( dest_angle % 90 )
4398 debug_log("not supported rotation angle = %d", rotation_angle);
4403 * xvimagesink only (A)
4404 * custom_convert - no xv (e.g. memsink, evasimagesink (B)
4405 * videoflip - avsysmemsink (C)
4407 if (player->set_mode.video_zc)
4409 if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
4411 rotation_type = ROTATION_USING_CUSTOM;
4415 rotation_type = ROTATION_USING_SINK;
4420 int surface_type = 0;
4421 rotation_type = ROTATION_USING_FLIP;
4423 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
4424 debug_log("check display surface type attribute: %d", surface_type);
4426 if ((surface_type == MM_DISPLAY_SURFACE_X) ||
4427 (surface_type == MM_DISPLAY_SURFACE_EVAS && !strcmp(player->ini.videosink_element_evas, "evaspixmapsink")))
4429 rotation_type = ROTATION_USING_SINK;
4433 rotation_type = ROTATION_USING_FLIP; //C
4436 debug_log("using %d type for rotation", rotation_type);
4439 /* get property value for setting */
4440 switch(rotation_type)
4442 case ROTATION_USING_SINK: // xvimagesink, pixmap
4449 pro_value = 3; // clockwise 90
4455 pro_value = 1; // counter-clockwise 90
4460 case ROTATION_USING_CUSTOM:
4462 gchar *ename = NULL;
4463 ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
4465 if (g_strrstr(ename, "fimcconvert"))
4472 pro_value = 90; // clockwise 90
4478 pro_value = 270; // counter-clockwise 90
4484 case ROTATION_USING_FLIP: // videoflip
4492 pro_value = 1; // clockwise 90
4498 pro_value = 3; // counter-clockwise 90
4505 debug_log("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
4513 _mmplayer_update_video_param(mm_player_t* player) // @
4515 MMHandleType attrs = 0;
4516 int surface_type = 0;
4517 int org_angle = 0; // current supported angle values are 0, 90, 180, 270
4519 int user_angle_type= 0;
4520 int rotation_value = 0;
4521 gchar *org_orient = NULL;
4525 /* check video sinkbin is created */
4526 return_val_if_fail ( player &&
4528 player->pipeline->videobin &&
4529 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
4530 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4531 MM_ERROR_PLAYER_NOT_INITIALIZED );
4533 attrs = MMPLAYER_GET_ATTRS(player);
4536 debug_error("cannot get content attribute");
4537 return MM_ERROR_PLAYER_INTERNAL;
4540 /* update user roation */
4541 mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
4543 /* get angle with user type */
4544 switch(user_angle_type)
4546 case MM_DISPLAY_ROTATION_NONE:
4549 case MM_DISPLAY_ROTATION_90: // counter-clockwise 90
4552 case MM_DISPLAY_ROTATION_180:
4555 case MM_DISPLAY_ROTATION_270: // clockwise 90
4560 /* get original orientation */
4561 mm_attrs_get_string_by_name(attrs, "content_video_orientation", &org_orient);
4565 if (!strcmp (org_orient, "rotate-90"))
4567 else if (!strcmp (org_orient, "rotate-180"))
4569 else if (!strcmp (org_orient, "rotate-270"))
4572 debug_log ("original rotation is %s", org_orient);
4576 debug_log ("content_video_orientation get fail");
4579 debug_log("check user angle: %d, orientation: %d", user_angle, org_angle);
4581 /* check video stream callback is used */
4582 if(!player->set_mode.media_packet_video_stream && player->use_video_stream )
4584 if (player->set_mode.video_zc)
4586 gchar *ename = NULL;
4590 mm_attrs_get_int_by_name(attrs, "display_width", &width);
4591 mm_attrs_get_int_by_name(attrs, "display_height", &height);
4593 /* resize video frame with requested values for fimcconvert */
4594 ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
4596 if (ename && g_strrstr(ename, "fimcconvert"))
4599 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
4602 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
4604 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
4605 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
4607 /* get rotation value to set */
4608 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4610 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "rotate", rotation_value, NULL);
4612 debug_log("updating fimcconvert - r[%d], w[%d], h[%d]", rotation_value, width, height);
4617 debug_log("using video stream callback with memsink. player handle : [%p]", player);
4619 /* get rotation value to set */
4620 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4622 g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
4625 return MM_ERROR_NONE;
4628 /* update display surface */
4629 mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
4630 debug_log("check display surface type attribute: %d", surface_type);
4632 /* configuring display */
4633 switch ( surface_type )
4635 case MM_DISPLAY_SURFACE_X:
4637 /* ximagesink or xvimagesink */
4638 void *surface = NULL;
4640 int display_method = 0;
4649 int force_aspect_ratio = 0;
4650 gboolean visible = TRUE;
4654 void* wl_display = NULL;
4655 GstContext *context = NULL;
4656 int wl_window_x = 0;
4657 int wl_window_y = 0;
4658 int wl_window_width = 0;
4659 int wl_window_height = 0;
4661 mm_attrs_get_data_by_name(attrs, "wl_display", &wl_display);
4663 context = gst_wayland_display_handle_context_new(wl_display);
4665 gst_element_set_context(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), context);
4667 /*It should be set after setting window*/
4668 mm_attrs_get_int_by_name(attrs, "wl_window_render_x", &wl_window_x);
4669 mm_attrs_get_int_by_name(attrs, "wl_window_render_y", &wl_window_y);
4670 mm_attrs_get_int_by_name(attrs, "wl_window_render_width", &wl_window_width);
4671 mm_attrs_get_int_by_name(attrs, "wl_window_render_height", &wl_window_height);
4673 /* common case if using x surface */
4674 mm_attrs_get_data_by_name(attrs, "display_overlay", &surface);
4679 wl_surface = (int*)surface;
4680 debug_log("set video param : xid %p", (int*)surface);
4683 gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), (int*)surface );
4684 /* After setting window handle, set render rectangle */
4685 gst_video_overlay_set_render_rectangle(
4686 GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ),
4687 wl_window_x,wl_window_y,wl_window_width,wl_window_height);
4691 xwin_id = *(int*)surface;
4692 debug_log("set video param : xid %p", *(int*)surface);
4695 gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)surface );
4701 /* FIXIT : is it error case? */
4702 debug_warning("still we don't have xid on player attribute. create it's own surface.");
4705 /* if xvimagesink */
4706 if (!strcmp(player->ini.videosink_element_x,"xvimagesink"))
4708 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
4709 mm_attrs_get_double_by_name(attrs, "display_zoom", &zoom);
4710 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4711 mm_attrs_get_int_by_name(attrs, "display_src_crop_x", &src_crop_x);
4712 mm_attrs_get_int_by_name(attrs, "display_src_crop_y", &src_crop_y);
4713 mm_attrs_get_int_by_name(attrs, "display_src_crop_width", &src_crop_w);
4714 mm_attrs_get_int_by_name(attrs, "display_src_crop_height", &src_crop_h);
4715 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
4716 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
4717 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
4718 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
4719 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4720 #define DEFAULT_DISPLAY_MODE 2 // TV only, PRI_VIDEO_OFF_AND_SEC_VIDEO_FULL_SCREEN
4722 /* setting for cropping media source */
4723 if (src_crop_w && src_crop_h)
4725 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4726 "src-crop-x", src_crop_x,
4727 "src-crop-y", src_crop_y,
4728 "src-crop-w", src_crop_w,
4729 "src-crop-h", src_crop_h,
4733 /* setting for ROI mode */
4734 if (display_method == 5) // 5 for ROI mode
4737 mm_attrs_get_int_by_name(attrs, "display_roi_mode", &roi_mode);
4738 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4739 "dst-roi-mode", roi_mode,
4745 /* get rotation value to set,
4746 do not use org_angle because ROI mode in xvimagesink needs both a rotation value and an orientation value */
4747 __mmplayer_get_property_value_for_rotation(player, user_angle, &rotation_value);
4751 /* get rotation value to set */
4752 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4755 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4756 "force-aspect-ratio", force_aspect_ratio,
4757 "zoom", (float)zoom,
4758 "orientation", org_angle/90, // setting for orientation of media, it is used for ROI/ZOOM feature in xvimagesink
4759 "rotate", rotation_value,
4760 "handle-events", TRUE,
4761 "display-geometry-method", display_method,
4762 "draw-borders", FALSE,
4764 "display-mode", DEFAULT_DISPLAY_MODE,
4767 debug_log("set video param : zoom %lf, rotate %d, method %d visible %d", zoom, rotation_value, display_method, visible);
4768 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d", roi_x, roi_y, roi_w, roi_h );
4769 debug_log("set video param : force aspect ratio %d, display mode %d", force_aspect_ratio, DEFAULT_DISPLAY_MODE);
4773 case MM_DISPLAY_SURFACE_EVAS:
4775 void *object = NULL;
4777 gboolean visible = TRUE;
4778 int display_method = 0;
4780 /* common case if using evas surface */
4781 mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
4782 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4783 mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
4784 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4786 /* if evasimagesink */
4787 if (!strcmp(player->ini.videosink_element_evas,"evasimagesink"))
4791 /* if it is evasimagesink, we are not supporting rotation */
4792 if (user_angle_type!=MM_DISPLAY_ROTATION_NONE)
4794 mm_attrs_set_int_by_name(attrs, "display_rotation", MM_DISPLAY_ROTATION_NONE);
4795 if (mmf_attrs_commit (attrs)) /* return -1 if error */
4796 debug_error("failed to commit\n");
4797 debug_warning("unsupported feature");
4798 return MM_ERROR_NOT_SUPPORT_API;
4800 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4801 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4802 "evas-object", object,
4804 "display-geometry-method", display_method,
4805 "rotate", rotation_value,
4807 debug_log("set video param : method %d", display_method);
4808 debug_log("set video param : evas-object %x, visible %d", object, visible);
4809 debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
4813 debug_error("no evas object");
4814 return MM_ERROR_PLAYER_INTERNAL;
4818 /* if evasimagesink using converter */
4819 if (player->set_mode.video_zc && player->pipeline->videobin[MMPLAYER_V_CONV].gst)
4823 int no_scaling = !scaling;
4825 mm_attrs_get_int_by_name(attrs, "display_width", &width);
4826 mm_attrs_get_int_by_name(attrs, "display_height", &height);
4828 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
4829 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
4830 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-buffer-num", 5, NULL);
4834 /* no-scaling order to fimcconvert, original width, height size of media src will be passed to sink plugin */
4835 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst,
4836 "dst-width", 0, /* setting 0, output video width will be media src's width */
4837 "dst-height", 0, /* setting 0, output video height will be media src's height */
4842 /* scaling order to fimcconvert */
4845 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
4849 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
4851 debug_log("set video param : video frame scaling down to width(%d) height(%d)", width, height);
4853 debug_log("set video param : display_evas_do_scaling %d", scaling);
4857 /* if evaspixmapsink */
4858 if (!strcmp(player->ini.videosink_element_evas,"evaspixmapsink"))
4862 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4863 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4864 "evas-object", object,
4866 "display-geometry-method", display_method,
4867 "rotate", rotation_value,
4869 debug_log("set video param : method %d", display_method);
4870 debug_log("set video param : evas-object %x, visible %d", object, visible);
4871 debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
4875 debug_error("no evas object");
4876 return MM_ERROR_PLAYER_INTERNAL;
4879 int display_method = 0;
4884 int origin_size = !scaling;
4886 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4887 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
4888 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
4889 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
4890 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
4892 /* get rotation value to set */
4893 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4895 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4896 "origin-size", origin_size,
4897 "rotate", rotation_value,
4902 "display-geometry-method", display_method,
4905 debug_log("set video param : method %d", display_method);
4906 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
4907 roi_x, roi_y, roi_w, roi_h );
4908 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
4912 case MM_DISPLAY_SURFACE_X_EXT: /* NOTE : this surface type is used for the videoTexture(canvasTexture) overlay */
4914 void *pixmap_id_cb = NULL;
4915 void *pixmap_id_cb_user_data = NULL;
4916 int display_method = 0;
4917 gboolean visible = TRUE;
4919 /* if xvimagesink */
4920 if (strcmp(player->ini.videosink_element_x,"xvimagesink"))
4922 debug_error("videosink is not xvimagesink");
4923 return MM_ERROR_PLAYER_INTERNAL;
4926 /* get information from attributes */
4927 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
4928 mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
4929 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4930 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4934 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
4935 if (pixmap_id_cb_user_data)
4937 debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
4942 debug_error("failed to set pixmap-id-callback");
4943 return MM_ERROR_PLAYER_INTERNAL;
4945 /* get rotation value to set */
4946 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4948 debug_log("set video param : rotate %d, method %d, visible %d", rotation_value, display_method, visible);
4950 /* set properties of videosink plugin */
4951 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4952 "display-geometry-method", display_method,
4953 "draw-borders", FALSE,
4955 "rotate", rotation_value,
4956 "pixmap-id-callback", pixmap_id_cb,
4957 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
4961 case MM_DISPLAY_SURFACE_NULL:
4970 return MM_ERROR_NONE;
4974 __mmplayer_gst_element_link_bucket(GList* element_bucket) // @
4976 GList* bucket = element_bucket;
4977 MMPlayerGstElement* element = NULL;
4978 MMPlayerGstElement* prv_element = NULL;
4979 gint successful_link_count = 0;
4983 return_val_if_fail(element_bucket, -1);
4985 prv_element = (MMPlayerGstElement*)bucket->data;
4986 bucket = bucket->next;
4988 for ( ; bucket; bucket = bucket->next )
4990 element = (MMPlayerGstElement*)bucket->data;
4992 if ( element && element->gst )
4995 /* If next element is audio appsrc then make a seprate audio pipeline */
4996 if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),"audio_appsrc") ||
4997 !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),"subtitle_appsrc"))
4999 prv_element = element;
5003 if ( GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst)) )
5005 debug_log("linking [%s] to [%s] success\n",
5006 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
5007 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
5008 successful_link_count ++;
5012 debug_log("linking [%s] to [%s] failed\n",
5013 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
5014 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
5019 prv_element = element;
5024 return successful_link_count;
5028 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket) // @
5030 GList* bucket = element_bucket;
5031 MMPlayerGstElement* element = NULL;
5032 int successful_add_count = 0;
5036 return_val_if_fail(element_bucket, 0);
5037 return_val_if_fail(bin, 0);
5039 for ( ; bucket; bucket = bucket->next )
5041 element = (MMPlayerGstElement*)bucket->data;
5043 if ( element && element->gst )
5045 if( !gst_bin_add(bin, GST_ELEMENT(element->gst)) )
5047 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s] to bin [%s] failed\n",
5048 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
5049 GST_ELEMENT_NAME(GST_ELEMENT(bin) ) );
5052 successful_add_count ++;
5058 return successful_add_count;
5061 static void __mmplayer_gst_caps_notify_cb (GstPad * pad, GParamSpec * unused, gpointer data)
5063 mm_player_t* player = (mm_player_t*) data;
5064 GstCaps *caps = NULL;
5065 GstStructure *str = NULL;
5070 return_if_fail ( pad )
5071 return_if_fail ( unused )
5072 return_if_fail ( data )
5074 caps = gst_pad_query_caps(pad, NULL);
5080 str = gst_caps_get_structure(caps, 0);
5086 name = gst_structure_get_name(str);
5092 debug_log("name = %s\n", name);
5094 if (strstr(name, "audio"))
5096 _mmplayer_update_content_attrs (player, ATTR_AUDIO);
5098 if (player->audio_stream_changed_cb)
5100 debug_error("call the audio stream changed cb\n");
5101 player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
5104 else if (strstr(name, "video"))
5106 _mmplayer_update_content_attrs (player, ATTR_VIDEO);
5108 if (player->video_stream_changed_cb)
5110 debug_error("call the video stream changed cb\n");
5111 player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
5121 gst_caps_unref(caps);
5131 * This function is to create audio pipeline for playing.
5133 * @param player [in] handle of player
5135 * @return This function returns zero on success.
5137 * @see __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
5139 #define MMPLAYER_CREATEONLY_ELEMENT(x_bin, x_id, x_factory, x_name) \
5140 x_bin[x_id].id = x_id;\
5141 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5142 if ( ! x_bin[x_id].gst )\
5144 debug_error("failed to create %s \n", x_factory);\
5148 #define MMPLAYER_CREATE_ELEMENT_ADD_BIN(x_bin, x_id, x_factory, x_name, y_bin, x_player) \
5149 x_bin[x_id].id = x_id;\
5150 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5151 if ( ! x_bin[x_id].gst )\
5153 debug_error("failed to create %s \n", x_factory);\
5158 if (x_player->ini.set_dump_element_flag)\
5159 __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
5161 if( !gst_bin_add(GST_BIN(y_bin), GST_ELEMENT(x_bin[x_id].gst)))\
5163 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s] to bin [%s] failed\n",\
5164 GST_ELEMENT_NAME(GST_ELEMENT(x_bin[x_id].gst)),\
5165 GST_ELEMENT_NAME(GST_ELEMENT(y_bin) ) );\
5169 /* macro for code readability. just for sinkbin-creation functions */
5170 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
5173 x_bin[x_id].id = x_id;\
5174 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5175 if ( ! x_bin[x_id].gst )\
5177 debug_error("failed to create %s \n", x_factory);\
5182 if (x_player->ini.set_dump_element_flag)\
5183 __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
5185 if ( x_add_bucket )\
5186 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
5190 __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5192 mm_player_t* player = (mm_player_t*) data;
5197 gint endianness = 0;
5198 guint64 channel_mask = 0;
5200 MMPlayerAudioStreamDataType audio_stream = { 0, };
5201 GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5204 return_if_fail(player->audio_stream_render_cb_ex);
5206 debug_log ("__mmplayer_audio_stream_decoded_render_cb new pad: %s", GST_PAD_NAME (pad));
5208 gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
5209 audio_stream.data = mapinfo.data;
5210 audio_stream.data_size = mapinfo.size;
5212 GstCaps *caps = gst_pad_get_current_caps( pad );
5213 GstStructure *structure = gst_caps_get_structure (caps, 0);
5215 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5216 gst_structure_get_int (structure, "rate", &rate);
5217 gst_structure_get_int (structure, "channels", &channel);
5218 gst_structure_get_int (structure, "depth", &depth);
5219 gst_structure_get_int (structure, "endianness", &endianness);
5220 gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
5222 gst_caps_unref(GST_CAPS(caps));
5224 audio_stream.bitrate = rate;
5225 audio_stream.channel = channel;
5226 audio_stream.depth = depth;
5227 audio_stream.is_little_endian = (endianness == 1234 ? 1 : 0);
5228 audio_stream.channel_mask = channel_mask;
5229 debug_log ("bitrate : %d channel : %d depth: %d ls_little_endian : %d channel_mask: %d, %p", rate, channel, depth, endianness, channel_mask, player->audio_stream_cb_user_param);
5230 player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param);
5231 gst_buffer_unmap(buffer, &mapinfo);
5237 __mmplayer_gst_audio_deinterleave_pad_added (GstElement *elem, GstPad *pad, gpointer data)
5239 mm_player_t* player = (mm_player_t*)data;
5240 MMPlayerGstElement* audiobin = player->pipeline->audiobin;
5241 GstPad* sinkpad = NULL;
5242 GstElement *queue = NULL, *sink = NULL;
5245 return_if_fail (player && player->pipeline && player->pipeline->mainbin);
5247 queue = gst_element_factory_make ("queue", NULL);
5250 debug_log ("fail make queue\n");
5254 sink = gst_element_factory_make ("fakesink", NULL);
5257 debug_log ("fail make fakesink\n");
5261 gst_bin_add_many (GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
5263 if (!gst_element_link_pads_full (queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING))
5265 debug_warning("failed to link queue & sink\n");
5269 sinkpad = gst_element_get_static_pad (queue, "sink");
5271 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
5273 debug_warning ("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
5277 debug_error("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
5279 gst_object_unref (sinkpad);
5280 g_object_set (sink, "sync", player->audio_stream_sink_sync, NULL);
5281 g_object_set (sink, "signal-handoffs", TRUE, NULL);
5283 gst_element_set_state (sink, GST_STATE_PAUSED);
5284 gst_element_set_state (queue, GST_STATE_PAUSED);
5286 MMPLAYER_SIGNAL_CONNECT( player,
5288 MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
5290 G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
5297 debug_error("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
5300 gst_object_unref(GST_OBJECT(queue));
5305 gst_object_unref(GST_OBJECT(sink));
5310 gst_object_unref ( GST_OBJECT(sinkpad) );
5320 * - Local playback : audiotp !audioconvert ! volume ! capsfilter ! audioeffect ! audioeffect_sec ! audiosink
5321 * - Streaming : audiotp !audioconvert !volume ! audiosink
5322 * - PCM extraction : audiotp !audioconvert ! audioresample ! capsfilter ! fakesink
5324 void __mmplayer_gst_create_audiosink_configure(mm_player_t* player, MMHandleType attrs)
5326 #define MAX_PROPS_LEN 64
5327 gint volume_type = 0;
5328 gint route_path = 0;
5329 gint latency_mode = 0;
5330 gchar *stream_type = NULL;
5332 gchar stream_props[MAX_PROPS_LEN] = {0,};
5333 GstStructure *props = NULL;
5336 * It should be set after player creation through attribute.
5337 * But, it can not be changed during playing.
5340 mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
5341 mm_attrs_get_string_by_name (attrs, "sound_stream_type", &stream_type );
5343 if ( stream_id < 1 || !stream_type || strlen(stream_type) < 1)
5345 debug_error("stream_id[%d] or stream_type[%s] is not valid.\n", stream_id, stream_type);
5349 snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d", stream_type, stream_id);
5350 props = gst_structure_from_string(stream_props, NULL);
5351 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
5354 debug_log("stream_id[%d], stream_type[%s], result[%s].\n", stream_id, stream_type, stream_props);
5356 /* for audio tunning */
5358 if (player->profile.play_mode == MM_PLAYER_MODE_MIDI)
5360 volume_type |= MM_SOUND_VOLUME_GAIN_MIDI;
5363 /* hook sound_type if emergency case */
5364 if (player->sm.event == ASM_EVENT_EMERGENCY)
5366 debug_log ("This is emergency session, hook sound_type from [%d] to [%d]\n", volume_type, MM_SOUND_VOLUME_TYPE_EMERGENCY);
5367 volume_type = MM_SOUND_VOLUME_TYPE_EMERGENCY;
5370 mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
5372 if (player->sm.user_route_policy != 0)
5374 route_path = player->sm.user_route_policy;
5377 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
5378 "latency", latency_mode,
5381 debug_log("audiosink property status...volume type:%d, user-route=%d, latency=%d \n",
5382 volume_type, route_path, latency_mode);
5387 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
5389 MMPlayerGstElement* first_element = NULL;
5390 MMPlayerGstElement* audiobin = NULL;
5391 MMHandleType attrs = 0;
5393 GstPad *ghostpad = NULL;
5394 GList* element_bucket = NULL;
5395 gboolean link_audio_sink_now = TRUE;
5400 return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5403 audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
5406 debug_error("failed to allocate memory for audiobin\n");
5407 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5410 attrs = MMPLAYER_GET_ATTRS(player);
5413 audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
5414 audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
5415 if ( !audiobin[MMPLAYER_A_BIN].gst )
5417 debug_error("failed to create audiobin\n");
5422 player->pipeline->audiobin = audiobin;
5424 player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
5426 /* Adding audiotp plugin for reverse trickplay feature */
5427 // MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
5430 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
5433 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER, player->ini.name_of_audio_resampler, "audio resampler", TRUE, player);
5435 if (player->set_mode.pcm_extraction) // pcm extraction only and no sound output
5437 if(player->audio_stream_render_cb_ex)
5439 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
5441 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
5442 /* raw pad handling signal */
5443 MMPLAYER_SIGNAL_CONNECT( player,
5444 (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
5445 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
5446 G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
5450 int dst_samplerate = 0;
5451 int dst_channels = 0;
5453 char *caps_str = NULL;
5454 GstCaps* caps = NULL;
5456 /* get conf. values */
5457 mm_attrs_multiple_get(player->attrs,
5459 "pcm_extraction_samplerate", &dst_samplerate,
5460 "pcm_extraction_channels", &dst_channels,
5461 "pcm_extraction_depth", &dst_depth,
5465 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
5466 caps = gst_caps_new_simple ("audio/x-raw",
5467 "rate", G_TYPE_INT, dst_samplerate,
5468 "channels", G_TYPE_INT, dst_channels,
5469 "depth", G_TYPE_INT, dst_depth,
5471 caps_str = gst_caps_to_string(caps);
5472 debug_log("new caps : %s\n", caps_str);
5474 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5477 gst_caps_unref( caps );
5478 MMPLAYER_FREEIF( caps_str );
5481 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
5484 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
5487 else // normal playback
5489 //GstCaps* caps = NULL;
5492 /* for logical volume control */
5493 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
5494 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
5496 if (player->sound.mute)
5498 debug_log("mute enabled\n");
5499 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
5504 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
5505 caps = gst_caps_from_string( "audio/x-raw-int, "
5506 "endianness = (int) LITTLE_ENDIAN, "
5507 "signed = (boolean) true, "
5508 "width = (int) 16, "
5509 "depth = (int) 16" );
5510 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5511 gst_caps_unref( caps );
5514 /* chech if multi-chennels */
5515 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)
5517 GstPad *srcpad = NULL;
5518 GstCaps *caps = NULL;
5520 if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src")))
5522 if ((caps = gst_pad_query_caps(srcpad, NULL)))
5524 //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5525 GstStructure *str = gst_caps_get_structure(caps, 0);
5527 gst_structure_get_int (str, "channels", &channels);
5528 gst_caps_unref(caps);
5530 gst_object_unref(srcpad);
5534 /* audio effect element. if audio effect is enabled */
5535 if ( (strcmp(player->ini.name_of_audio_effect, ""))
5537 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom) )
5539 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.name_of_audio_effect, "audio effect filter", TRUE, player);
5541 debug_log("audio effect config. bypass = %d, effect type = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
5543 if ( (!player->bypass_audio_effect)
5544 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom) )
5546 if ( MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type )
5548 if (!_mmplayer_audio_effect_custom_apply(player))
5550 debug_msg("apply audio effect(custom) setting success\n");
5555 if ( (strcmp(player->ini.name_of_audio_effect_sec, ""))
5556 && (player->set_mode.rich_audio) )
5558 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.name_of_audio_effect_sec, "audio effect filter", TRUE, player);
5561 if (!MMPLAYER_IS_RTSP_STREAMING(player))
5563 if (player->set_mode.rich_audio && channels <= 2)
5564 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VSP, "audiovsp", "x-speed", TRUE, player);
5567 /* create audio sink */
5568 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.name_of_audiosink, "audiosink", link_audio_sink_now, player);
5571 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL); /* qos on */
5572 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
5574 /* FIXIT : using system clock. isn't there another way? */
5575 if (player->videodec_linked)
5577 debug_log("provide clock for movie = %s", (player->ini.provide_clock_for_movie)?"audio_clock":"sys_clock");
5578 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_movie, NULL);
5582 debug_log("provide clock for music = %s", (player->ini.provide_clock_for_music)?"audio_clock":"sys_clock");
5583 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_music, NULL);
5586 if ( g_strrstr(player->ini.name_of_audiosink, "pulsesink") )
5588 __mmplayer_gst_create_audiosink_configure(player, attrs);
5591 /* Antishock can be enabled when player is resumed by soundCM.
5592 * But, it's not used in MMS, setting and etc.
5593 * Because, player start seems like late.
5595 __mmplayer_set_antishock( player , FALSE );
5598 if (audiobin[MMPLAYER_A_SINK].gst)
5600 GstPad *sink_pad = NULL;
5601 sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
5602 MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
5603 "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
5604 gst_object_unref (GST_OBJECT(sink_pad));
5607 __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
5609 /* adding created elements to bin */
5610 debug_log("adding created elements to bin\n");
5611 if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket ))
5613 debug_error("failed to add elements\n");
5617 /* linking elements in the bucket by added order. */
5618 debug_log("Linking elements in the bucket by added order.\n");
5619 if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5621 debug_error("failed to link elements\n");
5625 /* get first element's sinkpad for creating ghostpad */
5626 first_element = (MMPlayerGstElement *)element_bucket->data;
5628 pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5631 debug_error("failed to get pad from first element of audiobin\n");
5635 ghostpad = gst_ghost_pad_new("sink", pad);
5638 debug_error("failed to create ghostpad\n");
5642 if ( FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad) )
5644 debug_error("failed to add ghostpad to audiobin\n");
5648 gst_object_unref(pad);
5650 g_list_free(element_bucket);
5652 mm_attrs_set_int_by_name(attrs, "content_audio_found", TRUE);
5656 return MM_ERROR_NONE;
5660 debug_log("ERROR : releasing audiobin\n");
5663 gst_object_unref(GST_OBJECT(pad));
5666 gst_object_unref(GST_OBJECT(ghostpad));
5668 g_list_free( element_bucket );
5670 /* release element which are not added to bin */
5671 for ( i = 1; i < MMPLAYER_A_NUM; i++ ) /* NOTE : skip bin */
5673 if ( audiobin[i].gst )
5675 GstObject* parent = NULL;
5676 parent = gst_element_get_parent( audiobin[i].gst );
5680 gst_object_unref(GST_OBJECT(audiobin[i].gst));
5681 audiobin[i].gst = NULL;
5685 gst_object_unref(GST_OBJECT(parent));
5690 /* release audiobin with it's childs */
5691 if ( audiobin[MMPLAYER_A_BIN].gst )
5693 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
5696 MMPLAYER_FREEIF( audiobin );
5698 player->pipeline->audiobin = NULL;
5700 return MM_ERROR_PLAYER_INTERNAL;
5703 static GstPadProbeReturn
5704 __mmplayer_audio_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
5706 mm_player_t* player = (mm_player_t*) u_data;
5707 GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
5708 GstMapInfo probe_info = GST_MAP_INFO_INIT;
5710 gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
5712 if (player->audio_stream_cb && probe_info.size && probe_info.data)
5713 player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
5715 return GST_PAD_PROBE_OK;
5718 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
5720 return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
5723 static GstPadProbeReturn
5724 __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
5726 GstCaps *caps = NULL;
5727 MMPlayerVideoStreamDataType stream;
5728 MMVideoBuffer *video_buffer = NULL;
5729 GstMemory *dataBlock = NULL;
5730 GstMemory *metaBlock = NULL;
5731 GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5732 GstStructure *structure = NULL;
5733 const gchar *string_format = NULL;
5734 unsigned int fourcc = 0;
5735 mm_player_t* player = (mm_player_t*)user_data;
5736 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
5738 return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
5739 return_val_if_fail(gst_buffer_n_memory(buffer) , GST_PAD_PROBE_DROP);
5741 caps = gst_pad_get_current_caps(pad);
5743 debug_error( "Caps is NULL." );
5744 return GST_PAD_PROBE_OK;
5747 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5749 /* clear stream data structure */
5750 memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
5752 structure = gst_caps_get_structure( caps, 0 );
5753 gst_structure_get_int(structure, "width", &(stream.width));
5754 gst_structure_get_int(structure, "height", &(stream.height));
5755 string_format = gst_structure_get_string(structure, "format");
5757 fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
5759 stream.format = util_get_pixtype(fourcc);
5760 gst_caps_unref( caps );
5764 debug_log( "Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
5765 GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format );
5768 if (stream.width == 0 || stream.height == 0 || stream.format == MM_PIXEL_FORMAT_INVALID) {
5769 debug_error("Wrong condition!!");
5773 /* set size and timestamp */
5774 dataBlock = gst_buffer_peek_memory(buffer, 0);
5775 stream.length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
5776 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano sec -> mili sec */
5778 /* check zero-copy */
5779 if (player->set_mode.video_zc &&
5780 player->set_mode.media_packet_video_stream &&
5781 gst_buffer_n_memory(buffer) > 1) {
5782 metaBlock = gst_buffer_peek_memory(buffer, 1);
5783 gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
5784 video_buffer = (MMVideoBuffer *)mapinfo.data;
5789 if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
5790 /* copy pointer of tbm bo, stride, elevation */
5791 memcpy(stream.bo, video_buffer->handle.bo,
5792 sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
5794 else if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
5795 memcpy(stream.data, video_buffer->data,
5796 sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
5798 memcpy(stream.stride, video_buffer->stride_width,
5799 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5800 memcpy(stream.elevation, video_buffer->stride_height,
5801 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5802 /* set gst buffer */
5803 stream.internal_buffer = buffer;
5805 gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
5806 stream.data[0] = mapinfo.data;
5809 if (player->video_stream_cb) {
5810 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
5814 gst_memory_unmap(metaBlock, &mapinfo);
5816 gst_memory_unmap(dataBlock, &mapinfo);
5819 return GST_PAD_PROBE_OK;
5823 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket, gboolean use_video_stream)
5825 gchar* video_csc = "videoconvert"; // default colorspace converter
5826 GList* element_bucket = *bucket;
5828 return_val_if_fail(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5832 if (!player->set_mode.media_packet_video_stream && use_video_stream)
5834 if (player->set_mode.video_zc && strlen(player->ini.name_of_video_converter) > 0)
5836 video_csc = player->ini.name_of_video_converter;
5839 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5840 debug_log("using video converter: %s", video_csc);
5842 if ( !player->set_mode.video_zc)
5844 GstStructure *str = NULL;
5845 gint width = 0; //width of video
5846 gint height = 0; //height of video
5847 GstCaps* video_caps = NULL;
5848 GstStructure *structure = NULL;
5850 /* rotator, scaler and capsfilter */
5851 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5852 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "video scaler", TRUE, player);
5853 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CAPS, "capsfilter", "videocapsfilter", TRUE, player);
5855 /* get video stream caps parsed by demuxer */
5856 str = gst_caps_get_structure (player->v_stream_caps, 0);
5859 debug_error("cannot get structure");
5863 mm_attrs_get_int_by_name(player->attrs, "display_width", &width);
5867 gst_structure_set (structure, "width", G_TYPE_INT, width, NULL);
5869 structure = gst_structure_new("video/x-raw", "width", G_TYPE_INT, width, NULL);
5873 mm_attrs_get_int_by_name(player->attrs, "display_height", &height);
5877 gst_structure_set (structure, "height", G_TYPE_INT, height, NULL);
5879 structure = gst_structure_new("video/x-raw", "height", G_TYPE_INT, height, NULL);
5883 if (width || height) {
5884 video_caps = gst_caps_new_full(structure, NULL);
5885 gst_structure_free(structure);
5887 g_object_set (GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_CAPS].gst), "caps", video_caps, NULL );
5888 MMPLAYER_LOG_GST_CAPS_TYPE(video_caps);
5889 gst_caps_unref(video_caps);
5895 MMDisplaySurfaceType surface_type = MM_DISPLAY_SURFACE_NULL;
5896 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", (int *)&surface_type);
5898 if (player->set_mode.video_zc)
5900 if ( (surface_type == MM_DISPLAY_SURFACE_EVAS) && ( !strcmp(player->ini.videosink_element_evas, "evasimagesink")) )
5902 video_csc = player->ini.name_of_video_converter;
5910 if (video_csc && (strcmp(video_csc, "")))
5912 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5913 debug_log("using video converter: %s", video_csc);
5916 /* set video rotator */
5917 if ( !player->set_mode.video_zc )
5918 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5921 #if !defined(__arm__)
5922 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "videoscaler", TRUE, player);
5926 *bucket = element_bucket;
5928 return MM_ERROR_NONE;
5933 return MM_ERROR_PLAYER_INTERNAL;
5937 * This function is to create video pipeline.
5939 * @param player [in] handle of player
5940 * caps [in] src caps of decoder
5941 * surface_type [in] surface type for video rendering
5943 * @return This function returns zero on success.
5945 * @see __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5949 * - x surface (arm/x86) : xvimagesink
5950 * - evas surface (arm) : evaspixmapsink
5951 * fimcconvert ! evasimagesink
5952 * - evas surface (x86) : videoconvertor ! videoflip ! evasimagesink
5955 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5959 GList*element_bucket = NULL;
5960 MMPlayerGstElement* first_element = NULL;
5961 MMPlayerGstElement* videobin = NULL;
5962 gchar *videosink_element = NULL;
5966 return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5969 videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5972 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5975 player->pipeline->videobin = videobin;
5977 attrs = MMPLAYER_GET_ATTRS(player);
5980 debug_error("cannot get content attribute");
5981 return MM_ERROR_PLAYER_INTERNAL;
5985 videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
5986 videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
5987 if ( !videobin[MMPLAYER_V_BIN].gst )
5989 debug_error("failed to create videobin");
5993 if( player->use_video_stream ) // video stream callback, so send raw video data to application
5995 debug_log("using memsink\n");
5997 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, TRUE) != MM_ERROR_NONE)
6000 /* finally, create video sink. output will be BGRA8888. */
6001 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, "avsysmemsink", "videosink", TRUE, player);
6003 MMPLAYER_SIGNAL_CONNECT( player,
6004 videobin[MMPLAYER_V_SINK].gst,
6005 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
6007 G_CALLBACK(__mmplayer_videostream_cb),
6010 else // render video data using sink plugin like xvimagesink
6012 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, FALSE) != MM_ERROR_NONE)
6015 /* set video sink */
6016 switch (surface_type)
6018 case MM_DISPLAY_SURFACE_X:
6019 if (strlen(player->ini.videosink_element_x) > 0)
6020 videosink_element = player->ini.videosink_element_x;
6024 case MM_DISPLAY_SURFACE_EVAS:
6025 if (strlen(player->ini.videosink_element_evas) > 0)
6026 videosink_element = player->ini.videosink_element_evas;
6030 case MM_DISPLAY_SURFACE_X_EXT:
6032 void *pixmap_id_cb = NULL;
6033 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
6034 if (pixmap_id_cb) /* this is used for the videoTextue(canvasTexture) overlay */
6036 videosink_element = player->ini.videosink_element_x;
6040 debug_error("something wrong.. callback function for getting pixmap id is null");
6045 case MM_DISPLAY_SURFACE_NULL:
6046 if (strlen(player->ini.videosink_element_fake) > 0)
6047 videosink_element = player->ini.videosink_element_fake;
6052 debug_error("unidentified surface type");
6056 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, videosink_element, TRUE, player);
6057 debug_log("selected videosink name: %s", videosink_element);
6059 /* connect signal handlers for sink plug-in */
6060 switch (surface_type) {
6061 case MM_DISPLAY_SURFACE_X_EXT:
6062 MMPLAYER_SIGNAL_CONNECT( player,
6063 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
6064 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
6065 "frame-render-error",
6066 G_CALLBACK(__mmplayer_videoframe_render_error_cb),
6068 debug_log("videoTexture usage, connect a signal handler for pixmap rendering error");
6075 if (_mmplayer_update_video_param(player) != MM_ERROR_NONE)
6078 if (videobin[MMPLAYER_V_SINK].gst)
6080 GstPad *sink_pad = NULL;
6081 sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
6084 MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
6085 "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
6086 gst_object_unref (GST_OBJECT(sink_pad));
6090 /* store it as it's sink element */
6091 __mmplayer_add_sink( player, videobin[MMPLAYER_V_SINK].gst );
6093 /* adding created elements to bin */
6094 if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket) )
6096 debug_error("failed to add elements\n");
6100 /* Linking elements in the bucket by added order */
6101 if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
6103 debug_error("failed to link elements\n");
6107 /* get first element's sinkpad for creating ghostpad */
6108 first_element = (MMPlayerGstElement *)element_bucket->data;
6109 if ( !first_element )
6111 debug_error("failed to get first element from bucket\n");
6115 pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
6118 debug_error("failed to get pad from first element\n");
6122 /* create ghostpad */
6123 player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
6124 if ( FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
6126 debug_error("failed to add ghostpad to videobin\n");
6129 gst_object_unref(pad);
6131 /* done. free allocated variables */
6132 g_list_free(element_bucket);
6134 mm_attrs_set_int_by_name(attrs, "content_video_found", TRUE);
6138 return MM_ERROR_NONE;
6141 debug_error("ERROR : releasing videobin\n");
6143 g_list_free( element_bucket );
6146 gst_object_unref(GST_OBJECT(pad));
6148 /* release videobin with it's childs */
6149 if ( videobin[MMPLAYER_V_BIN].gst )
6151 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
6155 MMPLAYER_FREEIF( videobin );
6157 player->pipeline->videobin = NULL;
6159 return MM_ERROR_PLAYER_INTERNAL;
6162 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
6164 GList *element_bucket = NULL;
6165 MMPlayerGstElement *textbin = player->pipeline->textbin;
6167 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_FAKE_QUEUE, "queue", "text_f_queue", TRUE, player);
6168 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
6169 MMPLAYER_SIGNAL_CONNECT( player,
6170 G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
6171 MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
6173 G_CALLBACK(__mmplayer_update_subtitle),
6176 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
6177 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
6178 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
6180 if (!player->play_subtitle)
6182 debug_log ("add textbin sink as sink element of whole pipeline.\n");
6183 __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
6186 /* adding created elements to bin */
6187 debug_log("adding created elements to bin\n");
6188 if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
6190 debug_error("failed to add elements\n");
6194 /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
6195 GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
6196 GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
6198 /* linking elements in the bucket by added order. */
6199 debug_log("Linking elements in the bucket by added order.\n");
6200 if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
6202 debug_error("failed to link elements\n");
6206 /* done. free allocated variables */
6207 g_list_free(element_bucket);
6209 if (textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst)
6212 GstPad *ghostpad = NULL;
6214 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst), "sink");
6217 debug_error("failed to get video pad of textbin\n");
6218 return MM_ERROR_PLAYER_INTERNAL;
6221 ghostpad = gst_ghost_pad_new("text_sink", pad);
6222 gst_object_unref(pad);
6226 debug_error("failed to create ghostpad of textbin\n");
6230 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad))
6232 debug_error("failed to add ghostpad to textbin\n");
6237 return MM_ERROR_NONE;
6240 g_list_free(element_bucket);
6242 return MM_ERROR_PLAYER_INTERNAL;
6245 static int __mmplayer_gst_create_text_pipeline(mm_player_t* player)
6247 MMPlayerGstElement *textbin = NULL;
6248 GList *element_bucket = NULL;
6250 GstPad *ghostpad = NULL;
6255 return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6258 textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
6261 debug_error("failed to allocate memory for textbin\n");
6262 return MM_ERROR_PLAYER_NO_FREE_SPACE;
6266 textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
6267 textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
6268 if ( !textbin[MMPLAYER_T_BIN].gst )
6270 debug_error("failed to create textbin\n");
6275 player->pipeline->textbin = textbin;
6278 if (player->use_textoverlay)
6280 debug_log ("use textoverlay for displaying \n");
6282 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_TEXT_FAKE_QUEUE, "queue", "text_t_queue", textbin[MMPLAYER_T_BIN].gst, player);
6284 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_QUEUE, "queue", "text_v_queue", textbin[MMPLAYER_T_BIN].gst, player);
6286 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_CONVERTER, "fimcconvert", "text_v_converter", textbin[MMPLAYER_T_BIN].gst, player);
6288 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_OVERLAY, "textoverlay", "text_overlay", textbin[MMPLAYER_T_BIN].gst, player);
6290 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_QUEUE].gst, "src", textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "sink"))
6292 debug_error("failed to link queue and converter\n");
6296 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "video_sink"))
6298 debug_error("failed to link queue and textoverlay\n");
6302 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "text_sink"))
6304 debug_error("failed to link queue and textoverlay\n");
6310 int surface_type = 0;
6312 debug_log ("use subtitle message for displaying \n");
6314 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
6316 switch(surface_type)
6318 case MM_DISPLAY_SURFACE_X:
6319 case MM_DISPLAY_SURFACE_EVAS:
6320 case MM_DISPLAY_SURFACE_GL:
6321 case MM_DISPLAY_SURFACE_NULL:
6322 case MM_DISPLAY_SURFACE_X_EXT:
6323 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE)
6325 debug_error("failed to make plain text elements\n");
6334 gst_object_unref(pad);
6338 return MM_ERROR_NONE;
6342 debug_log("ERROR : releasing textbin\n");
6345 gst_object_unref(GST_OBJECT(pad));
6348 gst_object_unref(GST_OBJECT(ghostpad));
6350 g_list_free( element_bucket );
6352 /* release element which are not added to bin */
6353 for ( i = 1; i < MMPLAYER_T_NUM; i++ ) /* NOTE : skip bin */
6355 if ( textbin[i].gst )
6357 GstObject* parent = NULL;
6358 parent = gst_element_get_parent( textbin[i].gst );
6362 gst_object_unref(GST_OBJECT(textbin[i].gst));
6363 textbin[i].gst = NULL;
6367 gst_object_unref(GST_OBJECT(parent));
6372 /* release textbin with it's childs */
6373 if ( textbin[MMPLAYER_T_BIN].gst )
6375 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
6378 MMPLAYER_FREEIF( textbin );
6380 player->pipeline->textbin = NULL;
6382 return MM_ERROR_PLAYER_INTERNAL;
6387 __mmplayer_gst_create_subtitle_src(mm_player_t* player)
6389 MMPlayerGstElement* mainbin = NULL;
6390 MMHandleType attrs = 0;
6391 GstElement *subsrc = NULL;
6392 GstElement *subparse = NULL;
6393 gchar *subtitle_uri =NULL;
6394 const gchar *charset = NULL;
6400 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
6402 mainbin = player->pipeline->mainbin;
6404 attrs = MMPLAYER_GET_ATTRS(player);
6407 debug_error("cannot get content attribute\n");
6408 return MM_ERROR_PLAYER_INTERNAL;
6411 mm_attrs_get_string_by_name ( attrs, "subtitle_uri", &subtitle_uri );
6412 if ( !subtitle_uri || strlen(subtitle_uri) < 1)
6414 debug_error("subtitle uri is not proper filepath.\n");
6415 return MM_ERROR_PLAYER_INVALID_URI;
6417 debug_log("subtitle file path is [%s].\n", subtitle_uri);
6420 /* create the subtitle source */
6421 subsrc = gst_element_factory_make("filesrc", "subtitle_source");
6424 debug_error ( "failed to create filesrc element\n" );
6427 g_object_set(G_OBJECT (subsrc), "location", subtitle_uri, NULL);
6429 mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6430 mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
6432 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc))
6434 debug_warning("failed to add queue\n");
6439 subparse = gst_element_factory_make("subparse", "subtitle_parser");
6442 debug_error ( "failed to create subparse element\n" );
6446 charset = util_get_charset(subtitle_uri);
6449 debug_log ("detected charset is %s\n", charset );
6450 g_object_set (G_OBJECT (subparse), "subtitle-encoding", charset, NULL);
6453 mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE;
6454 mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
6456 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse))
6458 debug_warning("failed to add subparse\n");
6462 if (!gst_element_link_pads (subsrc, "src", subparse, "sink"))
6464 debug_warning("failed to link subsrc and subparse\n");
6468 player->play_subtitle = TRUE;
6469 player->adjust_subtitle_pos = 0;
6471 debug_log ("play subtitle using subtitle file\n");
6473 if (player->pipeline->textbin == NULL)
6475 if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player))
6477 debug_error("failed to create textbin. continuing without text\n");
6481 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst)))
6483 debug_warning("failed to add textbin\n");
6487 debug_log ("link text input selector and textbin ghost pad");
6489 player->textsink_linked = 1;
6490 player->external_text_idx = 0;
6491 debug_msg("player->textsink_linked set to 1\n");
6495 debug_log("text bin has been created. reuse it.");
6496 player->external_text_idx = 1;
6499 if (!gst_element_link_pads (subparse, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink"))
6501 debug_warning("failed to link subparse and textbin\n");
6505 pad = gst_element_get_static_pad (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
6509 debug_error("failed to get sink pad from textsink to probe data");
6510 return MM_ERROR_PLAYER_INTERNAL;
6513 gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
6514 __mmplayer_subtitle_adjust_position_probe, player, NULL);
6516 gst_object_unref(pad);
6522 return MM_ERROR_NONE;
6525 player->textsink_linked = 0;
6526 return MM_ERROR_PLAYER_INTERNAL;
6530 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
6532 mm_player_t* player = (mm_player_t*) data;
6533 MMMessageParamType msg = {0, };
6534 GstClockTime duration = 0;
6535 gpointer text = NULL;
6536 guint text_size = 0;
6537 gboolean ret = TRUE;
6538 GstMapInfo mapinfo = GST_MAP_INFO_INIT;
6542 return_val_if_fail ( player, FALSE );
6543 return_val_if_fail ( buffer, FALSE );
6545 gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
6546 text = g_memdup(mapinfo.data, mapinfo.size);
6547 text_size = mapinfo.size;
6548 duration = GST_BUFFER_DURATION(buffer);
6551 if ( player->set_mode.subtitle_off )
6553 debug_log("subtitle is OFF.\n" );
6557 if ( !text || (text_size == 0))
6559 debug_log("There is no subtitle to be displayed.\n" );
6563 msg.data = (void *) text;
6564 msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
6566 debug_log("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
6568 MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
6569 gst_buffer_unmap(buffer, &mapinfo);
6576 static GstPadProbeReturn
6577 __mmplayer_subtitle_adjust_position_probe (GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
6580 mm_player_t *player = (mm_player_t *) u_data;
6581 GstClockTime cur_timestamp = 0;
6582 gint64 adjusted_timestamp = 0;
6583 GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
6584 GstMapInfo probe_info = GST_MAP_INFO_INIT;
6586 return_val_if_fail ( player, FALSE );
6588 gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
6590 if ( player->set_mode.subtitle_off )
6592 debug_log("subtitle is OFF.\n" );
6596 if (player->adjust_subtitle_pos == 0 )
6598 debug_log("nothing to do");
6602 cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
6603 adjusted_timestamp = (gint64) cur_timestamp + ((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
6605 gst_buffer_unmap(buffer, &probe_info);
6607 if ( adjusted_timestamp < 0)
6609 debug_log("adjusted_timestamp under zero");
6614 GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
6615 debug_log("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
6616 GST_TIME_ARGS(cur_timestamp),
6617 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
6619 return GST_PAD_PROBE_OK;
6621 static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
6625 /* check player and subtitlebin are created */
6626 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6627 return_val_if_fail ( player->play_subtitle, MM_ERROR_NOT_SUPPORT_API );
6631 debug_log ("nothing to do\n");
6633 return MM_ERROR_NONE;
6638 case MM_PLAYER_POS_FORMAT_TIME:
6640 /* check current postion */
6641 player->adjust_subtitle_pos = position;
6643 debug_log("save adjust_subtitle_pos in player") ;
6649 debug_warning("invalid format.\n");
6651 return MM_ERROR_INVALID_ARGUMENT;
6657 return MM_ERROR_NONE;
6659 static int __gst_adjust_video_position(mm_player_t* player, int offset)
6662 debug_log("adjusting video_pos in player") ;
6663 int current_pos = 0;
6664 /* check player and videobin are created */
6665 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6666 if ( !player->pipeline->videobin ||
6667 !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
6669 debug_log("no video pipeline or sink is there");
6670 return MM_ERROR_PLAYER_INVALID_STATE ;
6674 debug_log ("nothing to do\n");
6676 return MM_ERROR_NONE;
6678 if(__gst_get_position ( player, MM_PLAYER_POS_FORMAT_TIME, (unsigned long*)¤t_pos ) != MM_ERROR_NONE )
6680 debug_log("failed to get current position");
6681 return MM_ERROR_PLAYER_INTERNAL;
6683 if ( (current_pos - offset ) < GST_TIME_AS_MSECONDS(player->duration) )
6685 debug_log("enter video delay is valid");
6688 debug_log("enter video delay is crossing content boundary");
6689 return MM_ERROR_INVALID_ARGUMENT ;
6691 g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst),"ts-offset",((gint64) offset * G_GINT64_CONSTANT(1000000)),NULL);
6692 debug_log("video delay has been done");
6695 return MM_ERROR_NONE;
6699 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data) // @
6701 GstElement *appsrc = element;
6702 tBuffer *buf = (tBuffer *)user_data;
6703 GstBuffer *buffer = NULL;
6704 GstFlowReturn ret = GST_FLOW_OK;
6707 return_if_fail ( element );
6708 return_if_fail ( buf );
6710 buffer = gst_buffer_new ();
6712 if (buf->offset >= buf->len)
6714 debug_log("call eos appsrc\n");
6715 g_signal_emit_by_name (appsrc, "end-of-stream", &ret);
6719 if ( buf->len - buf->offset < size)
6721 len = buf->len - buf->offset + buf->offset;
6724 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));
6725 GST_BUFFER_OFFSET(buffer) = buf->offset;
6726 GST_BUFFER_OFFSET_END(buffer) = buf->offset + len;
6728 //debug_log("feed buffer %p, offset %u-%u length %u\n", buffer, buf->offset, buf->len,len);
6729 g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
6735 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data) // @
6737 tBuffer *buf = (tBuffer *)user_data;
6739 return_val_if_fail ( buf, FALSE );
6741 buf->offset = (int)size;
6747 __gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data) // @
6749 mm_player_t *player = (mm_player_t*)user_data;
6750 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
6752 return_if_fail ( player );
6754 debug_msg("app-src: feed data\n");
6756 if (player->media_stream_buffer_status_cb[type])
6757 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
6761 __gst_appsrc_seek_data(GstElement *element, guint64 offset, gpointer user_data) // @
6763 mm_player_t *player = (mm_player_t*)user_data;
6764 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
6766 return_val_if_fail ( player, FALSE );
6768 debug_msg("app-src: seek data\n");
6770 if(player->media_stream_seek_data_cb[type])
6771 player->media_stream_seek_data_cb[type](type, offset, player->buffer_cb_user_param);
6778 __gst_appsrc_enough_data(GstElement *element, gpointer user_data) // @
6780 mm_player_t *player = (mm_player_t*)user_data;
6781 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
6783 return_val_if_fail ( player, FALSE );
6785 debug_msg("app-src: enough data:%p\n", player->media_stream_buffer_status_cb[type]);
6787 if (player->media_stream_buffer_status_cb[type])
6788 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
6794 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
6796 mm_player_t* player = (mm_player_t*)hplayer;
6797 GstBuffer *buffer = NULL;
6798 GstFlowReturn gst_ret = GST_FLOW_OK;
6799 int ret = MM_ERROR_NONE;
6804 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6806 /* check current state */
6807 // MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
6810 /* NOTE : we should check and create pipeline again if not created as we destroy
6811 * whole pipeline when stopping in streamming playback
6813 if ( ! player->pipeline )
6815 if ( MM_ERROR_NONE != __gst_realize( player ) )
6817 debug_error("failed to realize before starting. only in streamming\n");
6818 return MM_ERROR_PLAYER_INTERNAL;
6822 debug_msg("app-src: pushing data\n");
6826 debug_error("buf is null\n");
6827 return MM_ERROR_NONE;
6830 buffer = gst_buffer_new ();
6834 debug_log("call eos appsrc\n");
6835 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
6836 return MM_ERROR_NONE;
6839 //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));
6841 debug_log("feed buffer %p, length %u\n", buf, size);
6842 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
6849 /* if retval is FALSE, it will be dropped for perfomance. */
6851 __mmplayer_check_useful_message(mm_player_t *player, GstMessage * message)
6853 gboolean retval = FALSE;
6855 if ( !(player->pipeline && player->pipeline->mainbin) )
6857 debug_error("player pipeline handle is null");
6861 switch (GST_MESSAGE_TYPE (message))
6863 case GST_MESSAGE_TAG:
6864 case GST_MESSAGE_EOS:
6865 case GST_MESSAGE_ERROR:
6866 case GST_MESSAGE_WARNING:
6867 case GST_MESSAGE_CLOCK_LOST:
6868 case GST_MESSAGE_NEW_CLOCK:
6869 case GST_MESSAGE_ELEMENT:
6870 case GST_MESSAGE_DURATION_CHANGED:
6871 case GST_MESSAGE_ASYNC_START:
6874 case GST_MESSAGE_ASYNC_DONE:
6875 case GST_MESSAGE_STATE_CHANGED:
6876 /* we only handle messages from pipeline */
6877 if(( message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst ) && (!player->pp_rebuilding))
6882 case GST_MESSAGE_BUFFERING:
6884 gint buffer_percent = 0;
6886 gst_message_parse_buffering (message, &buffer_percent);
6888 if ((MMPLAYER_IS_STREAMING(player)) &&
6889 (player->streamer) &&
6890 (player->streamer->is_buffering == TRUE) &&
6891 (buffer_percent == MAX_BUFFER_PERCENT))
6893 debug_log (">>> [%s] Buffering DONE is detected !!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
6894 player->streamer->is_buffering_done = TRUE;
6908 static GstBusSyncReply
6909 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
6911 mm_player_t *player = (mm_player_t *)data;
6912 GstBusSyncReply reply = GST_BUS_DROP;
6914 if ( ! ( player->pipeline && player->pipeline->mainbin ) )
6916 debug_error("player pipeline handle is null");
6917 return GST_BUS_PASS;
6920 if (!__mmplayer_check_useful_message(player, message))
6922 gst_message_unref (message);
6923 return GST_BUS_DROP;
6926 switch (GST_MESSAGE_TYPE (message))
6928 case GST_MESSAGE_STATE_CHANGED:
6929 /* post directly for fast launch */
6930 if (player->sync_handler) {
6931 __mmplayer_gst_callback(NULL, message, player);
6932 reply = GST_BUS_DROP;
6935 reply = GST_BUS_PASS;
6938 case GST_MESSAGE_TAG:
6939 __mmplayer_gst_extract_tag_from_msg(player, message);
6943 GstTagList *tags = NULL;
6945 gst_message_parse_tag (message, &tags);
6947 debug_error("TAGS received from element \"%s\".\n",
6948 GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
6950 gst_tag_list_foreach (tags, print_tag, NULL);
6951 gst_tag_list_free (tags);
6959 case GST_MESSAGE_DURATION_CHANGED:
6960 __mmplayer_gst_handle_duration(player, message);
6962 case GST_MESSAGE_ASYNC_DONE:
6963 /* NOTE:Don't call gst_callback directly
6964 * because previous frame can be showed even though this message is received for seek.
6967 reply = GST_BUS_PASS;
6971 if (reply == GST_BUS_DROP)
6972 gst_message_unref (message);
6979 __mm_player_src_pad_block_cb (GstPad *pad, gboolean blocked, gpointer user_data)
6983 debug_log("src pad is blocked");
6987 debug_log("src pad is unblocked");
6992 __mmplayer_gst_create_decoder ( mm_player_t *player,
6993 MMPlayerTrackType track,
6995 enum MainElementID elemId,
6998 gboolean ret = TRUE;
6999 GstPad *sinkpad = NULL;
7003 return_val_if_fail( player &&
7005 player->pipeline->mainbin, FALSE);
7006 return_val_if_fail((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE);
7007 return_val_if_fail(srcpad, FALSE);
7008 return_val_if_fail((player->pipeline->mainbin[elemId].gst == NULL), FALSE);
7010 GstElement *decodebin = NULL;
7011 GstCaps *dec_caps = NULL;
7013 /* create decodebin */
7014 decodebin = gst_element_factory_make("decodebin", name);
7018 debug_error("error : fail to create decodebin for %d decoder\n", track);
7023 /* raw pad handling signal */
7024 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7025 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
7027 /* This signal is emitted whenever decodebin2 finds a new stream. It is emitted
7028 before looking for any elements that can handle that stream.*/
7029 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
7030 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
7032 /* This signal is emitted when a element is added to the bin.*/
7033 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
7034 G_CALLBACK(__mmplayer_gst_element_added), player);
7036 if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), decodebin))
7038 debug_error("failed to add new decodebin\n");
7043 dec_caps = gst_pad_query_caps (srcpad, NULL);
7046 //debug_log ("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
7047 g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
7048 gst_caps_unref(dec_caps);
7051 player->pipeline->mainbin[elemId].id = elemId;
7052 player->pipeline->mainbin[elemId].gst = decodebin;
7054 sinkpad = gst_element_get_static_pad (decodebin, "sink");
7056 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
7058 debug_warning ("failed to link [%s:%s] to decoder\n", GST_DEBUG_PAD_NAME(srcpad));
7059 gst_object_unref (GST_OBJECT(decodebin));
7062 if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (decodebin))
7064 debug_error("failed to sync second level decodebin state with parent\n");
7067 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
7068 // TO CHECK : gst_pad_set_blocked_async (srcpad, FALSE, __mm_player_src_pad_block_cb, NULL);
7070 debug_log("Total num of %d tracks = %d \n", track, player->selector[track].total_track_num);
7075 gst_object_unref ( GST_OBJECT(sinkpad) );
7085 * This function is to create audio or video pipeline for playing.
7087 * @param player [in] handle of player
7089 * @return This function returns zero on success.
7094 __mmplayer_gst_create_pipeline(mm_player_t* player) // @
7097 MMPlayerGstElement *mainbin = NULL;
7098 MMHandleType attrs = 0;
7099 GstElement* element = NULL;
7101 GstElement* elem_src_audio = NULL;
7102 GstElement* elem_src_subtitle = NULL;
7103 GstElement* es_video_queue = NULL;
7104 GstElement* es_audio_queue = NULL;
7105 GstElement* es_subtitle_queue = NULL;
7107 GList* element_bucket = NULL;
7108 gboolean need_state_holder = TRUE;
7113 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7115 /* get profile attribute */
7116 attrs = MMPLAYER_GET_ATTRS(player);
7119 debug_error("cannot get content attribute\n");
7123 /* create pipeline handles */
7124 if ( player->pipeline )
7126 debug_warning("pipeline should be released before create new one\n");
7130 player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0( sizeof(MMPlayerGstPipelineInfo) );
7131 if (player->pipeline == NULL)
7134 memset( player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo) );
7137 /* create mainbin */
7138 mainbin = (MMPlayerGstElement*) g_malloc0( sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM );
7139 if (mainbin == NULL)
7142 memset( mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
7144 /* create pipeline */
7145 mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
7146 mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
7147 if ( ! mainbin[MMPLAYER_M_PIPE].gst )
7149 debug_error("failed to create pipeline\n");
7152 player->demux_pad_index = 0;
7153 player->subtitle_language_list = NULL;
7155 player->is_subtitle_force_drop = FALSE;
7156 player->last_multiwin_status = FALSE;
7158 _mmplayer_track_initialize(player);
7160 /* create source element */
7161 switch ( player->profile.uri_type )
7163 /* rtsp streamming */
7164 case MM_PLAYER_URI_TYPE_URL_RTSP:
7166 gint network_bandwidth;
7167 gchar *user_agent, *wap_profile;
7169 element = gst_element_factory_make(player->ini.name_of_rtspsrc, "streaming_source");
7173 debug_error("failed to create streaming source element\n");
7177 debug_log("using streamming source [%s].\n", player->ini.name_of_rtspsrc);
7180 network_bandwidth = 0;
7181 user_agent = wap_profile = NULL;
7184 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
7185 mm_attrs_get_string_by_name ( attrs,"streaming_wap_profile", &wap_profile );
7186 mm_attrs_get_int_by_name ( attrs, "streaming_network_bandwidth", &network_bandwidth );
7188 secure_debug_log("user_agent : %s\n", user_agent);
7189 secure_debug_log("wap_profile : %s\n", wap_profile);
7191 /* setting property to streaming source */
7192 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7194 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
7196 g_object_set(G_OBJECT(element), "wap_profile", wap_profile, NULL);
7198 MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7199 G_CALLBACK (__mmplayer_gst_rtp_dynamic_pad), player );
7200 MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
7201 G_CALLBACK (__mmplayer_gst_rtp_no_more_pads), player );
7203 player->use_decodebin = FALSE;
7207 /* WFD streamming */
7208 case MM_PLAYER_URI_TYPE_URL_WFD:
7210 element = gst_element_factory_make("wfdrtspsrc", "wfd_source");
7213 debug_error("failed to create wfd streaming source element\n");
7216 debug_log("using wfd streamming source wfdrtspsrc.\n");
7217 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7218 g_object_set(G_OBJECT(element), "debug", TRUE, NULL);
7219 g_object_set(G_OBJECT(element), "latency", 0, NULL);
7220 MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7221 G_CALLBACK (__mmplayer_gst_wfd_dynamic_pad), player );
7223 player->use_decodebin = FALSE;
7228 case MM_PLAYER_URI_TYPE_URL_HTTP:
7230 gchar *user_agent, *proxy, *cookies, **cookie_list;
7231 gint http_timeout = DEFAULT_HTTP_TIMEOUT;
7232 user_agent = proxy = cookies = NULL;
7234 gint mode = MM_PLAYER_PD_MODE_NONE;
7236 mm_attrs_get_int_by_name ( attrs, "pd_mode", &mode );
7238 player->pd_mode = mode;
7240 debug_log("http playback, PD mode : %d\n", player->pd_mode);
7242 if ( ! MMPLAYER_IS_HTTP_PD(player) )
7244 element = gst_element_factory_make(player->ini.name_of_httpsrc, "http_streaming_source");
7247 debug_error("failed to create http streaming source element[%s].\n", player->ini.name_of_httpsrc);
7250 debug_log("using http streamming source [%s].\n", player->ini.name_of_httpsrc);
7253 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
7254 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
7255 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
7256 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
7258 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
7259 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
7261 debug_log("get timeout from ini\n");
7262 http_timeout = player->ini.http_timeout;
7266 secure_debug_log("location : %s\n", player->profile.uri);
7267 secure_debug_log("cookies : %s\n", cookies);
7268 secure_debug_log("proxy : %s\n", proxy);
7269 secure_debug_log("user_agent : %s\n", user_agent);
7270 debug_log("timeout : %d\n", http_timeout);
7272 /* setting property to streaming source */
7273 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7274 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
7275 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
7277 /* check if prosy is vailid or not */
7278 if ( util_check_valid_url ( proxy ) )
7279 g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
7280 /* parsing cookies */
7281 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
7282 g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
7284 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
7286 if ( MMPLAYER_URL_HAS_DASH_SUFFIX(player) )
7288 debug_warning("it's dash. and it's still experimental feature.");
7290 else if (MMPLAYER_URL_HAS_HLS_SUFFIX(player) )
7292 debug_warning("it's hls. using decodebin");
7295 else // progressive download
7297 gchar* location = NULL;
7299 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
7303 mm_attrs_get_string_by_name ( attrs, "pd_location", &path );
7305 MMPLAYER_FREEIF(player->pd_file_save_path);
7307 debug_log("PD Location : %s\n", path);
7311 player->pd_file_save_path = g_strdup(path);
7315 debug_error("can't find pd location so, it should be set \n");
7316 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
7320 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
7323 debug_error("failed to create PD push source element[%s].\n", "pdpushsrc");
7327 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
7328 g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
7330 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7332 g_object_get(element, "location", &location, NULL);
7333 debug_log("PD_LOCATION [%s].\n", location);
7341 case MM_PLAYER_URI_TYPE_FILE:
7344 debug_log("using filesrc for 'file://' handler.\n");
7346 element = gst_element_factory_make("filesrc", "source");
7350 debug_error("failed to create filesrc\n");
7354 g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */
7355 //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL);
7359 case MM_PLAYER_URI_TYPE_SS:
7361 gint http_timeout = DEFAULT_HTTP_TIMEOUT;
7362 element = gst_element_factory_make("souphttpsrc", "http streaming source");
7365 debug_error("failed to create http streaming source element[%s]", player->ini.name_of_httpsrc);
7369 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
7371 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
7372 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
7374 debug_log("get timeout from ini\n");
7375 http_timeout = player->ini.http_timeout;
7378 /* setting property to streaming source */
7379 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7380 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
7385 case MM_PLAYER_URI_TYPE_BUFF:
7387 guint64 stream_type = GST_APP_STREAM_TYPE_STREAM;
7389 debug_log("mem src is selected\n");
7391 element = gst_element_factory_make("appsrc", "buff-source");
7394 debug_error("failed to create appsrc element\n");
7398 g_object_set( element, "stream-type", stream_type, NULL );
7399 //g_object_set( element, "size", player->mem_buf.len, NULL );
7400 //g_object_set( element, "blocksize", (guint64)20480, NULL );
7402 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7403 G_CALLBACK(__gst_appsrc_seek_data), player);
7404 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7405 G_CALLBACK(__gst_appsrc_feed_data), player);
7406 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7407 G_CALLBACK(__gst_appsrc_enough_data), player);
7411 case MM_PLAYER_URI_TYPE_ES_BUFF:
7413 debug_log("es buff src is selected\n");
7415 if (player->v_stream_caps)
7417 element = gst_element_factory_make("appsrc", "video_appsrc");
7420 debug_critical("failed to create video app source element[appsrc].\n" );
7424 if ( player->a_stream_caps )
7426 elem_src_audio = gst_element_factory_make("appsrc", "audio_appsrc");
7427 if ( !elem_src_audio )
7429 debug_critical("failed to create audio app source element[appsrc].\n" );
7434 else if ( player->a_stream_caps )
7436 /* no video, only audio pipeline*/
7437 element = gst_element_factory_make("appsrc", "audio_appsrc");
7440 debug_critical("failed to create audio app source element[appsrc].\n" );
7445 if ( player->s_stream_caps )
7447 elem_src_subtitle = gst_element_factory_make("appsrc", "subtitle_appsrc");
7448 if ( !elem_src_subtitle )
7450 debug_critical("failed to create subtitle app source element[appsrc].\n" );
7455 debug_log("setting app sources properties.\n");
7456 debug_log("location : %s\n", player->profile.uri);
7458 if ( player->v_stream_caps && element )
7460 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
7461 "blocksize", (guint)1048576, /* size of many video frames are larger than default blocksize as 4096 */
7462 "caps", player->v_stream_caps, NULL);
7464 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
7465 g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
7466 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
7467 g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
7469 /*Fix Seek External Demuxer: set audio and video appsrc as seekable */
7470 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
7471 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7472 G_CALLBACK(__gst_seek_video_data), player);
7474 if (player->a_stream_caps && elem_src_audio)
7476 g_object_set(G_OBJECT(elem_src_audio), "format", GST_FORMAT_TIME,
7477 "caps", player->a_stream_caps, NULL);
7479 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7480 g_object_set(G_OBJECT(elem_src_audio), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7481 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7482 g_object_set(G_OBJECT(elem_src_audio), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7484 /*Fix Seek External Demuxer: set audio and video appsrc as seekable */
7485 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_audio), GST_APP_STREAM_TYPE_SEEKABLE);
7486 MMPLAYER_SIGNAL_CONNECT( player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7487 G_CALLBACK(__gst_seek_audio_data), player);
7490 else if (player->a_stream_caps && element)
7492 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
7493 "caps", player->a_stream_caps, NULL);
7495 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7496 g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7497 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
7498 g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
7500 /*Fix Seek External Demuxer: set audio and video appsrc as seekable */
7501 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
7502 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7503 G_CALLBACK(__gst_seek_audio_data), player);
7506 if (player->s_stream_caps && elem_src_subtitle)
7508 g_object_set(G_OBJECT(elem_src_subtitle), "format", GST_FORMAT_TIME,
7509 "caps", player->s_stream_caps, NULL);
7511 if ( player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
7512 g_object_set(G_OBJECT(elem_src_subtitle), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
7513 if ( player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
7514 g_object_set(G_OBJECT(elem_src_subtitle), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
7516 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_subtitle), GST_APP_STREAM_TYPE_SEEKABLE);
7518 MMPLAYER_SIGNAL_CONNECT( player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7519 G_CALLBACK(__gst_seek_subtitle_data), player);
7522 if (!player->es_player_push_mode)
7524 if (player->v_stream_caps && element)
7526 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7527 G_CALLBACK(__gst_appsrc_feed_video_data), player);
7528 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7529 G_CALLBACK(__gst_appsrc_enough_video_data), player);
7531 if (player->a_stream_caps && elem_src_audio)
7533 MMPLAYER_SIGNAL_CONNECT( player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7534 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
7535 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7536 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
7539 else if (player->a_stream_caps && element)
7541 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7542 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
7543 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7544 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
7547 if (player->s_stream_caps && elem_src_subtitle)
7549 MMPLAYER_SIGNAL_CONNECT( player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7550 G_CALLBACK(__gst_appsrc_feed_subtitle_data), player);
7554 need_state_holder = FALSE;
7559 case MM_PLAYER_URI_TYPE_MEM:
7561 guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
7563 debug_log("mem src is selected\n");
7565 element = gst_element_factory_make("appsrc", "mem-source");
7568 debug_error("failed to create appsrc element\n");
7572 g_object_set( element, "stream-type", stream_type, NULL );
7573 g_object_set( element, "size", player->mem_buf.len, NULL );
7574 g_object_set( element, "blocksize", (guint64)20480, NULL );
7576 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7577 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->mem_buf );
7578 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7579 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->mem_buf );
7582 case MM_PLAYER_URI_TYPE_URL:
7585 case MM_PLAYER_URI_TYPE_TEMP:
7588 case MM_PLAYER_URI_TYPE_NONE:
7593 /* check source element is OK */
7596 debug_error("no source element was created.\n");
7600 /* take source element */
7601 mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
7602 mainbin[MMPLAYER_M_SRC].gst = element;
7603 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
7605 if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL))
7607 player->streamer = __mm_player_streaming_create();
7608 __mm_player_streaming_initialize(player->streamer);
7611 if ( MMPLAYER_IS_HTTP_PD(player) )
7613 gdouble pre_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
7615 debug_log ("Picked queue2 element(pre buffer : %d sec)....\n", pre_buffering_time);
7616 element = gst_element_factory_make("queue2", "queue2");
7619 debug_error ( "failed to create http streaming buffer element\n" );
7624 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
7625 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
7626 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
7628 pre_buffering_time = (pre_buffering_time > 0)?(pre_buffering_time):(player->ini.http_buffering_time);
7630 __mm_player_streaming_set_queue2(player->streamer,
7633 player->ini.http_max_size_bytes,
7636 player->ini.http_buffering_limit,
7642 if (MMPLAYER_IS_ES_BUFF_SRC(player))
7644 if (player->v_stream_caps)
7646 es_video_queue = gst_element_factory_make("queue2", "video_queue");
7647 if (!es_video_queue)
7649 debug_error ("create es_video_queue for es player failed\n");
7652 mainbin[MMPLAYER_M_V_BUFFER].id = MMPLAYER_M_V_BUFFER;
7653 mainbin[MMPLAYER_M_V_BUFFER].gst = es_video_queue;
7654 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_V_BUFFER]);
7656 /* Adding audio appsrc to bucket */
7657 if (player->a_stream_caps && elem_src_audio)
7659 mainbin[MMPLAYER_M_2ND_SRC].id = MMPLAYER_M_2ND_SRC;
7660 mainbin[MMPLAYER_M_2ND_SRC].gst = elem_src_audio;
7661 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_2ND_SRC]);
7663 es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
7664 if (!es_audio_queue)
7666 debug_error ("create es_audio_queue for es player failed\n");
7669 mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
7670 mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
7671 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
7674 /* Only audio stream, no video */
7675 else if (player->a_stream_caps)
7677 es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
7678 if (!es_audio_queue)
7680 debug_error ("create es_audio_queue for es player failed\n");
7683 mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
7684 mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
7685 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
7688 if (player->s_stream_caps && elem_src_subtitle)
7690 mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
7691 mainbin[MMPLAYER_M_SUBSRC].gst = elem_src_subtitle;
7692 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SUBSRC]);
7694 es_subtitle_queue = gst_element_factory_make("queue2", "subtitle_queue");
7695 if (!es_subtitle_queue)
7697 debug_error ("create es_subtitle_queue for es player failed\n");
7700 mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_V_BUFFER;
7701 mainbin[MMPLAYER_M_S_BUFFER].gst = es_subtitle_queue;
7702 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
7707 /* create autoplugging element if src element is not a rtsp src */
7708 if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
7709 (player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_WFD)
7711 && (player->profile.uri_type != MM_PLAYER_URI_TYPE_ES_BUFF)
7716 enum MainElementID elemId = MMPLAYER_M_NUM;
7718 if ((player->use_decodebin) &&
7719 ((MMPLAYER_IS_HTTP_PD(player)) ||
7720 (!MMPLAYER_IS_HTTP_STREAMING(player))))
7722 elemId = MMPLAYER_M_AUTOPLUG;
7723 element = __mmplayer_create_decodebin(player);
7724 need_state_holder = FALSE;
7728 elemId = MMPLAYER_M_TYPEFIND;
7729 element = gst_element_factory_make("typefind", "typefinder");
7730 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
7731 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
7735 /* check autoplug element is OK */
7738 debug_error("can not create element (%d)\n", elemId);
7742 mainbin[elemId].id = elemId;
7743 mainbin[elemId].gst = element;
7745 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
7748 /* add elements to pipeline */
7749 if( !__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket))
7751 debug_error("Failed to add elements to pipeline\n");
7756 /* linking elements in the bucket by added order. */
7757 if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
7759 debug_error("Failed to link some elements\n");
7764 /* create fakesink element for keeping the pipeline state PAUSED. if needed */
7765 if ( need_state_holder )
7768 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
7769 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make ("fakesink", "state-holder");
7771 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
7773 debug_error ("fakesink element could not be created\n");
7776 GST_OBJECT_FLAG_UNSET (mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
7778 /* take ownership of fakesink. we are reusing it */
7779 gst_object_ref( mainbin[MMPLAYER_M_SRC_FAKESINK].gst );
7782 if ( FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
7783 mainbin[MMPLAYER_M_SRC_FAKESINK].gst) )
7785 debug_error("failed to add fakesink to bin\n");
7790 /* now we have completed mainbin. take it */
7791 player->pipeline->mainbin = mainbin;
7794 if (MMPLAYER_IS_ES_BUFF_SRC(player))
7796 GstPad *srcpad = NULL;
7798 if (mainbin[MMPLAYER_M_V_BUFFER].gst)
7800 srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_V_BUFFER].gst, "src");
7803 __mmplayer_gst_create_decoder ( player,
7804 MM_PLAYER_TRACK_TYPE_VIDEO,
7806 MMPLAYER_M_AUTOPLUG_V_DEC,
7809 gst_object_unref ( GST_OBJECT(srcpad) );
7814 if ((player->a_stream_caps) && (mainbin[MMPLAYER_M_A_BUFFER].gst))
7816 srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_BUFFER].gst, "src");
7819 __mmplayer_gst_create_decoder ( player,
7820 MM_PLAYER_TRACK_TYPE_AUDIO,
7822 MMPLAYER_M_AUTOPLUG_A_DEC,
7825 gst_object_unref ( GST_OBJECT(srcpad) );
7830 if (mainbin[MMPLAYER_M_S_BUFFER].gst)
7832 __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
7838 /* connect bus callback */
7839 bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
7842 debug_error ("cannot get bus from pipeline.\n");
7846 player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
7848 player->context.thread_default = g_main_context_get_thread_default();
7850 if (NULL == player->context.thread_default)
7852 player->context.thread_default = g_main_context_default();
7853 debug_log("thread-default context is the global default context");
7855 debug_warning("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
7857 /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
7858 if ( __mmplayer_check_subtitle ( player ) )
7860 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
7861 debug_error("fail to create subtitle src\n");
7864 /* set sync handler to get tag synchronously */
7865 gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL);
7868 gst_object_unref(GST_OBJECT(bus));
7869 g_list_free(element_bucket);
7873 return MM_ERROR_NONE;
7877 __mmplayer_gst_destroy_pipeline(player);
7878 g_list_free(element_bucket);
7880 /* release element which are not added to bin */
7881 for ( i = 1; i < MMPLAYER_M_NUM; i++ ) /* NOTE : skip pipeline */
7883 if ( mainbin[i].gst )
7885 GstObject* parent = NULL;
7886 parent = gst_element_get_parent( mainbin[i].gst );
7890 gst_object_unref(GST_OBJECT(mainbin[i].gst));
7891 mainbin[i].gst = NULL;
7895 gst_object_unref(GST_OBJECT(parent));
7900 /* release pipeline with it's childs */
7901 if ( mainbin[MMPLAYER_M_PIPE].gst )
7903 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7906 MMPLAYER_FREEIF( player->pipeline );
7907 MMPLAYER_FREEIF( mainbin );
7909 return MM_ERROR_PLAYER_INTERNAL;
7912 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
7914 GSource *source = NULL;
7918 source = g_main_context_find_source_by_id (context, source_id);
7922 debug_warning("context: %p, source id: %d, source: %p", context, source_id, source);
7923 g_source_destroy(source);
7930 __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
7933 int ret = MM_ERROR_NONE;
7937 return_val_if_fail ( player, MM_ERROR_INVALID_HANDLE );
7939 /* cleanup stuffs */
7940 MMPLAYER_FREEIF(player->type);
7941 player->have_dynamic_pad = FALSE;
7942 player->no_more_pad = FALSE;
7943 player->num_dynamic_pad = 0;
7944 player->demux_pad_index = 0;
7945 player->subtitle_language_list = NULL;
7946 player->use_deinterleave = FALSE;
7947 player->pp_rebuilding = FALSE;
7948 player->max_audio_channels = 0;
7949 player->video_share_api_delta = 0;
7950 player->video_share_clock_delta = 0;
7951 player->video_hub_download_mode = 0;
7953 __mmplayer_post_proc_reset(player);
7955 if (player->streamer)
7957 __mm_player_streaming_deinitialize (player->streamer);
7958 __mm_player_streaming_destroy(player->streamer);
7959 player->streamer = NULL;
7962 /* cleanup unlinked mime type */
7963 MMPLAYER_FREEIF(player->unlinked_audio_mime);
7964 MMPLAYER_FREEIF(player->unlinked_video_mime);
7965 MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
7967 /* cleanup running stuffs */
7968 __mmplayer_cancel_eos_timer( player );
7970 /* remove sound cb */
7971 if ( MM_ERROR_NONE != mm_sound_remove_device_information_changed_callback())
7973 debug_error("failed to mm_sound_remove_device_information_changed_callback()");
7976 /* cleanup gst stuffs */
7977 if ( player->pipeline )
7979 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
7980 GstTagList* tag_list = player->pipeline->tag_list;
7982 /* first we need to disconnect all signal hander */
7983 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_ALL );
7985 /* disconnecting bus watch */
7986 if ( player->bus_watcher )
7987 __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
7988 player->bus_watcher = 0;
7992 MMPlayerGstElement* audiobin = player->pipeline->audiobin;
7993 MMPlayerGstElement* videobin = player->pipeline->videobin;
7994 MMPlayerGstElement* textbin = player->pipeline->textbin;
7995 GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mainbin[MMPLAYER_M_PIPE].gst));
7996 gst_bus_set_sync_handler (bus, NULL, NULL, NULL);
7997 gst_object_unref(bus);
7999 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8000 ret = __mmplayer_gst_set_state ( player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout );
8001 if ( ret != MM_ERROR_NONE )
8003 debug_error("fail to change state to NULL\n");
8004 return MM_ERROR_PLAYER_INTERNAL;
8007 debug_warning("succeeded in chaning state to NULL\n");
8009 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
8012 if ( mainbin[MMPLAYER_M_SRC_FAKESINK].gst )
8013 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
8015 /* free avsysaudiosink
8016 avsysaudiosink should be unref when destory pipeline just after start play with BT.
8017 Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
8019 MMPLAYER_FREEIF( audiobin );
8020 MMPLAYER_FREEIF( videobin );
8021 MMPLAYER_FREEIF( textbin );
8022 MMPLAYER_FREEIF( mainbin );
8026 gst_tag_list_free(tag_list);
8028 MMPLAYER_FREEIF( player->pipeline );
8030 MMPLAYER_FREEIF(player->album_art);
8032 if (player->v_stream_caps)
8034 gst_caps_unref(player->v_stream_caps);
8035 player->v_stream_caps = NULL;
8038 if (player->a_stream_caps)
8040 gst_caps_unref(player->a_stream_caps);
8041 player->a_stream_caps = NULL;
8043 if (player->s_stream_caps)
8045 gst_caps_unref(player->s_stream_caps);
8046 player->s_stream_caps = NULL;
8049 _mmplayer_track_destroy(player);
8051 if ( player->sink_elements )
8052 g_list_free ( player->sink_elements );
8053 player->sink_elements = NULL;
8055 debug_warning("finished destroy pipeline\n");
8062 static int __gst_realize(mm_player_t* player) // @
8065 int ret = MM_ERROR_NONE;
8069 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8071 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
8073 ret = __mmplayer_gst_create_pipeline(player);
8076 debug_error("failed to create pipeline\n");
8080 /* set pipeline state to READY */
8081 /* NOTE : state change to READY must be performed sync. */
8082 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8083 ret = __mmplayer_gst_set_state(player,
8084 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
8086 if ( ret != MM_ERROR_NONE )
8088 /* return error if failed to set state */
8089 debug_error("failed to set READY state");
8094 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
8097 /* create dot before error-return. for debugging */
8098 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-realize" );
8105 static int __gst_unrealize(mm_player_t* player) // @
8107 int ret = MM_ERROR_NONE;
8111 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8113 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
8114 MMPLAYER_PRINT_STATE(player);
8116 /* release miscellaneous information */
8117 __mmplayer_release_misc( player );
8119 /* destroy pipeline */
8120 ret = __mmplayer_gst_destroy_pipeline( player );
8121 if ( ret != MM_ERROR_NONE )
8123 debug_error("failed to destory pipeline\n");
8127 /* release miscellaneous information.
8128 these info needs to be released after pipeline is destroyed. */
8129 __mmplayer_release_misc_post( player );
8131 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
8138 static int __gst_pending_seek ( mm_player_t* player )
8140 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
8141 int ret = MM_ERROR_NONE;
8145 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8147 if ( !player->pending_seek.is_pending )
8149 debug_log("pending seek is not reserved. nothing to do.\n" );
8153 /* check player state if player could pending seek or not. */
8154 current_state = MMPLAYER_CURRENT_STATE(player);
8156 if ( current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING )
8158 debug_warning("try to pending seek in %s state, try next time. \n",
8159 MMPLAYER_STATE_GET_NAME(current_state));
8163 debug_log("trying to play from (%lu) pending position\n", player->pending_seek.pos);
8165 ret = __gst_set_position ( player, player->pending_seek.format, player->pending_seek.pos, FALSE );
8167 if ( MM_ERROR_NONE != ret )
8168 debug_error("failed to seek pending postion. just keep staying current position.\n");
8170 player->pending_seek.is_pending = FALSE;
8177 static int __gst_start(mm_player_t* player) // @
8179 gboolean sound_extraction = 0;
8180 int ret = MM_ERROR_NONE;
8182 gboolean async = FALSE;
8186 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8188 /* get sound_extraction property */
8189 mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
8191 /* NOTE : if SetPosition was called before Start. do it now */
8192 /* streaming doesn't support it. so it should be always sync */
8193 /* !! create one more api to check if there is pending seek rather than checking variables */
8194 if ( (player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player))
8196 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
8197 ret = __gst_pause(player, FALSE);
8198 if ( ret != MM_ERROR_NONE )
8200 debug_error("failed to set state to PAUSED for pending seek\n");
8204 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
8206 if ( sound_extraction )
8208 debug_log("setting pcm extraction\n");
8210 ret = __mmplayer_set_pcm_extraction(player);
8211 if ( MM_ERROR_NONE != ret )
8213 debug_warning("failed to set pcm extraction\n");
8219 if ( MM_ERROR_NONE != __gst_pending_seek(player) )
8221 debug_warning("failed to seek pending postion. starting from the begin of content.\n");
8226 debug_log("current state before doing transition");
8227 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
8228 MMPLAYER_PRINT_STATE(player);
8231 /* set pipeline state to PLAYING */
8232 if (player->es_player_push_mode)
8236 /* set pipeline state to PLAYING */
8237 ret = __mmplayer_gst_set_state(player,
8238 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
8240 /* set pipeline state to PLAYING */
8241 ret = __mmplayer_gst_set_state(player,
8242 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
8244 if (ret == MM_ERROR_NONE)
8246 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
8250 debug_error("failed to set state to PLAYING");
8254 /* generating debug info before returning error */
8255 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-start" );
8262 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
8266 return_if_fail(player
8268 && player->pipeline->audiobin
8269 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
8271 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
8278 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
8282 return_if_fail(player
8284 && player->pipeline->audiobin
8285 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
8287 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
8292 static int __gst_stop(mm_player_t* player) // @
8294 GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
8295 MMHandleType attrs = 0;
8296 gboolean fadedown = FALSE;
8297 gboolean rewind = FALSE;
8299 int ret = MM_ERROR_NONE;
8302 gboolean async = FALSE;
8306 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
8307 return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
8309 debug_log("current state before doing transition");
8310 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
8311 MMPLAYER_PRINT_STATE(player);
8313 attrs = MMPLAYER_GET_ATTRS(player);
8316 debug_error("cannot get content attribute\n");
8317 return MM_ERROR_PLAYER_INTERNAL;
8320 mm_attrs_get_int_by_name(attrs, "sound_fadedown", &fadedown);
8322 /* enable fadedown */
8323 if (fadedown || player->sm.by_asm_cb)
8324 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8326 /* Just set state to PAUESED and the rewind. it's usual player behavior. */
8327 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
8329 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_BUFF ||
8330 player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS)
8332 state = GST_STATE_READY;
8336 state = GST_STATE_PAUSED;
8338 if ( ! MMPLAYER_IS_STREAMING(player) ||
8339 (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked)) {
8344 if (player->es_player_push_mode)
8349 ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, async, timeout );
8352 ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, FALSE, timeout );
8355 /* disable fadeout */
8356 if (fadedown || player->sm.by_asm_cb)
8357 __mmplayer_undo_sound_fadedown(player);
8359 /* return if set_state has failed */
8360 if ( ret != MM_ERROR_NONE )
8362 debug_error("failed to set state.\n");
8369 if ( ! __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8370 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
8371 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE) )
8373 debug_warning("failed to rewind\n");
8374 ret = MM_ERROR_PLAYER_SEEK;
8379 player->sent_bos = FALSE;
8382 if (player->es_player_push_mode) //for cloudgame
8387 /* wait for seek to complete */
8388 change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
8389 if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL )
8391 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
8395 debug_error("fail to stop player.\n");
8396 ret = MM_ERROR_PLAYER_INTERNAL;
8397 __mmplayer_dump_pipeline_state(player);
8400 /* generate dot file if enabled */
8401 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-stop" );
8408 int __gst_pause(mm_player_t* player, gboolean async) // @
8410 int ret = MM_ERROR_NONE;
8414 return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
8415 return_val_if_fail(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
8417 debug_log("current state before doing transition");
8418 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
8419 MMPLAYER_PRINT_STATE(player);
8421 /* set pipeline status to PAUSED */
8422 player->ignore_asyncdone = TRUE;
8424 ret = __mmplayer_gst_set_state(player,
8425 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
8427 player->ignore_asyncdone = FALSE;
8429 if ( FALSE == async )
8431 if ( ret != MM_ERROR_NONE )
8433 GstMessage *msg = NULL;
8434 GTimer *timer = NULL;
8435 gdouble MAX_TIMEOUT_SEC = 3;
8437 debug_error("failed to set state to PAUSED");
8439 timer = g_timer_new();
8440 g_timer_start(timer);
8442 GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
8443 gboolean got_msg = FALSE;
8444 /* check if gst error posted or not */
8447 msg = gst_bus_timed_pop(bus, GST_SECOND /2);
8450 if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR)
8452 GError *error = NULL;
8454 /* parse error code */
8455 gst_message_parse_error(msg, &error, NULL);
8457 if ( gst_structure_has_name ( gst_message_get_structure(msg), "streaming_error" ) )
8459 /* Note : the streaming error from the streaming source is handled
8460 * using __mmplayer_handle_streaming_error.
8462 __mmplayer_handle_streaming_error ( player, msg );
8467 debug_error("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
8469 if (error->domain == GST_STREAM_ERROR)
8471 ret = __gst_handle_stream_error( player, error, msg );
8473 else if (error->domain == GST_RESOURCE_ERROR)
8475 ret = __gst_handle_resource_error( player, error->code );
8477 else if (error->domain == GST_LIBRARY_ERROR)
8479 ret = __gst_handle_library_error( player, error->code );
8481 else if (error->domain == GST_CORE_ERROR)
8483 ret = __gst_handle_core_error( player, error->code );
8488 player->msg_posted = TRUE;
8490 gst_message_unref(msg);
8492 } while (!got_msg && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
8494 gst_object_unref(bus);
8495 g_timer_stop (timer);
8496 g_timer_destroy (timer);
8500 else if ( (!player->pipeline->videobin) && (!player->pipeline->audiobin) )
8502 if (MMPLAYER_IS_RTSP_STREAMING(player))
8504 return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
8506 else if ( ret== MM_ERROR_NONE)
8508 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
8512 /* generate dot file before returning error */
8513 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-pause" );
8520 int __gst_resume(mm_player_t* player, gboolean async) // @
8522 int ret = MM_ERROR_NONE;
8527 return_val_if_fail(player && player->pipeline,
8528 MM_ERROR_PLAYER_NOT_INITIALIZED);
8530 debug_log("current state before doing transition");
8531 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
8532 MMPLAYER_PRINT_STATE(player);
8534 /* generate dot file before returning error */
8535 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
8537 __mmplayer_set_antishock( player , FALSE );
8540 debug_log("do async state transition to PLAYING.\n");
8542 /* set pipeline state to PLAYING */
8543 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8545 ret = __mmplayer_gst_set_state(player,
8546 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout );
8547 if (ret != MM_ERROR_NONE)
8549 debug_error("failed to set state to PLAYING\n");
8556 // MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING );
8557 debug_log("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
8558 ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
8562 /* generate dot file before returning error */
8563 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
8571 __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called) // @
8573 unsigned long dur_msec = 0;
8574 gint64 dur_nsec = 0;
8575 gint64 pos_nsec = 0;
8576 gboolean ret = TRUE;
8577 gboolean accurated = FALSE;
8578 GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
8581 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8582 return_val_if_fail ( !MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP );
8584 if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
8585 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED )
8589 if( !MMPLAYER_IS_ES_BUFF_SRC(player) )
8592 /* check duration */
8593 /* NOTE : duration cannot be zero except live streaming.
8594 * Since some element could have some timing problemn with quering duration, try again.
8596 if ( !player->duration )
8598 if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
8602 player->duration = dur_nsec;
8605 if ( player->duration )
8607 dur_msec = GST_TIME_AS_MSECONDS(player->duration);
8611 debug_error("could not get the duration. fail to seek.\n");
8615 debug_log("playback rate: %f\n", player->playback_rate);
8617 mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
8620 seek_flags |= GST_SEEK_FLAG_ACCURATE;
8624 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
8630 case MM_PLAYER_POS_FORMAT_TIME:
8633 if( !MMPLAYER_IS_ES_BUFF_SRC(player) )
8636 /* check position is valid or not */
8637 if ( position > dur_msec )
8640 debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec);
8642 if ( player->doing_seek )
8644 debug_log("not completed seek");
8645 return MM_ERROR_PLAYER_DOING_SEEK;
8649 if ( !internal_called )
8650 player->doing_seek = TRUE;
8652 pos_nsec = position * G_GINT64_CONSTANT(1000000);
8654 if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked))
8656 gint64 cur_time = 0;
8658 /* get current position */
8659 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
8662 GstEvent *event = gst_event_new_seek (1.0,
8664 (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
8665 GST_SEEK_TYPE_SET, cur_time,
8666 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
8668 __gst_send_event_to_sink(player, event);
8671 __gst_pause( player, FALSE );
8674 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8675 GST_FORMAT_TIME, seek_flags,
8676 GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
8679 debug_error("failed to set position. dur[%lu] pos[%lu] pos_msec[%llu]\n", dur_msec, position, pos_nsec);
8685 case MM_PLAYER_POS_FORMAT_PERCENT:
8687 debug_log("seeking to (%lu)%% \n", position);
8689 if (player->doing_seek)
8691 debug_log("not completed seek");
8692 return MM_ERROR_PLAYER_DOING_SEEK;
8695 if ( !internal_called)
8696 player->doing_seek = TRUE;
8698 /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
8699 pos_nsec = (gint64) ( ( position * player->duration ) / 100 );
8700 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8701 GST_FORMAT_TIME, seek_flags,
8702 GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
8705 debug_error("failed to set position. dur[%lud] pos[%lud] pos_msec[%llud]\n", dur_msec, position, pos_nsec);
8716 /* NOTE : store last seeking point to overcome some bad operation
8717 * ( returning zero when getting current position ) of some elements
8719 player->last_position = pos_nsec;
8721 /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
8722 if ( player->playback_rate > 1.0 )
8723 _mmplayer_set_playspeed ( (MMHandleType)player, player->playback_rate );
8726 return MM_ERROR_NONE;
8729 player->pending_seek.is_pending = TRUE;
8730 player->pending_seek.format = format;
8731 player->pending_seek.pos = position;
8733 debug_warning("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n",
8734 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
8736 return MM_ERROR_NONE;
8739 debug_error("invalid arguments, position : %ld dur : %ld format : %d \n", position, dur_msec, format);
8740 return MM_ERROR_INVALID_ARGUMENT;
8743 player->doing_seek = FALSE;
8744 return MM_ERROR_PLAYER_SEEK;
8747 #define TRICKPLAY_OFFSET GST_MSECOND
8750 __gst_get_position(mm_player_t* player, int format, unsigned long* position) // @
8752 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
8753 signed long long pos_msec = 0;
8754 gboolean ret = TRUE;
8756 return_val_if_fail( player && position && player->pipeline && player->pipeline->mainbin,
8757 MM_ERROR_PLAYER_NOT_INITIALIZED );
8759 current_state = MMPLAYER_CURRENT_STATE(player);
8761 /* NOTE : query position except paused state to overcome some bad operation
8762 * please refer to below comments in details
8764 if ( current_state != MM_PLAYER_STATE_PAUSED )
8766 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
8769 /* NOTE : get last point to overcome some bad operation of some elements
8770 * ( returning zero when getting current position in paused state
8771 * and when failed to get postion during seeking
8773 if ( ( current_state == MM_PLAYER_STATE_PAUSED )
8775 //|| ( player->last_position != 0 && pos_msec == 0 ) )
8777 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
8779 if(player->playback_rate < 0.0)
8780 pos_msec = player->last_position - TRICKPLAY_OFFSET;
8782 pos_msec = player->last_position;
8785 pos_msec = player->last_position;
8787 player->last_position = pos_msec;
8789 debug_log("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
8794 if (player->duration > 0 && pos_msec > player->duration) {
8795 pos_msec = player->duration;
8798 if (player->sm.keep_last_pos) {
8799 debug_log("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position));
8800 pos_msec = player->last_position;
8803 player->last_position = pos_msec;
8808 case MM_PLAYER_POS_FORMAT_TIME:
8809 *position = GST_TIME_AS_MSECONDS(pos_msec);
8812 case MM_PLAYER_POS_FORMAT_PERCENT:
8817 dur = player->duration / GST_SECOND;
8820 debug_log ("duration is [%d], so returning position 0\n",dur);
8825 pos = pos_msec / GST_SECOND;
8826 *position = pos * 100 / dur;
8831 return MM_ERROR_PLAYER_INTERNAL;
8834 return MM_ERROR_NONE;
8838 static int __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
8840 #define STREAMING_IS_FINISHED 0
8841 #define BUFFERING_MAX_PER 100
8843 GstQuery *query = NULL;
8845 return_val_if_fail( player &&
8847 player->pipeline->mainbin,
8848 MM_ERROR_PLAYER_NOT_INITIALIZED );
8850 return_val_if_fail( start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT );
8852 if (!MMPLAYER_IS_HTTP_STREAMING ( player ))
8854 /* and rtsp is not ready yet. */
8855 debug_warning ( "it's only used for http streaming case.\n" );
8856 return MM_ERROR_NONE;
8864 case MM_PLAYER_POS_FORMAT_PERCENT :
8866 gint start_per = -1, stop_per = -1;
8867 gint64 buffered_total = 0;
8869 unsigned long position = 0;
8870 guint curr_size_bytes = 0;
8871 gint64 buffering_left = -1;
8872 gint buffered_sec = -1;
8874 gint64 content_duration = player->duration;
8875 guint64 content_size = player->http_content_size;
8877 if (content_duration > 0)
8879 if (!__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position))
8881 debug_log ("[Time] pos %d ms / dur %d sec / %lld bytes", position, (guint)(content_duration/GST_SECOND), content_size);
8882 start_per = 100 * (position*GST_MSECOND) / content_duration;
8884 /* buffered size info from multiqueue */
8885 if (player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst)
8887 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst), "curr-size-bytes", &curr_size_bytes, NULL);
8888 debug_log ("[MQ] curr_size_bytes = %d", curr_size_bytes);
8890 buffered_total += curr_size_bytes;
8893 /* buffered size info from queue2 */
8894 if (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
8896 query = gst_query_new_buffering ( GST_FORMAT_BYTES );
8897 if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query))
8899 GstBufferingMode mode;
8900 gint byte_in_rate = 0, byte_out_rate = 0;
8901 gint64 start_byte = 0, stop_byte = 0;
8902 guint num_of_ranges = 0;
8905 num_of_ranges = gst_query_get_n_buffering_ranges(query);
8906 for ( idx=0 ; idx<num_of_ranges ; idx++ )
8908 gst_query_parse_nth_buffering_range (query, idx, &start_byte, &stop_byte);
8909 debug_log ("[Q2][range %d] %lld ~ %lld\n", idx, start_byte, stop_byte);
8911 buffered_total += (stop_byte - start_byte);
8914 gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, &buffering_left);
8915 debug_log ("[Q2] in_rate %d, out_rate %d, left %lld\n", byte_in_rate, byte_out_rate, buffering_left);
8917 gst_query_unref (query);
8920 if (buffering_left == STREAMING_IS_FINISHED)
8922 stop_per = BUFFERING_MAX_PER;
8926 guint dur_sec = (guint)(content_duration/GST_SECOND);
8927 guint avg_byterate = (dur_sec>0)?((guint)(content_size/dur_sec)):(0);
8929 if (avg_byterate > 0)
8930 buffered_sec = (gint)(buffered_total/avg_byterate);
8931 else if (player->total_maximum_bitrate > 0)
8932 buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_maximum_bitrate);
8933 else if (player->total_bitrate > 0)
8934 buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_bitrate);
8936 if ((buffered_sec >= 0) && (dur_sec > 0))
8937 stop_per = start_per + (100 * buffered_sec / dur_sec);
8940 debug_log ("[Buffered Total] %lld bytes, %d sec, per %d~%d\n", buffered_total, buffered_sec, start_per, stop_per);
8944 if (((buffered_total == 0) || (start_per < 0) || (stop_per < 0)) &&
8945 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
8947 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
8948 if ( gst_element_query ( player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query ) )
8951 gint64 range_start_per = -1, range_stop_per = -1;
8953 gst_query_parse_buffering_range ( query, &format, &range_start_per, &range_stop_per, NULL );
8955 debug_log ("[Q2] range start %" G_GINT64_FORMAT " ~ stop %" G_GINT64_FORMAT "\n", range_start_per , range_stop_per);
8957 if (range_start_per != -1)
8958 start_per = (gint)(100 * range_start_per / GST_FORMAT_PERCENT_MAX);
8960 if (range_stop_per != -1)
8961 stop_per = (gint)(100 * range_stop_per / GST_FORMAT_PERCENT_MAX);
8963 gst_query_unref (query);
8967 *start_pos = (start_per < 100)?(start_per):(100);
8972 *stop_pos = (stop_per < 100)?(stop_per):(100);
8978 case MM_PLAYER_POS_FORMAT_TIME :
8979 debug_warning ( "Time format is not supported yet.\n" );
8986 debug_log("current buffer position : %lu~%lu \n", *start_pos, *stop_pos );
8988 return MM_ERROR_NONE;
8992 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param) // @
8998 debug_warning("set_message_callback is called with invalid player handle\n");
8999 return MM_ERROR_PLAYER_NOT_INITIALIZED;
9002 player->msg_cb = callback;
9003 player->msg_cb_param = user_param;
9005 debug_log("msg_cb : 0x%x msg_cb_param : 0x%x\n", (guint)callback, (guint)user_param);
9009 return MM_ERROR_NONE;
9012 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
9014 int ret = MM_ERROR_PLAYER_INVALID_URI;
9019 return_val_if_fail ( uri , FALSE);
9020 return_val_if_fail ( data , FALSE);
9021 return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
9023 memset(data, 0, sizeof(MMPlayerParseProfile));
9025 if ((path = strstr(uri, "file://")))
9027 int file_stat = MM_ERROR_NONE;
9029 file_stat = util_exist_file_path(path + 7);
9031 if (file_stat == MM_ERROR_NONE)
9033 strncpy(data->uri, path, MM_MAX_URL_LEN-1);
9035 if ( util_is_sdp_file ( path ) )
9037 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
9038 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9042 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
9044 ret = MM_ERROR_NONE;
9047 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
9049 data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
9054 debug_warning("could access %s.\n", path);
9058 else if ((path = strstr(uri, "es_buff://")))
9062 strcpy(data->uri, uri);
9063 data->uri_type = MM_PLAYER_URI_TYPE_ES_BUFF;
9064 ret = MM_ERROR_NONE;
9068 else if ((path = strstr(uri, "buff://")))
9070 data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
9071 ret = MM_ERROR_NONE;
9073 else if ((path = strstr(uri, "rtsp://")))
9076 if((path = strstr(uri, "/wfd1.0/"))) {
9077 strcpy(data->uri, uri);
9078 data->uri_type = MM_PLAYER_URI_TYPE_URL_WFD;
9079 ret = MM_ERROR_NONE;
9080 debug_log("uri is actually a wfd client path. giving it to wfdrtspsrc\n");
9083 strcpy(data->uri, uri);
9084 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9085 ret = MM_ERROR_NONE;
9089 else if ((path = strstr(uri, "http://")))
9092 strcpy(data->uri, uri);
9093 #ifdef MM_SMOOTH_STREAMING
9094 if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
9095 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
9097 data->uri_type = MM_PLAYER_URI_TYPE_SS;
9101 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
9103 ret = MM_ERROR_NONE;
9106 else if ((path = strstr(uri, "https://")))
9109 strcpy(data->uri, uri);
9110 #ifdef MM_SMOOTH_STREAMING
9111 if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
9112 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
9114 data->uri_type = MM_PLAYER_URI_TYPE_SS;
9117 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
9119 ret = MM_ERROR_NONE;
9122 else if ((path = strstr(uri, "rtspu://")))
9125 strcpy(data->uri, uri);
9126 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9127 ret = MM_ERROR_NONE;
9130 else if ((path = strstr(uri, "rtspr://")))
9132 strcpy(data->uri, path);
9133 char *separater =strstr(path, "*");
9137 char *urgent = separater + strlen("*");
9139 if ((urgent_len = strlen(urgent))) {
9140 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
9141 strcpy(data->urgent, urgent);
9142 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9143 ret = MM_ERROR_NONE;
9147 else if ((path = strstr(uri, "mms://")))
9150 strcpy(data->uri, uri);
9151 data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
9152 ret = MM_ERROR_NONE;
9155 else if ((path = strstr(uri, "mem://")))
9159 char *buffer = NULL;
9160 char *seperator = strchr(path, ',');
9161 char ext[100] = {0,}, size[100] = {0,};
9164 if ((buffer = strstr(path, "ext="))) {
9165 buffer += strlen("ext=");
9167 if (strlen(buffer)) {
9168 strcpy(ext, buffer);
9170 if ((seperator = strchr(ext, ','))
9171 || (seperator = strchr(ext, ' '))
9172 || (seperator = strchr(ext, '\0'))) {
9173 seperator[0] = '\0';
9178 if ((buffer = strstr(path, "size="))) {
9179 buffer += strlen("size=");
9181 if (strlen(buffer) > 0) {
9182 strcpy(size, buffer);
9184 if ((seperator = strchr(size, ','))
9185 || (seperator = strchr(size, ' '))
9186 || (seperator = strchr(size, '\0'))) {
9187 seperator[0] = '\0';
9190 mem_size = atoi(size);
9195 debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
9196 if ( mem_size && param)
9199 data->mem_size = mem_size;
9200 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
9201 ret = MM_ERROR_NONE;
9207 int file_stat = MM_ERROR_NONE;
9209 file_stat = util_exist_file_path(uri);
9211 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
9212 if (file_stat == MM_ERROR_NONE)
9214 g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", uri);
9216 if ( util_is_sdp_file( (char*)uri ) )
9218 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
9219 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9223 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
9225 ret = MM_ERROR_NONE;
9228 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
9230 data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
9235 debug_error ("invalid uri, could not play..\n");
9236 data->uri_type = MM_PLAYER_URI_TYPE_NONE;
9240 if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
9241 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
9242 } else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION){
9243 // ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
9246 /* dump parse result */
9247 secure_debug_warning("incomming uri : %s\n", uri);
9248 debug_log("uri_type : %d, play_mode : %d, mem : 0x%x, mem_size : %d, urgent : %s\n",
9249 data->uri_type, data->play_mode, (guint)data->mem, data->mem_size, data->urgent);
9256 gboolean _asm_postmsg(gpointer *data)
9258 mm_player_t* player = (mm_player_t*)data;
9259 MMMessageParamType msg = {0, };
9262 return_val_if_fail ( player, FALSE );
9263 debug_warning("get notified");
9265 if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
9266 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
9268 debug_warning("dispatched");
9273 msg.union_type = MM_MSG_UNION_CODE;
9274 msg.code = player->sm.event_src;
9276 #if 0 // should remove
9277 if (player->sm.event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
9279 /* fill the message with state of player */
9280 msg.state.current = MMPLAYER_CURRENT_STATE(player);
9281 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
9282 player->resumable_cancel_id = 0;
9287 MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
9288 player->resume_event_id = 0;
9291 debug_warning("dispatched");
9295 gboolean _asm_lazy_pause(gpointer *data)
9297 mm_player_t* player = (mm_player_t*)data;
9298 int ret = MM_ERROR_NONE;
9302 return_val_if_fail ( player, FALSE );
9304 if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
9306 debug_log ("Ready to proceed lazy pause\n");
9307 ret = _mmplayer_pause((MMHandleType)player);
9308 if(MM_ERROR_NONE != ret)
9310 debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
9315 debug_log ("Invalid state to proceed lazy pause\n");
9319 if (player->pipeline && player->pipeline->audiobin)
9320 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
9322 player->sm.by_asm_cb = FALSE; //should be reset here
9330 __mmplayer_can_do_interrupt(mm_player_t *player)
9332 if (!player || !player->pipeline || !player->attrs)
9334 debug_warning("not initialized");
9338 if ((player->sm.exit_cb) || (player->set_mode.pcm_extraction))
9340 debug_warning("leave from asm cb right now, %d, %d", player->sm.exit_cb, player->set_mode.pcm_extraction);
9344 /* check if seeking */
9345 if (player->doing_seek)
9347 MMMessageParamType msg_param;
9348 memset (&msg_param, 0, sizeof(MMMessageParamType));
9349 msg_param.code = MM_ERROR_PLAYER_SEEK;
9350 player->doing_seek = FALSE;
9351 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9355 /* check other thread */
9356 if (!g_mutex_trylock(&player->cmd_lock))
9358 debug_warning("locked already, cmd state : %d", player->cmd);
9360 /* check application command */
9361 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)
9363 debug_warning("playing.. should wait cmd lock then, will be interrupted");
9364 g_mutex_lock(&player->cmd_lock);
9367 debug_warning("nothing to do");
9372 debug_warning("can interrupt immediately");
9384 __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
9386 mm_player_t* player = (mm_player_t*) cb_data;
9387 ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
9388 int result = MM_ERROR_NONE;
9389 gboolean lazy_pause = FALSE;
9391 debug_warning("get notified");
9393 if (!__mmplayer_can_do_interrupt(player))
9395 debug_warning("no need to interrupt, so leave");
9399 player->sm.cb_pending = TRUE;
9400 debug_warning("asm event src type : %d, command : 0x%x", event_src, command);
9402 player->sm.by_asm_cb = TRUE;
9403 player->sm.event_src = event_src;
9405 /* first, check event source */
9406 if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG)
9408 int stop_by_asm = 0;
9409 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
9413 else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
9415 /* can use video overlay simultaneously */
9416 /* video resource conflict */
9417 if(player->pipeline->videobin)
9419 debug_log("video conflict but, can support multiple video");
9420 result = _mmplayer_pause((MMHandleType)player);
9421 cb_res = ASM_CB_RES_PAUSE;
9423 else if (player->pipeline->audiobin)
9425 debug_log("audio resource conflict");
9426 result = _mmplayer_pause((MMHandleType)player);
9427 if (result != MM_ERROR_NONE)
9429 debug_warning("fail to set pause by asm");
9431 cb_res = ASM_CB_RES_PAUSE;
9435 #if 0 // should remove
9436 else if (event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
9438 debug_warning("Got msg from asm for resumable canceled.\n");
9439 player->sm.antishock = TRUE;
9440 player->sm.by_asm_cb = FALSE;
9442 player->resumable_cancel_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
9443 cb_res = ASM_CB_RES_IGNORE;
9447 /* then, check command */
9450 case ASM_COMMAND_PLAY:
9451 debug_warning ("Got unexpected asm command (%d)", command);
9454 case ASM_COMMAND_STOP: // notification case
9456 debug_warning("Got msg from asm to stop");
9458 if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &player->last_position)) {
9459 debug_error("failed to get position");
9460 player->last_position = 0;
9463 debug_log ("pos_msec = %"GST_TIME_FORMAT"", GST_TIME_ARGS(player->last_position));
9465 result = _mmplayer_stop((MMHandleType)player);
9466 if (result != MM_ERROR_NONE)
9468 debug_warning("fail to set stop state by asm");
9469 cb_res = ASM_CB_RES_IGNORE;
9473 cb_res = ASM_CB_RES_STOP;
9475 player->sm.by_asm_cb = FALSE; // reset because no message any more from asm
9476 player->sm.keep_last_pos = TRUE;
9480 case ASM_COMMAND_PAUSE:
9482 debug_warning("Got msg from asm to Pause");
9483 if(event_src == ASM_EVENT_SOURCE_CALL_START ||
9484 event_src == ASM_EVENT_SOURCE_ALARM_START ||
9485 event_src == ASM_EVENT_SOURCE_MEDIA)
9487 if ( ! MMPLAYER_IS_RTSP_STREAMING(player) ) {
9488 //hold 0.7 second to excute "fadedown mute" effect
9489 debug_warning ("do fade down->pause->undo fade down");
9491 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
9493 result = _mmplayer_pause((MMHandleType)player);
9494 if (result != MM_ERROR_NONE)
9496 debug_warning("fail to set Pause state by asm");
9497 cb_res = ASM_CB_RES_IGNORE;
9500 __mmplayer_undo_sound_fadedown(player);
9502 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
9503 _mmplayer_unrealize((MMHandleType)player);
9506 #ifdef USE_LAZY_PAUSE // if enabled, should consider event id and context when removed
9507 else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
9509 lazy_pause = TRUE; // return as soon as possible, for fast start of other app
9511 if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
9512 g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
9514 player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
9515 debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
9520 debug_warning ("pause immediately");
9521 result = _mmplayer_pause((MMHandleType)player);
9523 cb_res = ASM_CB_RES_PAUSE;
9527 case ASM_COMMAND_RESUME:
9529 debug_warning("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
9530 player->sm.antishock = TRUE;
9531 player->sm.by_asm_cb = FALSE;
9533 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
9534 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
9535 cb_res = ASM_CB_RES_IGNORE;
9547 player->sm.by_asm_cb = FALSE;
9549 player->sm.cb_pending = FALSE;
9550 MMPLAYER_CMD_UNLOCK( player );
9553 debug_warning("dispatched");
9558 _mmplayer_create_player(MMHandleType handle) // @
9560 mm_player_t* player = MM_PLAYER_CAST(handle);
9564 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9566 /* initialize player state */
9567 MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
9568 MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
9569 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
9570 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
9572 /* check current state */
9573 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
9575 /* construct attributes */
9576 player->attrs = _mmplayer_construct_attribute(handle);
9578 if ( !player->attrs )
9580 debug_error("Failed to construct attributes\n");
9584 /* initialize gstreamer with configured parameter */
9585 if ( ! __mmplayer_init_gstreamer(player) )
9587 debug_error("Initializing gstreamer failed\n");
9591 /* initialize factories if not using decodebin */
9592 if( player->factories == NULL )
9593 __mmplayer_init_factories(player);
9595 /* create lock. note that g_tread_init() has already called in gst_init() */
9596 g_mutex_init(&player->fsink_lock);
9598 /* create repeat mutex */
9599 g_mutex_init(&player->repeat_thread_mutex);
9601 /* create repeat cond */
9602 g_cond_init(&player->repeat_thread_cond);
9604 /* create repeat thread */
9605 player->repeat_thread =
9606 g_thread_try_new ("repeat_thread", __mmplayer_repeat_thread, (gpointer)player, NULL);
9609 /* create next play mutex */
9610 g_mutex_init(&player->next_play_thread_mutex);
9612 /* create next play cond */
9613 g_cond_init(&player->next_play_thread_cond);
9615 /* create next play thread */
9616 player->next_play_thread =
9617 g_thread_try_new ("next_play_thread", __mmplayer_next_play_thread, (gpointer)player, NULL);
9618 if ( ! player->next_play_thread )
9620 debug_error("failed to create next play thread");
9624 if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
9626 debug_error("failed to initialize video capture\n");
9630 /* register to asm */
9631 if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
9633 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
9634 debug_error("failed to register asm server\n");
9635 return MM_ERROR_POLICY_INTERNAL;
9638 /* to add active device callback */
9639 if ( MM_ERROR_NONE != mm_sound_add_device_information_changed_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, __mmplayer_sound_device_info_changed_cb_func, (void*)player))
9641 debug_error("failed mm_sound_add_device_information_changed_callback \n");
9645 if (MMPLAYER_IS_HTTP_PD(player))
9647 player->pd_downloader = NULL;
9648 player->pd_file_save_path = NULL;
9651 player->streaming_type = STREAMING_SERVICE_NONE;
9653 /* give default value of audio effect setting */
9654 player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
9655 player->playback_rate = DEFAULT_PLAYBACK_RATE;
9657 player->play_subtitle = FALSE;
9658 player->use_textoverlay = FALSE;
9659 player->play_count = 0;
9660 player->use_decodebin = TRUE;
9661 player->ignore_asyncdone = FALSE;
9662 player->use_deinterleave = FALSE;
9663 player->pp_rebuilding = FALSE;
9664 player->max_audio_channels = 0;
9665 player->video_share_api_delta = 0;
9666 player->video_share_clock_delta = 0;
9667 player->has_closed_caption = FALSE;
9669 __mmplayer_post_proc_reset(player);
9671 if (player->ini.dump_element_keyword[0][0] == '\0')
9673 player->ini.set_dump_element_flag= FALSE;
9677 player->ini.set_dump_element_flag = TRUE;
9680 /* set player state to null */
9681 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
9682 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
9684 return MM_ERROR_NONE;
9688 g_mutex_clear(&player->fsink_lock );
9691 if ( player->repeat_thread )
9693 player->repeat_thread_exit = TRUE;
9694 g_cond_signal( &player->repeat_thread_cond );
9696 g_thread_join( player->repeat_thread );
9697 player->repeat_thread = NULL;
9699 g_mutex_clear(&player->repeat_thread_mutex );
9701 g_cond_clear (&player->repeat_thread_cond );
9703 /* clear repeat thread mutex/cond if still alive
9704 * this can happen if only thread creating has failed
9706 g_mutex_clear(&player->repeat_thread_mutex );
9707 g_cond_clear ( &player->repeat_thread_cond );
9709 /* free next play thread */
9710 if ( player->next_play_thread )
9712 player->next_play_thread_exit = TRUE;
9713 g_cond_signal( &player->next_play_thread_cond );
9715 g_thread_join( player->next_play_thread );
9716 player->next_play_thread = NULL;
9718 g_mutex_clear(&player->next_play_thread_mutex );
9720 g_cond_clear ( &player->next_play_thread_cond );
9722 /* clear next play thread mutex/cond if still alive
9723 * this can happen if only thread creating has failed
9725 g_mutex_clear(&player->next_play_thread_mutex );
9727 g_cond_clear ( &player->next_play_thread_cond );
9729 /* release attributes */
9730 _mmplayer_deconstruct_attribute(handle);
9734 return MM_ERROR_PLAYER_INTERNAL;
9738 __mmplayer_init_gstreamer(mm_player_t* player) // @
9740 static gboolean initialized = FALSE;
9741 static const int max_argc = 50;
9743 gchar** argv = NULL;
9744 gchar** argv2 = NULL;
9751 debug_log("gstreamer already initialized.\n");
9756 argc = malloc( sizeof(int) );
9757 argv = malloc( sizeof(gchar*) * max_argc );
9758 argv2 = malloc( sizeof(gchar*) * max_argc );
9760 if ( !argc || !argv )
9763 memset( argv, 0, sizeof(gchar*) * max_argc );
9764 memset( argv2, 0, sizeof(gchar*) * max_argc );
9768 argv[0] = g_strdup( "mmplayer" );
9771 for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
9773 if ( strlen( player->ini.gst_param[i] ) > 0 )
9775 argv[*argc] = g_strdup( player->ini.gst_param[i] );
9780 /* we would not do fork for scanning plugins */
9781 argv[*argc] = g_strdup("--gst-disable-registry-fork");
9784 /* check disable registry scan */
9785 if ( player->ini.skip_rescan )
9787 argv[*argc] = g_strdup("--gst-disable-registry-update");
9791 /* check disable segtrap */
9792 if ( player->ini.disable_segtrap )
9794 argv[*argc] = g_strdup("--gst-disable-segtrap");
9798 debug_log("initializing gstreamer with following parameter\n");
9799 debug_log("argc : %d\n", *argc);
9802 for ( i = 0; i < arg_count; i++ )
9805 debug_log("argv[%d] : %s\n", i, argv2[i]);
9809 /* initializing gstreamer */
9810 if ( ! gst_init_check (argc, &argv, &err))
9812 debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
9821 for ( i = 0; i < arg_count; i++ )
9823 //debug_log("release - argv[%d] : %s\n", i, argv2[i]);
9824 MMPLAYER_FREEIF( argv2[i] );
9827 MMPLAYER_FREEIF( argv );
9828 MMPLAYER_FREEIF( argv2 );
9829 MMPLAYER_FREEIF( argc );
9839 for ( i = 0; i < arg_count; i++ )
9841 debug_log("free[%d] : %s\n", i, argv2[i]);
9842 MMPLAYER_FREEIF( argv2[i] );
9845 MMPLAYER_FREEIF( argv );
9846 MMPLAYER_FREEIF( argv2 );
9847 MMPLAYER_FREEIF( argc );
9853 __mmplayer_destroy_streaming_ext(mm_player_t* player)
9855 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9857 if (player->pd_downloader)
9859 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
9860 MMPLAYER_FREEIF(player->pd_downloader);
9863 if (MMPLAYER_IS_HTTP_PD(player))
9865 _mmplayer_destroy_pd_downloader((MMHandleType)player);
9866 MMPLAYER_FREEIF(player->pd_file_save_path);
9869 return MM_ERROR_NONE;
9873 _mmplayer_destroy(MMHandleType handle) // @
9875 mm_player_t* player = MM_PLAYER_CAST(handle);
9879 /* check player handle */
9880 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9882 /* destroy can called at anytime */
9883 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
9885 __mmplayer_destroy_streaming_ext(player);
9887 /* release repeat thread */
9888 if ( player->repeat_thread )
9890 player->repeat_thread_exit = TRUE;
9891 g_cond_signal( &player->repeat_thread_cond );
9893 debug_log("waitting for repeat thread exit\n");
9894 g_thread_join ( player->repeat_thread );
9895 g_mutex_clear(&player->repeat_thread_mutex );
9896 g_cond_clear (&player->repeat_thread_cond );
9897 debug_log("repeat thread released\n");
9900 /* release next play thread */
9901 if ( player->next_play_thread )
9903 player->next_play_thread_exit = TRUE;
9904 g_cond_signal( &player->next_play_thread_cond );
9906 debug_log("waitting for next play thread exit\n");
9907 g_thread_join ( player->next_play_thread );
9908 g_mutex_clear(&player->next_play_thread_mutex );
9909 g_cond_clear(&player->next_play_thread_cond );
9910 debug_log("next play thread released\n");
9913 _mmplayer_release_video_capture(player);
9915 /* flush any pending asm_cb */
9916 if (player->sm.cb_pending)
9918 /* set a flag for make sure asm_cb to be returned immediately */
9919 debug_warning("asm cb has pending state");
9920 player->sm.exit_cb = TRUE;
9922 /* make sure to release any pending asm_cb which locked by cmd_lock */
9923 MMPLAYER_CMD_UNLOCK(player);
9925 MMPLAYER_CMD_LOCK(player);
9929 if ( MM_ERROR_NONE != _mmplayer_asm_unregister(&player->sm) )
9931 debug_error("failed to deregister asm server\n");
9934 #ifdef USE_LAZY_PAUSE
9935 if (player->lazy_pause_event_id)
9937 __mmplayer_remove_g_source_from_context(player->context.global_default, player->lazy_pause_event_id);
9938 player->lazy_pause_event_id = 0;
9942 if (player->resume_event_id)
9944 g_source_remove (player->resume_event_id);
9945 player->resume_event_id = 0;
9948 if (player->resumable_cancel_id)
9950 g_source_remove (player->resumable_cancel_id);
9951 player->resumable_cancel_id = 0;
9954 /* release pipeline */
9955 if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
9957 debug_error("failed to destory pipeline\n");
9958 return MM_ERROR_PLAYER_INTERNAL;
9961 if (player->is_external_subtitle_present && player->subtitle_language_list)
9963 g_list_free (player->subtitle_language_list);
9964 player->subtitle_language_list = NULL;
9967 __mmplayer_release_dump_list (player->dump_list);
9969 /* release miscellaneous information.
9970 these info needs to be released after pipeline is destroyed. */
9971 __mmplayer_release_misc_post( player );
9973 /* release attributes */
9974 _mmplayer_deconstruct_attribute( handle );
9976 /* release factories */
9977 __mmplayer_release_factories( player );
9980 g_mutex_clear(&player->fsink_lock );
9982 g_mutex_clear(&player->msg_cb_lock );
9986 return MM_ERROR_NONE;
9990 __mmplayer_realize_streaming_ext(mm_player_t* player)
9992 int ret = MM_ERROR_NONE;
9995 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9997 if (MMPLAYER_IS_HTTP_PD(player))
9999 gboolean bret = FALSE;
10001 player->pd_downloader = _mmplayer_create_pd_downloader();
10002 if ( !player->pd_downloader )
10004 debug_error ("Unable to create PD Downloader...");
10005 ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
10008 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
10012 debug_error ("Unable to create PD Downloader...");
10013 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
10022 _mmplayer_realize(MMHandleType hplayer) // @
10024 mm_player_t* player = (mm_player_t*)hplayer;
10026 void *param = NULL;
10027 int application_pid = -1;
10028 gboolean update_registry = FALSE;
10029 MMHandleType attrs = 0;
10030 int ret = MM_ERROR_NONE;
10034 /* check player handle */
10035 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
10037 /* check current state */
10038 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
10040 attrs = MMPLAYER_GET_ATTRS(player);
10043 debug_error("fail to get attributes.\n");
10044 return MM_ERROR_PLAYER_INTERNAL;
10047 mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
10048 player->sm.pid = application_pid;
10050 mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
10051 mm_attrs_get_data_by_name(attrs, "profile_user_param", ¶m);
10053 ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
10055 if (ret != MM_ERROR_NONE)
10057 debug_error("failed to parse profile\n");
10061 /* FIXIT : we can use thouse in player->profile directly */
10062 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
10064 player->mem_buf.buf = (char *)player->profile.mem;
10065 player->mem_buf.len = player->profile.mem_size;
10066 player->mem_buf.offset = 0;
10069 #ifdef TEST_ES // es_player_push_mode is needed?
10070 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF)
10072 if (strstr(uri, "es_buff://push_mode"))
10074 player->es_player_push_mode = TRUE;
10078 player->es_player_push_mode = FALSE;
10082 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
10084 debug_warning("mms protocol is not supported format.\n");
10085 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
10088 if (MMPLAYER_IS_STREAMING(player))
10089 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
10091 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
10093 player->needed_v_parser = FALSE;
10094 player->smooth_streaming = FALSE;
10095 player->videodec_linked = 0;
10096 player->videosink_linked = 0;
10097 player->audiodec_linked = 0;
10098 player->audiosink_linked = 0;
10099 player->textsink_linked = 0;
10100 player->is_external_subtitle_present = FALSE;
10101 /* set the subtitle ON default */
10102 player->is_subtitle_off = FALSE;
10104 /* registry should be updated for downloadable codec */
10105 mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
10107 if ( update_registry )
10109 debug_log("updating registry...\n");
10110 gst_update_registry();
10112 /* then we have to rebuild factories */
10113 __mmplayer_release_factories( player );
10114 __mmplayer_init_factories(player);
10117 /* realize pipeline */
10118 ret = __gst_realize( player );
10119 if ( ret != MM_ERROR_NONE )
10121 debug_error("fail to realize the player.\n");
10125 ret = __mmplayer_realize_streaming_ext(player);
10134 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
10137 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10139 /* destroy can called at anytime */
10140 if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
10142 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
10143 MMPLAYER_FREEIF(player->pd_downloader);
10147 return MM_ERROR_NONE;
10151 _mmplayer_unrealize(MMHandleType hplayer)
10153 mm_player_t* player = (mm_player_t*)hplayer;
10154 int ret = MM_ERROR_NONE;
10158 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
10160 /* check current state */
10161 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
10163 __mmplayer_unrealize_streaming_ext(player);
10165 /* unrealize pipeline */
10166 ret = __gst_unrealize( player );
10168 /* set asm stop if success */
10169 if (MM_ERROR_NONE == ret)
10171 if (player->sm.state != ASM_STATE_STOP)
10173 /* NOTE : Stop asm after pipeline unrealize. Keep this sequence. */
10174 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP, FALSE);
10177 debug_error("failed to set asm state to STOP");
10184 debug_error("failed and don't change asm state to stop");
10193 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
10195 mm_player_t* player = (mm_player_t*)hplayer;
10197 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10199 return __gst_set_message_callback(player, callback, user_param);
10203 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
10205 mm_player_t *player = (mm_player_t*)hplayer;
10207 return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
10209 *state = MMPLAYER_CURRENT_STATE(player);
10211 return MM_ERROR_NONE;
10216 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
10218 mm_player_t* player = (mm_player_t*) hplayer;
10219 GstElement* vol_element = NULL;
10224 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10226 debug_log("volume [L]=%f:[R]=%f\n",
10227 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
10229 /* invalid factor range or not */
10230 for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
10232 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
10233 debug_error("Invalid factor! (valid factor:0~1.0)\n");
10234 return MM_ERROR_INVALID_ARGUMENT;
10238 /* not support to set other value into each channel */
10239 if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
10240 return MM_ERROR_INVALID_ARGUMENT;
10242 /* Save volume to handle. Currently the first array element will be saved. */
10243 player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
10245 /* check pipeline handle */
10246 if ( ! player->pipeline || ! player->pipeline->audiobin )
10248 debug_log("audiobin is not created yet\n");
10249 debug_log("but, current stored volume will be set when it's created.\n");
10251 /* NOTE : stored volume will be used in create_audiobin
10252 * returning MM_ERROR_NONE here makes application to able to
10253 * set volume at anytime.
10255 return MM_ERROR_NONE;
10258 /* setting volume to volume element */
10259 vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
10263 debug_log("volume is set [%f]\n", player->sound.volume);
10264 g_object_set(vol_element, "volume", player->sound.volume, NULL);
10269 return MM_ERROR_NONE;
10274 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
10276 mm_player_t* player = (mm_player_t*) hplayer;
10281 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10282 return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
10284 /* returning stored volume */
10285 for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
10286 volume->level[i] = player->sound.volume;
10290 return MM_ERROR_NONE;
10296 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
10298 mm_player_t* player = (mm_player_t*) hplayer;
10299 GstElement* vol_element = NULL;
10303 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10305 /* mute value shoud 0 or 1 */
10306 if ( mute != 0 && mute != 1 )
10308 debug_error("bad mute value\n");
10310 /* FIXIT : definitly, we need _BAD_PARAM error code */
10311 return MM_ERROR_INVALID_ARGUMENT;
10314 player->sound.mute = mute;
10316 /* just hold mute value if pipeline is not ready */
10317 if ( !player->pipeline || !player->pipeline->audiobin )
10319 debug_log("pipeline is not ready. holding mute value\n");
10320 return MM_ERROR_NONE;
10323 vol_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
10325 /* NOTE : volume will only created when the bt is enabled */
10328 debug_log("mute : %d\n", mute);
10329 g_object_set(vol_element, "mute", mute, NULL);
10333 debug_log("volume elemnet is not created. using volume in audiosink\n");
10338 return MM_ERROR_NONE;
10342 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
10344 mm_player_t* player = (mm_player_t*) hplayer;
10348 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10349 return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
10351 /* just hold mute value if pipeline is not ready */
10352 if ( !player->pipeline || !player->pipeline->audiobin )
10354 debug_log("pipeline is not ready. returning stored value\n");
10355 *pmute = player->sound.mute;
10356 return MM_ERROR_NONE;
10359 *pmute = player->sound.mute;
10363 return MM_ERROR_NONE;
10367 _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
10369 mm_player_t* player = (mm_player_t*) hplayer;
10373 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10375 player->video_stream_changed_cb = callback;
10376 player->video_stream_changed_cb_user_param = user_param;
10377 debug_log("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
10381 return MM_ERROR_NONE;
10385 _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
10387 mm_player_t* player = (mm_player_t*) hplayer;
10391 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10393 player->audio_stream_changed_cb = callback;
10394 player->audio_stream_changed_cb_user_param = user_param;
10395 debug_log("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
10399 return MM_ERROR_NONE;
10403 _mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param) // @
10405 mm_player_t* player = (mm_player_t*) hplayer;
10409 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10411 player->audio_stream_render_cb_ex = callback;
10412 player->audio_stream_cb_user_param = user_param;
10413 player->audio_stream_sink_sync = sync;
10414 debug_log("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);
10418 return MM_ERROR_NONE;
10422 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
10424 mm_player_t* player = (mm_player_t*) hplayer;
10428 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10430 player->video_stream_cb = callback;
10431 player->video_stream_cb_user_param = user_param;
10432 player->use_video_stream = TRUE;
10433 debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
10437 return MM_ERROR_NONE;
10441 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
10443 mm_player_t* player = (mm_player_t*) hplayer;
10447 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10449 player->audio_stream_cb = callback;
10450 player->audio_stream_cb_user_param = user_param;
10451 debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
10455 return MM_ERROR_NONE;
10458 // set prepare size
10460 _mmplayer_set_prepare_buffering_time(MMHandleType hplayer, int second)
10462 mm_player_t* player = (mm_player_t*) hplayer;
10466 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10468 if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL)
10469 return MM_ERROR_PLAYER_INVALID_STATE;
10471 debug_log("pre buffer size : %d sec\n", second);
10475 debug_error("bad size value\n");
10476 return MM_ERROR_INVALID_ARGUMENT;
10479 if (player->streamer == NULL)
10481 player->streamer = __mm_player_streaming_create();
10482 __mm_player_streaming_initialize(player->streamer);
10485 player->streamer->buffering_req.initial_second = second;
10489 return MM_ERROR_NONE;
10492 // set runtime mode
10494 _mmplayer_set_runtime_buffering_mode(MMHandleType hplayer, MMPlayerBufferingMode mode, int second)
10496 mm_player_t* player = (mm_player_t*) hplayer;
10500 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10502 debug_log("mode %d\n", mode);
10504 if ((mode < 0) || (mode > MM_PLAYER_BUFFERING_MODE_MAX) ||
10505 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) && (second <= 0)))
10506 return MM_ERROR_INVALID_ARGUMENT;
10508 if (player->streamer == NULL)
10510 player->streamer = __mm_player_streaming_create();
10511 __mm_player_streaming_initialize(player->streamer);
10514 player->streamer->buffering_req.mode = mode;
10516 if ((second > 0) &&
10517 ((mode == MM_PLAYER_BUFFERING_MODE_FIXED) ||
10518 (mode == MM_PLAYER_BUFFERING_MODE_ADAPTIVE)))
10519 player->streamer->buffering_req.runtime_second = second;
10523 return MM_ERROR_NONE;
10527 _mmplayer_set_videoframe_render_error_cb(MMHandleType hplayer, mm_player_video_frame_render_error_callback callback, void *user_param) // @
10529 mm_player_t* player = (mm_player_t*) hplayer;
10533 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10534 return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
10536 player->video_frame_render_error_cb = callback;
10537 player->video_frame_render_error_cb_user_param = user_param;
10539 debug_log("Video frame render error cb Handle value is %p : %p\n", player, player->video_frame_render_error_cb);
10543 return MM_ERROR_NONE;
10547 __mmplayer_start_streaming_ext(mm_player_t *player)
10549 gint ret = MM_ERROR_NONE;
10552 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10554 if (MMPLAYER_IS_HTTP_PD(player))
10556 if ( !player->pd_downloader )
10558 ret = __mmplayer_realize_streaming_ext(player);
10560 if ( ret != MM_ERROR_NONE)
10562 debug_error ("failed to realize streaming ext\n");
10567 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
10569 ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
10572 debug_error ("ERROR while starting PD...\n");
10573 return MM_ERROR_PLAYER_NOT_INITIALIZED;
10575 ret = MM_ERROR_NONE;
10584 _mmplayer_start(MMHandleType hplayer) // @
10586 mm_player_t* player = (mm_player_t*) hplayer;
10587 gint ret = MM_ERROR_NONE;
10591 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10593 /* check current state */
10594 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
10596 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
10597 if ( ret != MM_ERROR_NONE )
10599 debug_error("failed to set asm state to PLAYING\n");
10603 /* NOTE : we should check and create pipeline again if not created as we destroy
10604 * whole pipeline when stopping in streamming playback
10606 if ( ! player->pipeline )
10608 ret = __gst_realize( player );
10609 if ( MM_ERROR_NONE != ret )
10611 debug_error("failed to realize before starting. only in streamming\n");
10617 ret = __mmplayer_start_streaming_ext(player);
10618 if ( ret != MM_ERROR_NONE )
10620 debug_error("failed to start streaming ext \n");
10623 /* start pipeline */
10624 ret = __gst_start( player );
10625 if ( ret != MM_ERROR_NONE )
10627 debug_error("failed to start player.\n");
10635 /* NOTE: post "not supported codec message" to application
10636 * when one codec is not found during AUTOPLUGGING in MSL.
10637 * So, it's separated with error of __mmplayer_gst_callback().
10638 * And, if any codec is not found, don't send message here.
10639 * Because GST_ERROR_MESSAGE is posted by other plugin internally.
10642 __mmplayer_handle_missed_plugin(mm_player_t* player)
10644 MMMessageParamType msg_param;
10645 memset (&msg_param, 0, sizeof(MMMessageParamType));
10646 gboolean post_msg_direct = FALSE;
10650 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10652 debug_log("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
10653 player->not_supported_codec, player->can_support_codec);
10655 if( player->not_found_demuxer )
10657 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
10658 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
10660 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10661 MMPLAYER_FREEIF(msg_param.data);
10663 return MM_ERROR_NONE;
10666 if (player->not_supported_codec)
10668 if ( player->can_support_codec ) // There is one codec to play
10670 post_msg_direct = TRUE;
10674 if ( player->pipeline->audiobin ) // Some content has only PCM data in container.
10675 post_msg_direct = TRUE;
10678 if ( post_msg_direct )
10680 MMMessageParamType msg_param;
10681 memset (&msg_param, 0, sizeof(MMMessageParamType));
10683 if ( player->not_supported_codec == MISSING_PLUGIN_AUDIO )
10685 debug_warning("not found AUDIO codec, posting error code to application.\n");
10687 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
10688 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
10690 else if ( player->not_supported_codec == MISSING_PLUGIN_VIDEO )
10692 debug_warning("not found VIDEO codec, posting error code to application.\n");
10694 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
10695 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
10698 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10700 MMPLAYER_FREEIF(msg_param.data);
10702 return MM_ERROR_NONE;
10704 else // no any supported codec case
10706 debug_warning("not found any codec, posting error code to application.\n");
10708 if ( player->not_supported_codec == MISSING_PLUGIN_AUDIO )
10710 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
10711 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
10715 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
10716 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
10719 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10721 MMPLAYER_FREEIF(msg_param.data);
10727 return MM_ERROR_NONE;
10730 static void __mmplayer_check_pipeline(mm_player_t* player)
10732 GstState element_state = GST_STATE_VOID_PENDING;
10733 GstState element_pending_state = GST_STATE_VOID_PENDING;
10735 int ret = MM_ERROR_NONE;
10737 if (player->pp_rebuilding)
10739 debug_warning("pipeline is under construction.\n");
10741 MMPLAYER_PLAYBACK_LOCK(player);
10742 MMPLAYER_PLAYBACK_UNLOCK(player);
10744 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
10746 /* wait for state transition */
10747 ret = gst_element_get_state( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND );
10749 if ( ret == GST_STATE_CHANGE_FAILURE )
10751 debug_error("failed to change pipeline state within %d sec\n", timeout );
10756 /* NOTE : it should be able to call 'stop' anytime*/
10758 _mmplayer_stop(MMHandleType hplayer) // @
10760 mm_player_t* player = (mm_player_t*)hplayer;
10761 int ret = MM_ERROR_NONE;
10765 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10767 /* check current state */
10768 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
10770 /* check pipline building state */
10771 __mmplayer_check_pipeline(player);
10773 /* NOTE : application should not wait for EOS after calling STOP */
10774 __mmplayer_cancel_eos_timer( player );
10776 __mmplayer_unrealize_streaming_ext(player);
10779 player->doing_seek = FALSE;
10781 /* stop pipeline */
10782 ret = __gst_stop( player );
10784 if ( ret != MM_ERROR_NONE )
10786 debug_error("failed to stop player.\n");
10795 _mmplayer_pause(MMHandleType hplayer) // @
10797 mm_player_t* player = (mm_player_t*)hplayer;
10798 gint64 pos_msec = 0;
10799 gboolean async = FALSE;
10800 gint ret = MM_ERROR_NONE;
10804 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10806 /* check current state */
10807 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
10809 /* check pipline building state */
10810 __mmplayer_check_pipeline(player);
10812 switch (MMPLAYER_CURRENT_STATE(player))
10814 case MM_PLAYER_STATE_READY:
10816 /* check prepare async or not.
10817 * In the case of streaming playback, it's recommned to avoid blocking wait.
10819 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10820 debug_log("prepare working mode : %s", (async ? "async" : "sync"));
10824 case MM_PLAYER_STATE_PLAYING:
10826 /* NOTE : store current point to overcome some bad operation
10827 * ( returning zero when getting current position in paused state) of some
10830 if ( !gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec))
10831 debug_warning("getting current position failed in paused\n");
10833 player->last_position = pos_msec;
10838 /* pause pipeline */
10839 ret = __gst_pause( player, async );
10841 if ( ret != MM_ERROR_NONE )
10843 debug_error("failed to pause player. ret : 0x%x\n", ret);
10852 _mmplayer_resume(MMHandleType hplayer)
10854 mm_player_t* player = (mm_player_t*)hplayer;
10855 int ret = MM_ERROR_NONE;
10856 gboolean async = FALSE;
10860 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10862 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
10865 debug_error("failed to set asm state to PLAYING\n");
10869 /* check current state */
10870 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
10872 /* resume pipeline */
10875 if(MMPLAYER_IS_ES_BUFF_SRC(player))
10880 ret = __gst_resume( player, async );
10882 if ( ret != MM_ERROR_NONE )
10884 debug_error("failed to resume player.\n");
10893 __mmplayer_set_play_count(mm_player_t* player, gint count)
10895 MMHandleType attrs = 0;
10899 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10901 attrs = MMPLAYER_GET_ATTRS(player);
10904 debug_error("fail to get attributes.\n");
10905 return MM_ERROR_PLAYER_INTERNAL;
10908 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
10909 if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
10910 debug_error("failed to commit\n");
10914 return MM_ERROR_NONE;
10918 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
10920 mm_player_t* player = (mm_player_t*)hplayer;
10921 gint64 start_pos = 0;
10922 gint64 end_pos = 0;
10923 gint infinity = -1;
10927 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10928 return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
10930 player->section_repeat = TRUE;
10931 player->section_repeat_start = start;
10932 player->section_repeat_end = end;
10934 start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
10935 end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
10937 __mmplayer_set_play_count( player, infinity );
10939 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10940 player->playback_rate,
10942 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10943 GST_SEEK_TYPE_SET, start_pos,
10944 GST_SEEK_TYPE_SET, end_pos)))
10946 debug_error("failed to activate section repeat\n");
10948 return MM_ERROR_PLAYER_SEEK;
10951 debug_log("succeeded to set section repeat from %d to %d\n",
10952 player->section_repeat_start, player->section_repeat_end);
10956 return MM_ERROR_NONE;
10960 __mmplayer_set_pcm_extraction(mm_player_t* player)
10962 gint64 start_nsec = 0;
10963 gint64 end_nsec = 0;
10964 gint64 dur_nsec = 0;
10965 gint64 dur_msec = 0;
10966 int required_start = 0;
10967 int required_end = 0;
10972 return_val_if_fail( player, FALSE );
10974 mm_attrs_multiple_get(player->attrs,
10976 "pcm_extraction_start_msec", &required_start,
10977 "pcm_extraction_end_msec", &required_end,
10980 debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
10982 if (required_start == 0 && required_end == 0)
10984 debug_log("extracting entire stream");
10985 return MM_ERROR_NONE;
10987 else if (required_start < 0 || required_start > required_end || required_end < 0 )
10989 debug_log("invalid range for pcm extraction");
10990 return MM_ERROR_INVALID_ARGUMENT;
10994 ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
10997 debug_error("failed to get duration");
10998 return MM_ERROR_PLAYER_INTERNAL;
11000 dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
11002 if (dur_msec < required_end) // FIXME
11004 debug_log("invalid end pos for pcm extraction");
11005 return MM_ERROR_INVALID_ARGUMENT;
11008 start_nsec = required_start * G_GINT64_CONSTANT(1000000);
11009 end_nsec = required_end * G_GINT64_CONSTANT(1000000);
11011 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
11014 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
11015 GST_SEEK_TYPE_SET, start_nsec,
11016 GST_SEEK_TYPE_SET, end_nsec)))
11018 debug_error("failed to seek for pcm extraction\n");
11020 return MM_ERROR_PLAYER_SEEK;
11023 debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
11027 return MM_ERROR_NONE;
11031 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
11033 mm_player_t* player = (mm_player_t*)hplayer;
11034 gint64 cur_pos = 0;
11039 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11041 player->section_repeat = FALSE;
11043 __mmplayer_set_play_count( player, onetime );
11045 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_pos);
11047 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
11050 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
11051 GST_SEEK_TYPE_SET, cur_pos,
11052 GST_SEEK_TYPE_SET, player->duration )))
11054 debug_error("failed to deactivate section repeat\n");
11056 return MM_ERROR_PLAYER_SEEK;
11061 return MM_ERROR_NONE;
11065 _mmplayer_set_playspeed(MMHandleType hplayer, float rate)
11067 mm_player_t* player = (mm_player_t*)hplayer;
11068 signed long long pos_msec = 0;
11069 int ret = MM_ERROR_NONE;
11071 signed long long start = 0, stop = 0;
11072 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
11075 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
11076 return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
11078 /* The sound of video is not supported under 0.0 and over 2.0. */
11079 if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
11081 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
11084 _mmplayer_set_mute(hplayer, mute);
11086 if (player->playback_rate == rate)
11087 return MM_ERROR_NONE;
11089 /* If the position is reached at start potion during fast backward, EOS is posted.
11090 * So, This EOS have to be classified with it which is posted at reaching the end of stream.
11092 player->playback_rate = rate;
11094 current_state = MMPLAYER_CURRENT_STATE(player);
11096 if ( current_state != MM_PLAYER_STATE_PAUSED )
11097 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
11099 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
11101 if ( ( current_state == MM_PLAYER_STATE_PAUSED )
11103 //|| ( player->last_position != 0 && pos_msec == 0 ) )
11105 debug_warning("returning last point : %lld\n", player->last_position );
11106 pos_msec = player->last_position;
11113 stop = GST_CLOCK_TIME_NONE;
11117 start = GST_CLOCK_TIME_NONE;
11120 if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
11123 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
11124 GST_SEEK_TYPE_SET, start,
11125 GST_SEEK_TYPE_SET, stop)))
11127 debug_error("failed to set speed playback\n");
11128 return MM_ERROR_PLAYER_SEEK;
11131 debug_log("succeeded to set speed playback as %0.1f\n", rate);
11135 return MM_ERROR_NONE;;
11139 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
11141 mm_player_t* player = (mm_player_t*)hplayer;
11142 int ret = MM_ERROR_NONE;
11146 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11148 ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
11156 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
11158 mm_player_t* player = (mm_player_t*)hplayer;
11159 int ret = MM_ERROR_NONE;
11161 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11163 ret = __gst_get_position ( player, format, position );
11169 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
11171 mm_player_t* player = (mm_player_t*)hplayer;
11172 int ret = MM_ERROR_NONE;
11174 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11176 ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
11182 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
11184 mm_player_t* player = (mm_player_t*)hplayer;
11185 int ret = MM_ERROR_NONE;
11189 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11191 ret = __gst_adjust_subtitle_position(player, format, position);
11198 _mmplayer_adjust_video_postion(MMHandleType hplayer, int offset) // @
11200 mm_player_t* player = (mm_player_t*)hplayer;
11201 int ret = MM_ERROR_NONE;
11205 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
11207 ret = __gst_adjust_video_position(player, offset);
11215 __mmplayer_is_midi_type( gchar* str_caps)
11217 if ( ( g_strrstr(str_caps, "audio/midi") ) ||
11218 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
11219 ( g_strrstr(str_caps, "application/x-smaf") ) ||
11220 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
11221 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
11222 ( g_strrstr(str_caps, "audio/xmf") ) ||
11223 ( g_strrstr(str_caps, "audio/mxmf") ) )
11225 debug_log("midi\n");
11234 __mmplayer_is_only_mp3_type (gchar *str_caps)
11236 if (g_strrstr(str_caps, "application/x-id3") ||
11237 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
11244 /* try to use ALP decoder first instead of selected decoder */
11246 __mmplayer_is_omx_decoder_type (mm_player_t* player)
11248 #define MIN_THRESHOLD_SIZE 320 * 1024 // 320K
11249 gboolean ret = FALSE;
11250 gchar* path = NULL;
11251 guint64 data_size = 0;
11254 return_val_if_fail (player, FALSE);
11256 /* consider mp3 audio only */
11257 if ((!MMPLAYER_IS_STREAMING(player)) &&
11258 (__mmplayer_is_only_mp3_type(player->type)))
11260 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
11262 if (stat(path, &sb) == 0)
11264 data_size = (guint64)sb.st_size;
11266 if (data_size > MIN_THRESHOLD_SIZE)
11273 debug_log ("need to select omx_decoder ? [%s]\n", (ret)?"YES":"NO");
11278 __mmplayer_set_audio_attrs (mm_player_t* player, GstCaps* caps)
11280 GstStructure* caps_structure = NULL;
11281 gint samplerate = 0;
11285 return_if_fail (player && caps);
11287 caps_structure = gst_caps_get_structure(caps, 0);
11289 /* set stream information */
11290 gst_structure_get_int (caps_structure, "rate", &samplerate);
11291 mm_attrs_set_int_by_name (player->attrs, "content_audio_samplerate", samplerate);
11293 gst_structure_get_int (caps_structure, "channels", &channels);
11294 mm_attrs_set_int_by_name (player->attrs, "content_audio_channels", channels);
11296 debug_log ("audio samplerate : %d channels : %d\n", samplerate, channels);
11300 __mmplayer_typefind_have_type( GstElement *tf, guint probability, // @
11301 GstCaps *caps, gpointer data)
11303 mm_player_t* player = (mm_player_t*)data;
11304 GstPad* pad = NULL;
11308 return_if_fail( player && tf && caps );
11310 /* store type string */
11311 MMPLAYER_FREEIF(player->type);
11312 player->type = gst_caps_to_string(caps);
11314 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
11316 if ( (!MMPLAYER_IS_WFD_STREAMING( player )) &&
11317 (!MMPLAYER_IS_RTSP_STREAMING( player )) &&
11318 (g_strrstr(player->type, "audio/x-raw-int")))
11320 debug_error("not support media format\n");
11322 if (player->msg_posted == FALSE)
11324 MMMessageParamType msg_param;
11325 memset (&msg_param, 0, sizeof(MMMessageParamType));
11327 msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
11328 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
11330 /* don't post more if one was sent already */
11331 player->msg_posted = TRUE;
11336 /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
11337 if ( __mmplayer_is_midi_type(player->type))
11339 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
11340 player->bypass_audio_effect = TRUE;
11342 else if ( g_strrstr(player->type, "application/x-hls"))
11344 /* If it can't know exact type when it parses uri because of redirection case,
11345 * it will be fixed by typefinder here.
11347 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
11349 else if ( g_strrstr(player->type, "application/dash+xml"))
11351 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
11354 pad = gst_element_get_static_pad(tf, "src");
11357 debug_error("fail to get typefind src pad.\n");
11361 if (player->use_decodebin)
11363 if(!__mmplayer_try_to_plug_decodebin( player, pad, caps ))
11365 gboolean async = FALSE;
11366 debug_error("failed to autoplug %s\n", player->type);
11368 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
11370 if ( async && player->msg_posted == FALSE )
11372 __mmplayer_handle_missed_plugin( player );
11381 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
11383 gboolean async = FALSE;
11384 debug_error("failed to autoplug %s\n", player->type);
11386 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
11388 if ( async && player->msg_posted == FALSE )
11390 __mmplayer_handle_missed_plugin( player );
11396 /* finish autopluging if no dynamic pad waiting */
11397 if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
11399 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
11401 __mmplayer_pipeline_complete( NULL, (gpointer)player );
11407 gst_object_unref( GST_OBJECT(pad) );
11414 #ifdef _MM_PLAYER_ALP_PARSER
11415 void check_name (void *data, void *user_data)
11417 mm_player_t* player = user_data;
11419 if (g_strrstr((gchar*)data, "mpegaudioparse"))
11421 debug_log("mpegaudioparse - set alp-mp3dec\n");
11422 g_object_set(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "alp-mp3dec", TRUE, NULL);
11427 static GstElement *
11428 __mmplayer_create_decodebin (mm_player_t* player)
11430 GstElement *decodebin = NULL;
11434 /* create decodebin */
11435 decodebin = gst_element_factory_make("decodebin", NULL);
11439 debug_error("fail to create decodebin\n");
11443 /* raw pad handling signal */
11444 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
11445 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
11447 /* no-more-pad pad handling signal */
11448 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
11449 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
11451 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
11452 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
11454 /* This signal is emitted when a pad for which there is no further possible
11455 decoding is added to the decodebin.*/
11456 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
11457 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player );
11459 /* This signal is emitted whenever decodebin2 finds a new stream. It is emitted
11460 before looking for any elements that can handle that stream.*/
11461 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
11462 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
11464 /* This signal is emitted whenever decodebin2 finds a new stream. It is emitted
11465 before looking for any elements that can handle that stream.*/
11466 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
11467 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
11469 /* Once decodebin2 has found the possible GstElementFactory objects to try for
11470 caps on pad, this signal is emited. The purpose of the signal is for the
11471 application to perform additional sorting or filtering on the element factory
11473 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
11474 G_CALLBACK(__mmplayer_gst_decode_autoplug_sort), player);
11476 /* This signal is emitted once decodebin2 has finished decoding all the data.*/
11477 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
11478 G_CALLBACK(__mmplayer_gst_decode_drained), player);
11480 /* This signal is emitted when a element is added to the bin.*/
11481 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
11482 G_CALLBACK(__mmplayer_gst_element_added), player);
11489 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
11491 MMPlayerGstElement* mainbin = NULL;
11492 GstElement* decodebin2 = NULL;
11493 GstElement* queue2 = NULL;
11494 GstElement* id3demux = NULL;
11495 GstPad* sinkpad = NULL;
11496 GstPad* qsrcpad= NULL;
11497 gchar *caps_str = NULL;
11498 gint64 dur_bytes = 0L;
11499 gchar* file_buffering_path = NULL;
11500 gboolean use_file_buffer = FALSE;
11502 guint max_buffer_size_bytes = 0;
11503 gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
11506 return_val_if_fail (player && player->pipeline && player->pipeline->mainbin, FALSE);
11508 mainbin = player->pipeline->mainbin;
11510 if ((!MMPLAYER_IS_HTTP_PD(player)) &&
11511 (MMPLAYER_IS_HTTP_STREAMING(player)))
11513 debug_log ("creating http streaming buffering queue (queue2)\n");
11515 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
11517 debug_error ("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
11521 queue2 = gst_element_factory_make ("queue2", "queue2");
11524 debug_error ("failed to create buffering queue element\n");
11528 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2))
11530 debug_error("failed to add buffering queue\n");
11534 sinkpad = gst_element_get_static_pad(queue2, "sink");
11535 qsrcpad = gst_element_get_static_pad(queue2, "src");
11537 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11539 debug_error("failed to link buffering queue\n");
11543 // if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
11545 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
11546 debug_error("fail to get duration.\n");
11548 debug_log("dur_bytes = %lld\n", dur_bytes);
11552 use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
11553 file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
11561 /* NOTE : we cannot get any duration info from ts container in case of streaming */
11562 // if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
11563 if(!g_strrstr(player->type, "video/mpegts"))
11565 max_buffer_size_bytes = (use_file_buffer)?(player->ini.http_max_size_bytes):(5*1024*1024);
11566 debug_log("max_buffer_size_bytes = %d\n", max_buffer_size_bytes);
11568 __mm_player_streaming_set_queue2(player->streamer,
11571 max_buffer_size_bytes,
11572 player->ini.http_buffering_time,
11574 player->ini.http_buffering_limit, // no meaning
11576 file_buffering_path,
11577 (guint64)dur_bytes);
11580 MMPLAYER_FREEIF(file_buffering_path);
11581 if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (queue2))
11583 debug_error("failed to sync queue2 state with parent\n");
11589 gst_object_unref(GST_OBJECT(sinkpad));
11591 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
11592 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
11596 /* create decodebin */
11597 decodebin2 = __mmplayer_create_decodebin(player);
11601 debug_error("can not create autoplug element\n");
11605 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin2))
11607 debug_error("failed to add decodebin2\n");
11611 /* to force caps on the decodebin element and avoid reparsing stuff by
11612 * typefind. It also avoids a deadlock in the way typefind activates pads in
11613 * the state change */
11614 g_object_set (decodebin2, "sink-caps", caps, NULL);
11616 sinkpad = gst_element_get_static_pad(decodebin2, "sink");
11618 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11620 debug_error("failed to link decodebin2\n");
11624 gst_object_unref(GST_OBJECT(sinkpad));
11626 mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
11627 mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin2;
11629 if ( ((!MMPLAYER_IS_HTTP_PD(player)) &&
11630 (MMPLAYER_IS_HTTP_STREAMING(player))) || MMPLAYER_IS_DASH_STREAMING (player))
11632 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
11634 g_object_set (G_OBJECT(decodebin2), "use-buffering", TRUE,
11635 "high-percent", (gint)player->ini.http_buffering_limit,
11636 "low-percent", 1, // 1%
11637 "max-size-bytes", MAX_DECODEBIN_BUFFER_BYTES,
11638 "max-size-time", (guint64)(MAX_DECODEBIN_BUFFER_TIME * GST_SECOND),
11639 "max-size-buffers", 0, NULL); // disable or automatic
11642 if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin2))
11644 debug_error("failed to sync decodebin2 state with parent\n");
11654 MMPLAYER_FREEIF( caps_str );
11657 gst_object_unref(GST_OBJECT(sinkpad));
11661 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
11662 * You need to explicitly set elements to the NULL state before
11663 * dropping the final reference, to allow them to clean up.
11665 gst_element_set_state(queue2, GST_STATE_NULL);
11667 /* And, it still has a parent "player".
11668 * You need to let the parent manage the object instead of unreffing the object directly.
11670 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
11671 gst_object_unref (queue2);
11677 /* NOTE : Trying to dispose element id3demux, but it is in READY instead of the NULL state.
11678 * You need to explicitly set elements to the NULL state before
11679 * dropping the final reference, to allow them to clean up.
11681 gst_element_set_state(id3demux, GST_STATE_NULL);
11683 /* And, it still has a parent "player".
11684 * You need to let the parent manage the object instead of unreffing the object directly.
11686 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), id3demux);
11687 gst_object_unref (id3demux);
11693 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
11694 * You need to explicitly set elements to the NULL state before
11695 * dropping the final reference, to allow them to clean up.
11697 gst_element_set_state(decodebin2, GST_STATE_NULL);
11699 /* And, it still has a parent "player".
11700 * You need to let the parent manage the object instead of unreffing the object directly.
11703 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin2);
11704 gst_object_unref (decodebin2);
11711 /* it will return first created element */
11713 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
11715 MMPlayerGstElement* mainbin = NULL;
11716 const char* mime = NULL;
11717 const GList* item = NULL;
11718 const gchar* klass = NULL;
11719 GstCaps* res = NULL;
11720 gboolean skip = FALSE;
11721 GstPad* queue_pad = NULL;
11722 GstElement* queue = NULL;
11723 GstElement *element = NULL;
11727 return_val_if_fail( player && player->pipeline && player->pipeline->mainbin, FALSE );
11729 mainbin = player->pipeline->mainbin;
11731 mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
11733 /* return if we got raw output */
11734 if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
11735 || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup"))
11738 element = (GstElement*)gst_pad_get_parent(pad);
11739 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
11740 * No queue will be added. I think it can caused breaking sound when playing raw audio
11741 * frames but there's no different. Decodebin also doesn't add with those wav fils.
11742 * Anyway, currentely raw-queue seems not necessary.
11745 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
11746 * has linked. if so, we need to add queue for quality of output. note that
11747 * decodebin also has same problem.
11749 klass = gst_element_factory_get_klass( gst_element_get_factory(element) );
11751 /* add queue if needed */
11752 if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
11753 || g_strrstr(klass, "Parse")) && !g_str_has_prefix(mime, "text"))
11755 debug_log("adding raw queue\n");
11757 queue = gst_element_factory_make("queue", NULL);
11760 debug_warning("failed to create queue\n");
11765 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
11767 debug_warning("failed to set state READY to queue\n");
11771 /* add to pipeline */
11772 if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
11774 debug_warning("failed to add queue\n");
11779 queue_pad = gst_element_get_static_pad(queue, "sink");
11781 if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
11783 debug_warning("failed to link queue\n");
11786 gst_object_unref ( GST_OBJECT(queue_pad) );
11790 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
11792 debug_warning("failed to set state READY to queue\n");
11796 /* replace given pad to queue:src */
11797 pad = gst_element_get_static_pad(queue, "src");
11800 debug_warning("failed to get pad from queue\n");
11805 /* check if player can do start continually */
11806 MMPLAYER_CHECK_CMD_IF_EXIT(player);
11808 if(__mmplayer_link_sink(player,pad))
11809 __mmplayer_gst_decode_callback(element, pad, player);
11811 gst_object_unref( GST_OBJECT(element));
11817 item = player->factories;
11818 for(; item != NULL ; item = item->next)
11820 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
11826 /* filtering exclude keyword */
11827 for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
11829 if ( g_strrstr(GST_OBJECT_NAME (factory),
11830 player->ini.exclude_element_keyword[idx] ) )
11832 debug_warning("skipping [%s] by exculde keyword [%s]\n",
11833 GST_OBJECT_NAME (factory),
11834 player->ini.exclude_element_keyword[idx] );
11841 if ( MMPLAYER_IS_RTSP_STREAMING(player) && g_strrstr(GST_OBJECT_NAME (factory), "omx_mpeg4dec"))
11843 // omx decoder can not support mpeg4video data partitioned
11844 // rtsp streaming didn't know mpeg4video data partitioned format
11845 // so, if rtsp playback, player will skip omx_mpeg4dec.
11846 debug_warning("skipping [%s] when rtsp streaming \n",
11847 GST_OBJECT_NAME (factory));
11852 if ( skip ) continue;
11854 /* check factory class for filtering */
11855 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory));
11858 /*parsers are not required in case of external feeder*/
11859 if (g_strrstr(klass, "Codec/Parser") && MMPLAYER_IS_ES_BUFF_SRC(player))
11862 /* NOTE : msl don't need to use image plugins.
11863 * So, those plugins should be skipped for error handling.
11865 if ( g_strrstr(klass, "Codec/Decoder/Image") )
11867 debug_log("skipping [%s] by not required\n", GST_OBJECT_NAME (factory));
11871 /* check pad compatability */
11872 for(pads = gst_element_factory_get_static_pad_templates(factory);
11873 pads != NULL; pads=pads->next)
11875 GstStaticPadTemplate *temp1 = pads->data;
11876 GstCaps* static_caps = NULL;
11878 if( temp1->direction != GST_PAD_SINK
11879 || temp1->presence != GST_PAD_ALWAYS)
11882 if ( GST_IS_CAPS( &temp1->static_caps.caps) )
11884 /* using existing caps */
11885 static_caps = gst_caps_ref(temp1->static_caps.caps );
11890 static_caps = gst_caps_from_string ( temp1->static_caps.string );
11893 res = gst_caps_intersect((GstCaps*)caps, static_caps);
11894 gst_caps_unref( static_caps );
11895 static_caps = NULL;
11897 if( res && !gst_caps_is_empty(res) )
11899 GstElement *new_element;
11900 GList *elements = player->parsers;
11901 char *name_template = g_strdup(temp1->name_template);
11902 gchar *name_to_plug = GST_OBJECT_NAME(factory);
11903 gst_caps_unref(res);
11905 /* check ALP Codec can be used or not */
11906 if ((g_strrstr(klass, "Codec/Decoder/Audio")))
11908 /* consider mp3 audio only */
11909 if ( !MMPLAYER_IS_STREAMING(player) && __mmplayer_is_only_mp3_type(player->type) )
11911 /* try to use ALP decoder first instead of selected decoder */
11912 GstElement *element = NULL;
11913 GstElementFactory * element_facory;
11914 gchar *path = NULL;
11915 guint64 data_size = 0;
11916 #define MIN_THRESHOLD_SIZE 320 * 1024 // 320K
11919 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
11921 if (stat(path, &sb) == 0)
11923 data_size = (guint64)sb.st_size;
11925 debug_log("file size : %u", data_size);
11927 if (data_size > MIN_THRESHOLD_SIZE)
11929 debug_log("checking if ALP can be used or not");
11930 element = gst_element_factory_make("omx_mp3dec", "omx mp3 decoder");
11933 /* check availability because multi-instance is not supported */
11934 GstStateChangeReturn ret = gst_element_set_state(element, GST_STATE_READY);
11936 if (ret != GST_STATE_CHANGE_SUCCESS) // use just selected decoder
11938 gst_object_unref (element);
11940 else if (ret == GST_STATE_CHANGE_SUCCESS) // replace facotry to use omx
11943 gst_element_set_state(element, GST_STATE_NULL);
11944 gst_object_unref (element);
11946 element_facory = gst_element_factory_find("omx_mp3dec");
11947 /* replace, otherwise use selected thing instead */
11948 if (element_facory)
11950 factory = element_facory;
11951 name_to_plug = GST_OBJECT_NAME(factory);
11954 /* make parser alp mode */
11955 #ifdef _MM_PLAYER_ALP_PARSER
11956 g_list_foreach (player->parsers, check_name, player);
11963 else if ((g_strrstr(klass, "Codec/Decoder/Video")))
11965 if ( g_strrstr(GST_OBJECT_NAME(factory), "omx_") )
11967 char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
11970 if (strncasecmp(env, "yes", 3) == 0)
11972 debug_log("skipping [%s] by disabled\n", name_to_plug);
11973 MMPLAYER_FREEIF(name_template);
11980 debug_log("found %s to plug\n", name_to_plug);
11982 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
11983 if ( ! new_element )
11985 debug_error("failed to create element [%s]. continue with next.\n",
11986 GST_OBJECT_NAME (factory));
11988 MMPLAYER_FREEIF(name_template);
11993 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
11994 * because parser can accept its own output as input.
11996 if (g_strrstr(klass, "Parser"))
11998 gchar *selected = NULL;
12000 for ( ; elements; elements = g_list_next(elements))
12002 gchar *element_name = elements->data;
12004 if (g_strrstr(element_name, name_to_plug))
12006 debug_log("but, %s already linked, so skipping it\n", name_to_plug);
12013 MMPLAYER_FREEIF(name_template);
12017 selected = g_strdup(name_to_plug);
12018 player->parsers = g_list_append(player->parsers, selected);
12021 /* store specific handles for futher control */
12022 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
12024 /* FIXIT : first value will be overwritten if there's more
12025 * than 1 demuxer/parser
12027 debug_log("plugged element is demuxer. take it\n");
12028 mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
12029 mainbin[MMPLAYER_M_DEMUX].gst = new_element;
12031 /*Added for multi audio support */
12032 if(g_strrstr(klass, "Demux"))
12034 mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
12035 mainbin[MMPLAYER_M_DEMUX_EX].gst = new_element;
12037 /* NOTE : workaround for bug in mpegtsdemux since doesn't emit
12038 no-more-pad signal. this may cause wrong content attributes at PAUSED state
12039 this code should be removed after mpegtsdemux is fixed */
12040 if ( g_strrstr(GST_OBJECT_NAME(factory), "mpegtsdemux") )
12042 debug_warning("force no-more-pad to TRUE since mpegtsdemux os not giving no-more-pad signal. content attributes may wrong");
12043 player->no_more_pad = TRUE;
12046 if (g_strrstr(name_to_plug, "asfdemux")) // to support trust-zone only
12048 g_object_set(mainbin[MMPLAYER_M_DEMUX_EX].gst, "file-location", player->profile.uri,NULL);
12051 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
12053 if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
12055 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
12056 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
12057 mainbin[MMPLAYER_M_DEC1].gst = new_element;
12059 else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
12061 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
12062 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
12063 mainbin[MMPLAYER_M_DEC2].gst = new_element;
12065 /* NOTE : IF one codec is found, add it to supported_codec and remove from
12066 * missing plugin. Both of them are used to check what's supported codec
12067 * before returning result of play start. And, missing plugin should be
12068 * updated here for multi track files.
12070 if(g_str_has_prefix(mime, "video"))
12072 GstPad *src_pad = NULL;
12073 GstPadTemplate *pad_templ = NULL;
12074 GstCaps *caps = NULL;
12075 gchar *caps_str = NULL;
12077 debug_log("found VIDEO decoder\n");
12078 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
12079 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
12081 src_pad = gst_element_get_static_pad (new_element, "src");
12082 pad_templ = gst_pad_get_pad_template (src_pad);
12083 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
12085 caps_str = gst_caps_to_string(caps);
12088 MMPLAYER_FREEIF( caps_str );
12089 gst_object_unref (src_pad);
12091 else if (g_str_has_prefix(mime, "audio"))
12093 debug_log("found AUDIO decoder\n");
12094 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
12095 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
12099 if ( ! __mmplayer_close_link(player, pad, new_element,
12100 name_template,gst_element_factory_get_static_pad_templates(factory)) )
12102 MMPLAYER_FREEIF(name_template);
12103 if (player->keep_detecting_vcodec)
12106 /* Link is failed even though a supportable codec is found. */
12107 __mmplayer_check_not_supported_codec(player, klass, mime);
12109 debug_error("failed to call _close_link\n");
12113 MMPLAYER_FREEIF(name_template);
12117 gst_caps_unref(res);
12122 /* There is no available codec. */
12123 __mmplayer_check_not_supported_codec(player, klass, mime);
12131 gst_object_unref( queue );
12134 gst_object_unref( queue_pad );
12137 gst_object_unref ( element );
12144 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
12148 return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
12149 return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
12151 debug_log("class : %s, mime : %s \n", factory_class, mime );
12153 /* add missing plugin */
12154 /* NOTE : msl should check missing plugin for image mime type.
12155 * Some motion jpeg clips can have playable audio track.
12156 * So, msl have to play audio after displaying popup written video format not supported.
12158 if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
12160 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
12162 debug_log("not found demuxer\n");
12163 player->not_found_demuxer = TRUE;
12164 player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
12170 if( !g_strrstr(factory_class, "Demuxer"))
12172 if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
12174 debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
12175 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
12177 /* check that clip have multi tracks or not */
12178 if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
12180 debug_log("video plugin is already linked\n");
12184 debug_warning("add VIDEO to missing plugin\n");
12185 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
12188 else if ( g_str_has_prefix(mime, "audio") )
12190 if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
12192 debug_log("audio plugin is already linked\n");
12196 debug_warning("add AUDIO to missing plugin\n");
12197 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
12205 return MM_ERROR_NONE;
12210 __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data)
12212 mm_player_t* player = (mm_player_t*)data;
12216 return_if_fail( player );
12218 /* remove fakesink. */
12219 if ( !__mmplayer_gst_remove_fakesink( player,
12220 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
12222 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
12223 * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
12224 * source element are not same. To overcome this situation, this function will called
12225 * several places and several times. Therefore, this is not an error case.
12230 debug_log("pipeline has completely constructed\n");
12232 if (( player->ini.async_start ) &&
12233 ( player->msg_posted == FALSE ) &&
12234 ( player->cmd >= MMPLAYER_COMMAND_START ))
12236 __mmplayer_handle_missed_plugin( player );
12239 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complete" );
12243 __mmplayer_verify_next_play_path(mm_player_t *player)
12245 MMHandleType attrs = 0;
12246 MMPlayerParseProfile profile;
12247 gint uri_idx = 0, check_cnt = 0;
12249 gint mode = MM_PLAYER_PD_MODE_NONE;
12251 guint num_of_list = 0;
12255 debug_log("checking for next play");
12257 if (player->pipeline->textbin)
12259 debug_error("subtitle path is enabled. next play is not supported.\n");
12263 attrs = MMPLAYER_GET_ATTRS(player);
12266 debug_error("fail to get attributes.\n");
12270 /* seamless playback is supported in case of audio only */
12271 mm_attrs_get_int_by_name(attrs, "content_video_found", &mode);
12274 debug_log("video found");
12278 if (mm_attrs_get_int_by_name (attrs, "pd_mode", &mode) == MM_ERROR_NONE)
12282 debug_warning("pd mode\n");
12287 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
12289 debug_error("can not get play count\n");
12292 num_of_list = g_list_length(player->uri_info.uri_list);
12294 debug_log("repeat count = %d, num_of_list = %d\n", count, num_of_list);
12296 if ( num_of_list == 0 )
12298 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE)
12300 debug_error("can not get profile_uri\n");
12306 debug_error("uri list is empty.\n");
12310 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12311 debug_log("add original path : %s ", uri);
12317 uri_idx = player->uri_info.uri_idx;
12323 if (check_cnt > num_of_list)
12325 debug_error("there is no valid uri.");
12329 debug_log("uri idx : %d / %d\n", uri_idx, num_of_list);
12331 if ( uri_idx < num_of_list-1 )
12337 if ((count <= 1) && (count != -1))
12339 debug_log("no repeat.");
12342 else if ( count > 1 ) /* decrease play count */
12344 /* we successeded to rewind. update play count and then wait for next EOS */
12347 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
12349 /* commit attribute */
12350 if ( mmf_attrs_commit ( attrs ) )
12352 debug_error("failed to commit attribute\n");
12356 /* count < 0 : repeat continually */
12360 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12361 debug_log("uri idx : %d, uri = %s\n", uri_idx, uri);
12365 debug_warning("next uri does not exist\n");
12369 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE)
12371 debug_error("failed to parse profile\n");
12375 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
12376 (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP))
12378 debug_warning("uri type is not supported (%d).", profile.uri_type);
12385 player->uri_info.uri_idx = uri_idx;
12386 mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
12389 if (mmf_attrs_commit(player->attrs))
12391 debug_error("failed to commit.\n");
12395 debug_log("next uri %s (%d)\n", uri, uri_idx);
12401 debug_error("unable to play next path. EOS will be posted soon.\n");
12406 __mmplayer_initialize_next_play(mm_player_t *player)
12412 player->needed_v_parser = FALSE;
12413 player->smooth_streaming = FALSE;
12414 player->videodec_linked = 0;
12415 player->audiodec_linked = 0;
12416 player->videosink_linked = 0;
12417 player->audiosink_linked = 0;
12418 player->textsink_linked = 0;
12419 player->is_external_subtitle_present = FALSE;
12420 player->not_supported_codec = MISSING_PLUGIN_NONE;
12421 player->can_support_codec = FOUND_PLUGIN_NONE;
12422 player->pending_seek.is_pending = FALSE;
12423 player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
12424 player->pending_seek.pos = 0;
12425 player->msg_posted = FALSE;
12426 player->has_many_types = FALSE;
12427 player->no_more_pad = FALSE;
12428 player->is_drm_file = FALSE;
12429 player->not_found_demuxer = 0;
12430 player->doing_seek = FALSE;
12431 player->max_audio_channels = 0;
12432 player->is_subtitle_force_drop = FALSE;
12433 player->play_subtitle = FALSE;
12434 player->use_textoverlay = FALSE;
12435 player->adjust_subtitle_pos = 0;
12437 player->updated_bitrate_count = 0;
12438 player->total_bitrate = 0;
12439 player->updated_maximum_bitrate_count = 0;
12440 player->total_maximum_bitrate = 0;
12442 _mmplayer_track_initialize(player);
12444 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
12446 player->bitrate[i] = 0;
12447 player->maximum_bitrate[i] = 0;
12450 if (player->v_stream_caps)
12452 gst_caps_unref(player->v_stream_caps);
12453 player->v_stream_caps = NULL;
12456 mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
12457 mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
12459 /* clean found parsers */
12460 if (player->parsers)
12462 GList *parsers = player->parsers;
12463 for ( ;parsers ; parsers = g_list_next(parsers))
12465 gchar *name = parsers->data;
12466 MMPLAYER_FREEIF(name);
12468 g_list_free(player->parsers);
12469 player->parsers = NULL;
12472 /* clean found audio decoders */
12473 if (player->audio_decoders)
12475 GList *a_dec = player->audio_decoders;
12476 for ( ;a_dec ; a_dec = g_list_next(a_dec))
12478 gchar *name = a_dec->data;
12479 MMPLAYER_FREEIF(name);
12481 g_list_free(player->audio_decoders);
12482 player->audio_decoders = NULL;
12489 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
12491 MMPlayerGstElement *mainbin = NULL;
12492 MMMessageParamType msg_param = {0,};
12493 GstElement *element = NULL;
12494 MMHandleType attrs = 0;
12496 enum MainElementID elemId = MMPLAYER_M_NUM;
12500 if ((player == NULL) ||
12501 (player->pipeline == NULL) ||
12502 (player->pipeline->mainbin == NULL))
12504 debug_error("player is null.\n");
12508 mainbin = player->pipeline->mainbin;
12509 msg_param.code = MM_ERROR_PLAYER_INTERNAL;
12511 attrs = MMPLAYER_GET_ATTRS(player);
12514 debug_error("fail to get attributes.\n");
12518 /* Initialize Player values */
12519 __mmplayer_initialize_next_play(player);
12521 mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
12523 if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE)
12525 debug_error("failed to parse profile\n");
12526 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
12530 if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
12531 (MMPLAYER_URL_HAS_HLS_SUFFIX(player)))
12533 debug_error("it's dash or hls. not support.");
12534 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
12539 switch ( player->profile.uri_type )
12542 case MM_PLAYER_URI_TYPE_FILE:
12544 debug_log("using filesrc for 'file://' handler.\n");
12546 element = gst_element_factory_make("filesrc", "source");
12550 debug_error("failed to create filesrc\n");
12554 g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */
12557 case MM_PLAYER_URI_TYPE_URL_HTTP:
12559 gchar *user_agent, *proxy, *cookies, **cookie_list;
12560 gint http_timeout = DEFAULT_HTTP_TIMEOUT;
12561 user_agent = proxy = cookies = NULL;
12562 cookie_list = NULL;
12564 element = gst_element_factory_make(player->ini.name_of_httpsrc, "http_streaming_source");
12567 debug_error("failed to create http streaming source element[%s].\n", player->ini.name_of_httpsrc);
12570 debug_log("using http streamming source [%s].\n", player->ini.name_of_httpsrc);
12572 /* get attribute */
12573 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
12574 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
12575 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
12576 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
12578 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
12579 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
12581 debug_log("get timeout from ini\n");
12582 http_timeout = player->ini.http_timeout;
12585 /* get attribute */
12586 secure_debug_log("location : %s\n", player->profile.uri);
12587 secure_debug_log("cookies : %s\n", cookies);
12588 secure_debug_log("proxy : %s\n", proxy);
12589 secure_debug_log("user_agent : %s\n", user_agent);
12590 debug_log("timeout : %d\n", http_timeout);
12592 /* setting property to streaming source */
12593 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
12594 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
12595 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
12597 /* check if prosy is vailid or not */
12598 if ( util_check_valid_url ( proxy ) )
12599 g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
12600 /* parsing cookies */
12601 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
12602 g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
12604 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
12608 debug_error("not support uri type %d\n", player->profile.uri_type);
12614 debug_error("no source element was created.\n");
12618 if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
12620 debug_error("failed to add source element to pipeline\n");
12621 gst_object_unref(GST_OBJECT(element));
12626 /* take source element */
12627 mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
12628 mainbin[MMPLAYER_M_SRC].gst = element;
12632 if (MMPLAYER_IS_HTTP_STREAMING(player))
12634 if (player->streamer == NULL)
12636 player->streamer = __mm_player_streaming_create();
12637 __mm_player_streaming_initialize(player->streamer);
12640 elemId = MMPLAYER_M_TYPEFIND;
12641 element = gst_element_factory_make("typefind", "typefinder");
12642 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
12643 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
12647 elemId = MMPLAYER_M_AUTOPLUG;
12648 element = __mmplayer_create_decodebin(player);
12651 /* check autoplug element is OK */
12654 debug_error("can not create element (%d)\n", elemId);
12658 if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
12660 debug_error("failed to add sinkbin to pipeline\n");
12661 gst_object_unref(GST_OBJECT(element));
12666 mainbin[elemId].id = elemId;
12667 mainbin[elemId].gst = element;
12669 if ( gst_element_link (mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE )
12671 debug_error("Failed to link src - autoplug (or typefind)\n");
12675 if (gst_element_set_state (mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE)
12677 debug_error("Failed to change state of src element\n");
12681 if (!MMPLAYER_IS_HTTP_STREAMING(player))
12683 if (gst_element_set_state (mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE)
12685 debug_error("Failed to change state of decodebin2\n");
12691 if (gst_element_set_state (mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE)
12693 debug_error("Failed to change state of src element\n");
12698 player->src_changed = TRUE;
12703 MMPLAYER_PLAYBACK_UNLOCK(player);
12705 if (!player->msg_posted)
12707 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
12708 player->msg_posted = TRUE;
12714 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
12716 mm_player_selector_t *selector = &player->selector[type];
12717 MMPlayerGstElement *sinkbin = NULL;
12718 enum MainElementID selectorId = MMPLAYER_M_NUM;
12719 enum MainElementID sinkId = MMPLAYER_M_NUM;
12720 GstPad *srcpad = NULL;
12721 GstPad *sinkpad = NULL;
12724 return_val_if_fail (player, FALSE);
12726 debug_log("type %d", type);
12730 #ifdef _USE_M_V_INPUT_SELECTOR_
12731 case MM_PLAYER_TRACK_TYPE_VIDEO:
12732 selectorId = MMPLAYER_M_V_INPUT_SELECTOR;
12733 sinkId = MMPLAYER_V_BIN;
12734 sinkbin = player->pipeline->videobin;
12735 debug_log("not supported yet");
12738 case MM_PLAYER_TRACK_TYPE_AUDIO:
12739 selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
12740 sinkId = MMPLAYER_A_BIN;
12741 sinkbin = player->pipeline->audiobin;
12743 case MM_PLAYER_TRACK_TYPE_TEXT:
12744 selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
12745 sinkId = MMPLAYER_T_BIN;
12746 sinkbin = player->pipeline->textbin;
12749 debug_error("requested type is not supportable");
12754 if (player->pipeline->mainbin[selectorId].gst)
12758 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
12760 if ((sinkbin) && (sinkbin[sinkId].gst))
12762 sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
12764 if (srcpad && sinkpad)
12766 /* after getting drained signal there is no data flows, so no need to do pad_block */
12767 debug_log("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
12768 gst_pad_unlink (srcpad, sinkpad);
12771 gst_object_unref (sinkpad);
12774 gst_object_unref (srcpad);
12777 debug_log("selector release");
12779 /* release and unref requests pad from the selector */
12780 for (n = 0; n < selector->channels->len; n++)
12782 GstPad *sinkpad = g_ptr_array_index (selector->channels, n);
12783 gst_element_release_request_pad ((player->pipeline->mainbin[selectorId].gst), sinkpad);
12785 g_ptr_array_set_size (selector->channels, 0);
12787 gst_element_set_state (player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
12788 gst_bin_remove (GST_BIN_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
12790 player->pipeline->mainbin[selectorId].gst = NULL;
12798 __mmplayer_deactivate_old_path(mm_player_t *player)
12801 return_if_fail ( player );
12803 g_object_set(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEC1].gst), "remove-buffer-signal", TRUE, NULL);
12804 #ifdef _USE_M_V_INPUT_SELECTOR_
12805 if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
12806 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
12807 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT)))
12809 if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
12810 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT)))
12813 debug_error("deactivate selector error");
12817 _mmplayer_track_destroy(player);
12818 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG );
12820 if (player->streamer)
12822 __mm_player_streaming_deinitialize (player->streamer);
12823 __mm_player_streaming_destroy(player->streamer);
12824 player->streamer = NULL;
12827 MMPLAYER_PLAYBACK_LOCK(player);
12828 g_cond_signal( &player->next_play_thread_cond );
12835 if (!player->msg_posted)
12837 MMMessageParamType msg = {0,};
12840 msg.code = MM_ERROR_PLAYER_INTERNAL;
12841 debug_error("next_uri_play> deactivate error");
12843 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
12844 player->msg_posted = TRUE;
12849 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
12851 int result = MM_ERROR_NONE;
12852 mm_player_t* player = (mm_player_t*) hplayer;
12855 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12857 mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
12858 if (mmf_attrs_commit(player->attrs))
12860 debug_error("failed to commit the original uri.\n");
12861 result = MM_ERROR_PLAYER_INTERNAL;
12865 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
12867 debug_error("failed to add the original uri in the uri list.\n");
12875 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
12877 mm_player_t* player = (mm_player_t*) hplayer;
12878 guint num_of_list = 0;
12882 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12883 return_val_if_fail (uri, MM_ERROR_INVALID_ARGUMENT);
12885 if (player->pipeline && player->pipeline->textbin)
12887 debug_error("subtitle path is enabled.\n");
12888 return MM_ERROR_PLAYER_INVALID_STATE;
12891 num_of_list = g_list_length(player->uri_info.uri_list);
12893 if (is_first_path == TRUE)
12895 if (num_of_list == 0)
12897 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12898 debug_log("add original path : %s", uri);
12902 player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
12903 player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
12905 debug_log("change original path : %s", uri);
12910 if (num_of_list == 0)
12912 MMHandleType attrs = 0;
12913 char *original_uri = NULL;
12915 attrs = MMPLAYER_GET_ATTRS(player);
12918 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
12922 debug_error("there is no original uri.");
12923 return MM_ERROR_PLAYER_INVALID_STATE;
12926 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
12927 player->uri_info.uri_idx = 0;
12929 debug_log("add original path at first : %s (%d)", original_uri);
12933 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12934 debug_log("add new path : %s (total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
12938 return MM_ERROR_NONE;
12941 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
12943 mm_player_t* player = (mm_player_t*) hplayer;
12944 char *next_uri = NULL;
12945 guint num_of_list = 0;
12948 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12950 num_of_list = g_list_length(player->uri_info.uri_list);
12952 if (num_of_list > 0)
12954 gint uri_idx = player->uri_info.uri_idx;
12956 if ( uri_idx < num_of_list-1 )
12961 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12962 debug_error("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
12964 *uri = g_strdup(next_uri);
12968 return MM_ERROR_NONE;
12972 __mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad* pad,
12973 GstCaps *caps, gpointer data)
12975 mm_player_t* player = (mm_player_t*)data;
12976 const gchar* klass = NULL;
12977 const gchar* mime = NULL;
12978 gchar* caps_str = NULL;
12980 klass = gst_element_factory_get_klass (gst_element_get_factory(elem));
12981 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12982 caps_str = gst_caps_to_string(caps);
12984 debug_warning("unknown type of caps : %s from %s",
12985 caps_str, GST_ELEMENT_NAME (elem));
12987 MMPLAYER_FREEIF(caps_str);
12989 /* There is no available codec. */
12990 __mmplayer_check_not_supported_codec (player, klass, mime);
12994 __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad* pad,
12995 GstCaps * caps, gpointer data)
12997 mm_player_t* player = (mm_player_t*)data;
12998 const char* mime = NULL;
12999 gboolean ret = TRUE;
13001 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
13002 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
13004 if (g_str_has_prefix(mime, "audio")) {
13005 GstStructure* caps_structure = NULL;
13006 gint samplerate = 0;
13008 gchar *caps_str = NULL;
13010 caps_structure = gst_caps_get_structure(caps, 0);
13011 gst_structure_get_int (caps_structure, "rate", &samplerate);
13012 gst_structure_get_int (caps_structure, "channels", &channels);
13014 if ( (channels > 0 && samplerate == 0)) {
13015 debug_log("exclude audio...");
13019 caps_str = gst_caps_to_string(caps);
13020 /* set it directly because not sent by TAG */
13021 if (g_strrstr(caps_str, "mobile-xmf")) {
13022 mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
13024 MMPLAYER_FREEIF (caps_str);
13025 } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
13026 debug_log("already video linked");
13029 debug_log("found new stream");
13036 __mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad* pad,
13037 GstCaps* caps, GstElementFactory* factory, gpointer data)
13039 /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
13040 We are defining our own and will be removed when it actually exposed */
13042 GST_AUTOPLUG_SELECT_TRY,
13043 GST_AUTOPLUG_SELECT_EXPOSE,
13044 GST_AUTOPLUG_SELECT_SKIP
13045 } GstAutoplugSelectResult;
13047 GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
13048 mm_player_t* player = (mm_player_t*)data;
13050 gchar* factory_name = NULL;
13051 gchar* caps_str = NULL;
13052 const gchar* klass = NULL;
13055 factory_name = GST_OBJECT_NAME (factory);
13056 klass = gst_element_factory_get_klass(factory);
13057 caps_str = gst_caps_to_string(caps);
13059 // debug_log("found new element [%s] to link for caps [%s]", factory_name, caps_str);
13060 debug_log("found new element [%s] to link", factory_name);
13062 /* store type string */
13063 if (player->type == NULL)
13065 player->type = gst_caps_to_string(caps);
13067 /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
13068 if (__mmplayer_is_midi_type(player->type))
13070 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
13071 player->bypass_audio_effect = TRUE;
13073 else if (g_strrstr(player->type, "application/x-hls"))
13075 /* If it can't know exact type when it parses uri because of redirection case,
13076 * it will be fixed by typefinder here.
13078 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
13080 else if (g_strrstr(player->type, "application/dash+xml"))
13082 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
13086 /* filtering exclude keyword */
13087 for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
13089 if ( strstr(factory_name, player->ini.exclude_element_keyword[idx] ) )
13091 debug_warning("skipping [%s] by exculde keyword [%s]\n",
13092 factory_name, player->ini.exclude_element_keyword[idx] );
13094 // NOTE : does we need to check n_value against the number of item selected?
13095 result = GST_AUTOPLUG_SELECT_SKIP;
13100 /* check factory class for filtering */
13101 /* NOTE : msl don't need to use image plugins.
13102 * So, those plugins should be skipped for error handling.
13104 if (g_strrstr(klass, "Codec/Decoder/Image"))
13106 debug_log("skipping [%s] by not required\n", factory_name);
13107 result = GST_AUTOPLUG_SELECT_SKIP;
13112 if ((MMPLAYER_IS_ES_BUFF_SRC(player)) &&
13113 (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser"))))
13115 // TO CHECK : subtitle if needed, add subparse exception.
13116 debug_log("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
13117 result = GST_AUTOPLUG_SELECT_SKIP;
13122 if (g_strrstr(factory_name, "mpegpsdemux"))
13124 debug_log("skipping PS container - not support\n");
13125 result = GST_AUTOPLUG_SELECT_SKIP;
13129 if (g_strrstr(factory_name, "mpegtsdemux") || g_strrstr(factory_name, SMOOTH_STREAMING_DEMUX))
13131 if (g_strrstr(factory_name, SMOOTH_STREAMING_DEMUX))
13132 player->smooth_streaming = TRUE;
13134 if (g_strrstr(caps_str, "video/x-h264"))
13136 player->needed_v_parser = TRUE;
13138 else if (g_strrstr(caps_str, "video/mpeg"))
13140 player->needed_v_parser = TRUE;
13144 /* check ALP Codec can be used or not */
13145 if ((g_strrstr(klass, "Codec/Decoder/Audio")))
13147 GstStructure* str = NULL;
13150 str = gst_caps_get_structure( caps, 0 );
13153 gst_structure_get_int (str, "channels", &channels);
13155 debug_log ("check audio ch : %d %d\n", player->max_audio_channels, channels);
13156 if (player->max_audio_channels < channels)
13158 player->max_audio_channels = channels;
13162 if (!player->audiodec_linked)
13164 /* set stream information */
13165 __mmplayer_set_audio_attrs (player, caps);
13168 else if ((g_strrstr(klass, "Codec/Decoder/Video")))
13170 if (g_strrstr(factory_name, "omx_"))
13172 char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
13175 if (strncasecmp(env, "yes", 3) == 0)
13177 debug_log ("skipping [%s] by disabled\n", factory_name);
13178 result = GST_AUTOPLUG_SELECT_SKIP;
13185 if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
13186 (g_strrstr(klass, "Codec/Decoder/Video")))
13190 GstStructure *str = NULL;
13191 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
13193 /* don't make video because of not required */
13194 if (stype == MM_DISPLAY_SURFACE_NULL)
13196 debug_log ("no video because it's not required. -> return expose");
13197 if (player->set_mode.media_packet_video_stream == FALSE)
13199 result = GST_AUTOPLUG_SELECT_EXPOSE;
13204 /* get w/h for omx state-tune */
13205 str = gst_caps_get_structure (caps, 0);
13206 gst_structure_get_int (str, "width", &width);
13209 if (player->v_stream_caps) {
13210 gst_caps_unref(player->v_stream_caps);
13211 player->v_stream_caps = NULL;
13214 player->v_stream_caps = gst_caps_copy(caps);
13215 debug_log ("take caps for video state tune");
13216 MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
13220 if (g_strrstr(klass, "Decoder"))
13222 const char* mime = NULL;
13223 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
13225 if (g_str_has_prefix(mime, "video"))
13227 // __mmplayer_check_video_zero_cpoy(player, factory);
13229 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
13230 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
13232 player->videodec_linked = 1;
13234 else if(g_str_has_prefix(mime, "audio"))
13236 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
13237 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
13239 player->audiodec_linked = 1;
13244 MMPLAYER_FREEIF(caps_str);
13251 static GValueArray*
13252 __mmplayer_gst_decode_autoplug_factories(GstElement *bin, GstPad* pad,
13253 GstCaps * caps, gpointer data)
13255 //mm_player_t* player = (mm_player_t*)data;
13257 debug_log("decodebin is requesting factories for caps [%s] from element[%s]",
13258 gst_caps_to_string(caps),
13259 GST_ELEMENT_NAME(GST_PAD_PARENT(pad)));
13265 static GValueArray*
13266 __mmplayer_gst_decode_autoplug_sort(GstElement *bin, GstPad* pad,
13267 GstCaps* caps, GValueArray* factories, gpointer data) // @
13269 #define DEFAULT_IDX 0xFFFF
13272 guint a_omx_idx = DEFAULT_IDX;
13273 guint a_dec_idx = DEFAULT_IDX;
13274 guint v_dec_idx = DEFAULT_IDX;
13275 guint v_parser_idx = DEFAULT_IDX;
13276 guint new_pos = DEFAULT_IDX;
13277 guint elem_idx = DEFAULT_IDX;
13279 GValueArray* new_factories = NULL;
13280 GValue val = { 0, };
13282 GstElementFactory *factory = NULL;
13283 const gchar* klass = NULL;
13284 gchar* factory_name = NULL;
13285 gchar* caps_str = NULL;
13287 mm_player_t* player = (mm_player_t*)data;
13288 caps_str = gst_caps_to_string(caps);
13290 //debug_log("autoplug-sort signal [num: %d]\n", factories->n_values);
13291 debug_log("requesting custom sorting for the factories for caps [%s]", caps_str);
13293 MMPLAYER_FREEIF(caps_str);
13295 for(idx=0; idx < factories->n_values; idx++)
13297 factory = g_value_get_object(g_value_array_get_nth(factories, idx));
13298 klass = gst_element_factory_get_klass(factory);
13299 factory_name = GST_OBJECT_NAME (factory);
13301 //debug_log("Klass [%s] Factory [%s]\n", klass, factory_name);
13303 if (g_strrstr(klass, "Codec/Decoder/Audio"))
13305 if (a_dec_idx == DEFAULT_IDX)
13308 /* check ALP Codec can be used or not */
13309 if ((a_omx_idx == DEFAULT_IDX) &&
13310 (g_strrstr(factory_name, "omx_mp3dec")) &&
13311 (__mmplayer_is_omx_decoder_type(player)))
13313 debug_log("--> mp3_local : Priority of omx is higher than the others\n");
13318 else if ((v_dec_idx == DEFAULT_IDX) && (g_strrstr(klass, "Codec/Decoder/Video")))
13323 if ((v_parser_idx == DEFAULT_IDX) &&
13324 (((player->smooth_streaming) &&
13325 (g_strrstr(factory_name, "legacyh264parse"))) ||
13326 // (g_strrstr(factory_name, "h264parse")) ||
13327 (g_strrstr(factory_name, "mpeg4videoparse"))))
13329 v_parser_idx = idx;
13333 if (player->needed_v_parser || player->smooth_streaming)
13335 debug_log("needed parser? %s, ss? %s\n",
13336 (player->needed_v_parser)?"OO":"XX",
13337 (player->smooth_streaming)?"OO":"XX");
13340 new_pos = (a_dec_idx!=DEFAULT_IDX)?(a_dec_idx):((player->needed_v_parser)?(v_dec_idx):(v_parser_idx));
13341 elem_idx = (a_omx_idx!=DEFAULT_IDX)?(a_omx_idx):((player->needed_v_parser)?(v_parser_idx):(v_dec_idx));
13343 /* consider file mp3 audio only */
13344 if ((elem_idx != DEFAULT_IDX) && (new_pos < elem_idx))
13346 debug_log("[Re-arrange] factories sequence, new_pos : %d, elem_idx : %d\n", new_pos, elem_idx);
13348 new_factories = g_value_array_copy(factories);
13350 // insert omx decoder in front of other decoders
13351 factory = g_value_get_object(g_value_array_get_nth(factories, elem_idx));
13353 g_value_init (&val, G_TYPE_OBJECT);
13354 g_value_set_object (&val, factory);
13355 g_value_array_insert(new_factories, new_pos, &val);
13356 g_value_unset (&val);
13358 // remove duplicated omx element
13359 g_value_array_remove(new_factories, elem_idx+1);
13361 for(idx=0; idx < new_factories->n_values; idx++)
13363 factory = g_value_get_object(g_value_array_get_nth(new_factories, idx));
13365 debug_log("[Re-arranged] Klass [%s] Factory [%s]\n",
13366 gst_element_factory_get_klass(factory), GST_OBJECT_NAME (factory));
13370 /* returning NULL to keep current order */
13371 return (new_factories)?(new_factories):(NULL);
13375 __mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad* new_pad,
13376 gpointer data) // @
13378 //mm_player_t* player = (mm_player_t*)data;
13379 GstCaps* caps = NULL;
13381 debug_log("[Decodebin2] pad-removed signal\n");
13383 caps = gst_pad_query_caps(new_pad, NULL);
13386 gchar* caps_str = NULL;
13387 caps_str = gst_caps_to_string(caps);
13389 debug_log("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem) );
13391 MMPLAYER_FREEIF(caps_str);
13396 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
13398 mm_player_t* player = (mm_player_t*)data;
13401 return_if_fail ( player );
13403 debug_log("__mmplayer_gst_decode_drained");
13405 if (player->use_deinterleave == TRUE)
13407 debug_log("group playing mode.");
13411 if (!g_mutex_trylock(&player->cmd_lock))
13413 debug_warning("Fail to get cmd lock");
13417 if (!__mmplayer_verify_next_play_path(player))
13419 debug_log("decoding is finished.");
13420 g_mutex_unlock(&player->cmd_lock);
13424 player->pp_rebuilding = TRUE;
13426 /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
13427 __mmplayer_deactivate_old_path(player);
13429 g_mutex_unlock(&player->cmd_lock);
13435 __mmplayer_gst_element_added (GstElement *bin, GstElement *element, gpointer data)
13437 mm_player_t* player = (mm_player_t*)data;
13438 const gchar* klass = NULL;
13439 gchar* factory_name = NULL;
13441 klass = gst_element_factory_get_klass (gst_element_get_factory(element));
13442 factory_name = GST_OBJECT_NAME (gst_element_get_factory(element));
13444 debug_log("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
13446 if (__mmplayer_add_dump_buffer_probe(player, element))
13447 debug_log("add buffer probe");
13450 if (g_strrstr(klass, "Codec/Decoder/Audio"))
13452 gchar* selected = NULL;
13453 selected = g_strdup( GST_ELEMENT_NAME(element));
13454 player->audio_decoders = g_list_append (player->audio_decoders, selected);
13458 if (g_strrstr(klass, "Parser"))
13460 gchar* selected = NULL;
13462 selected = g_strdup (factory_name);
13463 player->parsers = g_list_append (player->parsers, selected);
13466 if ((g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) && !(g_strrstr(klass, "Adaptive")))
13468 /* FIXIT : first value will be overwritten if there's more
13469 * than 1 demuxer/parser
13472 //debug_log ("plugged element is demuxer. take it\n");
13473 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
13474 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
13476 /*Added for multi audio support */ // Q. del?
13477 if (g_strrstr(klass, "Demux"))
13479 player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
13480 player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
13484 if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux"))
13486 int surface_type = 0;
13488 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
13490 #if 0 // this is for 0.10 plugin with downstream modification
13491 /* playback protection if drm file */
13492 if (player->use_video_stream || surface_type == MM_DISPLAY_SURFACE_EVAS || surface_type == MM_DISPLAY_SURFACE_X_EXT)
13494 debug_log("playback can be protected if playready drm");
13495 g_object_set (G_OBJECT(element), "playback-protection", TRUE, NULL);
13500 // to support trust-zone only
13501 if (g_strrstr(factory_name, "asfdemux"))
13503 debug_log ("set file-location %s\n", player->profile.uri);
13504 g_object_set (G_OBJECT(element), "file-location", player->profile.uri, NULL);
13506 if (player->video_hub_download_mode == TRUE)
13508 g_object_set (G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
13511 else if (g_strrstr(factory_name, "legacyh264parse")) // SMOOTH_STREAMING_DEMUX
13513 debug_log ("[%s] output-format to legacyh264parse\n", SMOOTH_STREAMING_DEMUX);
13514 g_object_set (G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
13516 else if (g_strrstr(factory_name, "mpegaudioparse"))
13518 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
13519 (__mmplayer_is_only_mp3_type(player->type)))
13521 debug_log ("[mpegaudioparse] set streaming pull mode.");
13522 g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
13525 else if (g_strrstr(factory_name, "omx"))
13527 if (g_strrstr(klass, "Codec/Decoder/Video"))
13529 gboolean ret = FALSE;
13531 if (player->v_stream_caps != NULL)
13533 GstPad *pad = gst_element_get_static_pad(element, "sink");
13537 ret = gst_pad_set_caps(pad, player->v_stream_caps);
13538 debug_log("found omx decoder, setting gst_pad_set_caps for omx (ret:%d)", ret);
13539 MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
13540 gst_object_unref (pad);
13543 g_object_set (G_OBJECT(element), "state-tuning", TRUE, NULL);
13545 #ifdef _MM_PLAYER_ALP_PARSER
13546 if (g_strrstr(factory_name, "omx_mp3dec"))
13548 g_list_foreach (player->parsers, check_name, player);
13551 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
13554 if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
13555 (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue")))
13557 debug_log ("plugged element is multiqueue. take it\n");
13559 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
13560 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
13562 if ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
13563 (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)))
13566 if ((MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) &&
13567 (player->streamer->buffering_req.initial_second == 0))
13568 player->streamer->buffering_req.initial_second = DEFAULT_LIVE_PLAYING_TIME;
13570 __mm_player_streaming_set_multiqueue(player->streamer,
13573 MAX_DECODEBIN_BUFFER_BYTES, // player->ini.http_max_size_bytes,
13574 player->ini.http_buffering_time,
13576 player->ini.http_buffering_limit);
13578 __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
13582 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-added" );
13586 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
13589 return_val_if_fail ( player, FALSE );
13591 if ( MMPLAYER_IS_STREAMING(player) )
13594 /* This callback can be set to music player only. */
13595 if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
13597 debug_warning("audio callback is not supported for video");
13601 if (player->audio_stream_cb)
13604 GstPad *pad = NULL;
13606 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
13610 debug_error("failed to get sink pad from audiosink to probe data\n");
13613 player->audio_cb_probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
13614 __mmplayer_audio_stream_probe, player, NULL);
13616 gst_object_unref (pad);
13623 debug_error("There is no audio callback to configure.\n");
13633 __mmplayer_init_factories(mm_player_t* player) // @
13635 return_if_fail ( player );
13637 player->factories = gst_registry_feature_filter(gst_registry_get(),
13638 (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
13639 player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
13643 __mmplayer_release_factories(mm_player_t* player) // @
13646 return_if_fail ( player );
13648 if (player->factories)
13650 gst_plugin_feature_list_free (player->factories);
13651 player->factories = NULL;
13658 __mmplayer_release_misc(mm_player_t* player)
13661 gboolean cur_mode = player->set_mode.rich_audio;
13664 return_if_fail ( player );
13666 player->use_video_stream = FALSE;
13667 player->video_stream_cb = NULL;
13668 player->video_stream_cb_user_param = NULL;
13670 player->audio_stream_cb = NULL;
13671 player->audio_stream_render_cb_ex = NULL;
13672 player->audio_stream_cb_user_param = NULL;
13673 player->audio_stream_sink_sync = false;
13675 player->video_stream_changed_cb = NULL;
13676 player->video_stream_changed_cb_user_param = NULL;
13678 player->audio_stream_changed_cb = NULL;
13679 player->audio_stream_changed_cb_user_param = NULL;
13681 player->sent_bos = FALSE;
13682 player->playback_rate = DEFAULT_PLAYBACK_RATE;
13684 player->doing_seek = FALSE;
13686 player->updated_bitrate_count = 0;
13687 player->total_bitrate = 0;
13688 player->updated_maximum_bitrate_count = 0;
13689 player->total_maximum_bitrate = 0;
13691 player->not_found_demuxer = 0;
13693 player->last_position = 0;
13694 player->duration = 0;
13695 player->http_content_size = 0;
13696 player->not_supported_codec = MISSING_PLUGIN_NONE;
13697 player->can_support_codec = FOUND_PLUGIN_NONE;
13698 player->pending_seek.is_pending = FALSE;
13699 player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
13700 player->pending_seek.pos = 0;
13701 player->msg_posted = FALSE;
13702 player->has_many_types = FALSE;
13703 player->is_drm_file = FALSE;
13704 player->max_audio_channels = 0;
13705 player->video_share_api_delta = 0;
13706 player->video_share_clock_delta = 0;
13707 player->sm.keep_last_pos = FALSE;
13708 player->is_subtitle_force_drop = FALSE;
13709 player->play_subtitle = FALSE;
13710 player->use_textoverlay = FALSE;
13711 player->adjust_subtitle_pos = 0;
13712 player->last_multiwin_status = FALSE;
13713 player->has_closed_caption = FALSE;
13714 player->set_mode.media_packet_video_stream = FALSE;
13716 memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
13718 player->set_mode.rich_audio = cur_mode;
13720 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
13722 player->bitrate[i] = 0;
13723 player->maximum_bitrate[i] = 0;
13726 /* remove media stream cb (appsrc cb) */
13727 for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++)
13729 player->media_stream_buffer_status_cb[i] = NULL;
13730 player->media_stream_seek_data_cb[i] = NULL;
13733 /* free memory related to audio effect */
13734 MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
13736 if (player->state_tune_caps)
13738 gst_caps_unref(player->state_tune_caps);
13739 player->state_tune_caps = NULL;
13742 if (player->video_cb_probe_id)
13744 GstPad *pad = NULL;
13746 pad = gst_element_get_static_pad (player->video_fakesink, "sink");
13749 debug_log("release video probe\n");
13751 /* release audio callback */
13752 gst_pad_remove_probe (pad, player->video_cb_probe_id);
13753 player->video_cb_probe_id = 0;
13754 player->video_stream_cb = NULL;
13755 player->video_stream_cb_user_param = NULL;
13763 __mmplayer_release_misc_post(mm_player_t* player)
13765 char *original_uri = NULL;
13768 /* player->pipeline is already released before. */
13770 return_if_fail ( player );
13772 mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
13773 mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
13775 /* clean found parsers */
13776 if (player->parsers)
13778 GList *parsers = player->parsers;
13779 for ( ;parsers ; parsers = g_list_next(parsers))
13781 gchar *name = parsers->data;
13782 MMPLAYER_FREEIF(name);
13784 g_list_free(player->parsers);
13785 player->parsers = NULL;
13788 /* clean found audio decoders */
13789 if (player->audio_decoders)
13791 GList *a_dec = player->audio_decoders;
13792 for ( ;a_dec ; a_dec = g_list_next(a_dec))
13794 gchar *name = a_dec->data;
13795 MMPLAYER_FREEIF(name);
13797 g_list_free(player->audio_decoders);
13798 player->audio_decoders = NULL;
13801 /* clean the uri list except original uri */
13802 if (player->uri_info.uri_list)
13804 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
13808 mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
13809 debug_log("restore original uri = %s\n", original_uri);
13811 if (mmf_attrs_commit(player->attrs))
13813 debug_error("failed to commit the original uri.\n");
13817 GList *uri_list = player->uri_info.uri_list;
13818 for ( ;uri_list ; uri_list = g_list_next(uri_list))
13820 gchar *uri = uri_list->data;
13821 MMPLAYER_FREEIF(uri);
13823 g_list_free(player->uri_info.uri_list);
13824 player->uri_info.uri_list = NULL;
13827 player->uri_info.uri_idx = 0;
13828 player->src_changed = FALSE;
13833 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
13835 GstElement *element = NULL;
13838 debug_log("creating %s to plug\n", name);
13840 element = gst_element_factory_make(name, NULL);
13843 debug_error("failed to create queue\n");
13847 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
13849 debug_error("failed to set state READY to %s\n", name);
13850 gst_object_unref (element);
13854 if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
13856 debug_error("failed to add %s\n", name);
13857 gst_object_unref (element);
13861 sinkpad = gst_element_get_static_pad(element, "sink");
13863 if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
13865 debug_error("failed to link %s\n", name);
13866 gst_object_unref (sinkpad);
13867 gst_object_unref (element);
13871 debug_log("linked %s to pipeline successfully\n", name);
13873 gst_object_unref (sinkpad);
13879 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
13880 const char *padname, const GList *templlist)
13882 GstPad *pad = NULL;
13883 gboolean has_dynamic_pads = FALSE;
13884 gboolean has_many_types = FALSE;
13885 const char *klass = NULL;
13886 GstStaticPadTemplate *padtemplate = NULL;
13887 GstElementFactory *factory = NULL;
13888 GstElement* queue = NULL;
13889 GstElement* parser = NULL;
13890 GstPad *pssrcpad = NULL;
13891 GstPad *qsrcpad = NULL, *qsinkpad = NULL;
13892 MMPlayerGstElement *mainbin = NULL;
13893 GstStructure* str = NULL;
13894 GstCaps* srccaps = NULL;
13895 GstState target_state = GST_STATE_READY;
13896 gboolean isvideo_decoder = FALSE;
13897 guint q_max_size_time = 0;
13901 return_val_if_fail ( player &&
13902 player->pipeline &&
13903 player->pipeline->mainbin,
13906 mainbin = player->pipeline->mainbin;
13908 debug_log("plugging pad %s:%s to newly create %s:%s\n",
13909 GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
13910 GST_PAD_NAME( srcpad ),
13911 GST_ELEMENT_NAME( sinkelement ),
13914 factory = gst_element_get_factory(sinkelement);
13915 klass = gst_element_factory_get_klass(factory);
13917 /* check if player can do start continually */
13918 MMPLAYER_CHECK_CMD_IF_EXIT(player);
13920 /* need it to warm up omx before linking to pipeline */
13921 if (g_strrstr(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ), "demux"))
13923 debug_log("get demux caps.\n");
13924 if (player->state_tune_caps)
13926 gst_caps_unref(player->state_tune_caps);
13927 player->state_tune_caps = NULL;
13929 player->state_tune_caps = gst_caps_copy(gst_pad_get_current_caps(srcpad));
13932 /* NOTE : OMX Codec can check if resource is available or not at this state. */
13933 if (g_strrstr(GST_ELEMENT_NAME(sinkelement), "omx"))
13935 if (player->state_tune_caps != NULL)
13937 debug_log("set demux's caps to omx codec if resource is available");
13938 if (gst_pad_set_caps(gst_element_get_static_pad(sinkelement, "sink"), player->state_tune_caps))
13940 target_state = GST_STATE_PAUSED;
13941 isvideo_decoder = TRUE;
13942 g_object_set(G_OBJECT(sinkelement), "state-tuning", TRUE, NULL);
13946 debug_warning("failed to set caps for state tuning");
13949 gst_caps_unref(player->state_tune_caps);
13950 player->state_tune_caps = NULL;
13953 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, target_state) )
13955 debug_error("failed to set %d state to %s\n", target_state, GST_ELEMENT_NAME( sinkelement ));
13956 if (isvideo_decoder)
13958 gst_element_set_state(sinkelement, GST_STATE_NULL);
13959 gst_object_unref(G_OBJECT(sinkelement));
13960 player->keep_detecting_vcodec = TRUE;
13965 /* add to pipeline */
13966 if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
13968 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
13972 debug_log("element klass : %s\n", klass);
13974 /* added to support multi track files */
13975 /* only decoder case and any of the video/audio still need to link*/
13976 if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
13978 gchar *name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
13980 if (g_strrstr(name, "mpegtsdemux")|| g_strrstr(name, SMOOTH_STREAMING_DEMUX))
13982 gchar *src_demux_caps_str = NULL;
13983 gchar *needed_parser = NULL;
13984 GstCaps *src_demux_caps = NULL;
13985 gboolean smooth_streaming = FALSE;
13987 src_demux_caps = gst_pad_query_caps(srcpad, NULL);
13988 src_demux_caps_str = gst_caps_to_string(src_demux_caps);
13990 gst_caps_unref(src_demux_caps);
13992 if (g_strrstr(src_demux_caps_str, "video/x-h264"))
13994 if (g_strrstr(name, SMOOTH_STREAMING_DEMUX))
13996 needed_parser = g_strdup("legacyh264parse");
13997 smooth_streaming = TRUE;
14001 needed_parser = g_strdup("h264parse");
14004 else if (g_strrstr(src_demux_caps_str, "video/mpeg"))
14006 needed_parser = g_strdup("mpeg4videoparse");
14008 MMPLAYER_FREEIF(src_demux_caps_str);
14012 parser = __mmplayer_element_create_and_link(player, srcpad, needed_parser);
14013 MMPLAYER_FREEIF(needed_parser);
14017 debug_error("failed to create parser\n");
14021 if (smooth_streaming)
14023 g_object_set (parser, "output-format", 1, NULL); /* NALU/Byte Stream format */
14026 /* update srcpad if parser is created */
14027 pssrcpad = gst_element_get_static_pad(parser, "src");
14032 MMPLAYER_FREEIF(name);
14034 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
14037 debug_error("failed to create queue\n");
14041 /* update srcpad to link with decoder */
14042 qsrcpad = gst_element_get_static_pad(queue, "src");
14045 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
14047 /* assigning queue handle for futher manipulation purpose */
14048 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
14049 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
14051 mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
14052 mainbin[MMPLAYER_M_Q1].gst = queue;
14054 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
14056 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", 0 , NULL);
14057 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-buffers", 2, NULL);
14058 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-bytes", 0, NULL);
14062 if (!MMPLAYER_IS_RTSP_STREAMING(player))
14063 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
14066 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
14068 mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
14069 mainbin[MMPLAYER_M_Q2].gst = queue;
14071 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
14073 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", 0 , NULL);
14074 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-buffers", 2, NULL);
14075 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-bytes", 0, NULL);
14079 if (!MMPLAYER_IS_RTSP_STREAMING(player))
14080 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
14085 debug_error("Not supporting more then two elementary stream\n");
14089 pad = gst_element_get_static_pad(sinkelement, padname);
14093 debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
14094 padname, GST_ELEMENT_NAME(sinkelement) );
14096 pad = gst_element_get_static_pad(sinkelement, "sink");
14099 debug_error("failed to get pad(sink) from %s. \n",
14100 GST_ELEMENT_NAME(sinkelement) );
14105 /* to check the video/audio type set the proper flag*/
14106 const gchar *mime_type = NULL;
14108 srccaps = gst_pad_query_caps(srcpad, NULL);
14112 str = gst_caps_get_structure( srccaps, 0 );
14116 mime_type = gst_structure_get_name(str);
14121 /* link queue and decoder. so, it will be queue - decoder. */
14122 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
14124 gst_object_unref(GST_OBJECT(pad));
14125 debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
14127 /* reconstitute supportable codec */
14128 if (strstr(mime_type, "video"))
14130 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
14132 else if (strstr(mime_type, "audio"))
14134 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
14139 if (strstr(mime_type, "video"))
14141 player->videodec_linked = 1;
14142 debug_msg("player->videodec_linked set to 1\n");
14145 else if (strstr(mime_type, "audio"))
14147 player->audiodec_linked = 1;
14148 debug_msg("player->auddiodec_linked set to 1\n");
14151 gst_object_unref(GST_OBJECT(pad));
14152 gst_caps_unref(GST_CAPS(srccaps));
14156 if ( !MMPLAYER_IS_HTTP_PD(player) )
14158 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
14160 if (MMPLAYER_IS_HTTP_STREAMING(player))
14162 gint64 dur_bytes = 0L;
14163 gchar *file_buffering_path = NULL;
14164 gboolean use_file_buffer = FALSE;
14166 if ( !mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
14168 debug_log("creating http streaming buffering queue\n");
14170 queue = gst_element_factory_make("queue2", "queue2");
14173 debug_error ( "failed to create buffering queue element\n" );
14177 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
14179 debug_error("failed to set state READY to buffering queue\n");
14183 if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
14185 debug_error("failed to add buffering queue\n");
14189 qsinkpad = gst_element_get_static_pad(queue, "sink");
14190 qsrcpad = gst_element_get_static_pad(queue, "src");
14192 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
14194 debug_error("failed to link buffering queue\n");
14200 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
14201 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue;
14203 if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
14205 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
14206 debug_error("fail to get duration.\n");
14210 use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
14211 file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
14219 /* NOTE : we cannot get any duration info from ts container in case of streaming */
14220 if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
14222 __mm_player_streaming_set_queue2(player->streamer,
14225 player->ini.http_max_size_bytes,
14226 player->ini.http_buffering_time,
14228 player->ini.http_buffering_limit,
14230 file_buffering_path,
14231 (guint64)dur_bytes);
14234 MMPLAYER_FREEIF(file_buffering_path);
14239 /* if it is not decoder or */
14240 /* in decoder case any of the video/audio still need to link*/
14241 if(!g_strrstr(klass, "Decoder"))
14244 pad = gst_element_get_static_pad(sinkelement, padname);
14247 debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
14248 padname, GST_ELEMENT_NAME(sinkelement) );
14250 pad = gst_element_get_static_pad(sinkelement, "sink");
14254 debug_error("failed to get pad(sink) from %s. \n",
14255 GST_ELEMENT_NAME(sinkelement) );
14260 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
14262 gst_object_unref(GST_OBJECT(pad));
14263 debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
14267 gst_object_unref(GST_OBJECT(pad));
14270 for(;templlist != NULL; templlist = templlist->next)
14272 padtemplate = templlist->data;
14274 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
14276 if( padtemplate->direction != GST_PAD_SRC ||
14277 padtemplate->presence == GST_PAD_REQUEST )
14280 switch(padtemplate->presence)
14282 case GST_PAD_ALWAYS:
14284 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
14285 GstCaps *caps = gst_pad_query_caps(srcpad, NULL);
14287 /* Check whether caps has many types */
14288 if ( !gst_caps_is_fixed(caps))
14290 debug_log ("always pad but, caps has many types");
14291 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
14292 has_many_types = TRUE;
14296 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
14298 gst_object_unref(GST_OBJECT(srcpad));
14299 gst_caps_unref(GST_CAPS(caps));
14301 debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
14305 gst_caps_unref(GST_CAPS(caps));
14306 gst_object_unref(GST_OBJECT(srcpad));
14312 case GST_PAD_SOMETIMES:
14313 has_dynamic_pads = TRUE;
14321 /* check if player can do start continually */
14322 MMPLAYER_CHECK_CMD_IF_EXIT(player);
14324 if( has_dynamic_pads )
14326 player->have_dynamic_pad = TRUE;
14327 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
14328 G_CALLBACK(__mmplayer_add_new_pad), player);
14330 /* for streaming, more then one typefind will used for each elementary stream
14331 * so this doesn't mean the whole pipeline completion
14333 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
14335 MMPLAYER_SIGNAL_CONNECT( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
14336 G_CALLBACK(__mmplayer_pipeline_complete), player);
14340 if (has_many_types)
14342 GstPad *pad = NULL;
14344 player->has_many_types = has_many_types;
14346 pad = gst_element_get_static_pad(sinkelement, "src");
14347 MMPLAYER_SIGNAL_CONNECT (player, pad, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
14348 gst_object_unref (GST_OBJECT(pad));
14352 /* check if player can do start continually */
14353 MMPLAYER_CHECK_CMD_IF_EXIT(player);
14355 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
14357 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
14363 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
14365 debug_error("failed to set state PAUSED to queue\n");
14371 gst_object_unref (GST_OBJECT(qsrcpad));
14377 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
14379 debug_error("failed to set state PAUSED to queue\n");
14385 gst_object_unref (GST_OBJECT(pssrcpad));
14397 gst_object_unref(GST_OBJECT(qsrcpad));
14399 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
14400 * You need to explicitly set elements to the NULL state before
14401 * dropping the final reference, to allow them to clean up.
14403 gst_element_set_state(queue, GST_STATE_NULL);
14404 /* And, it still has a parent "player".
14405 * You need to let the parent manage the object instead of unreffing the object directly.
14408 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
14409 //gst_object_unref( queue );
14413 gst_caps_unref(GST_CAPS(srccaps));
14418 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
14420 const gchar *klass;
14421 //const gchar *name;
14423 /* we only care about element factories */
14424 if (!GST_IS_ELEMENT_FACTORY(feature))
14427 /* only parsers, demuxers and decoders */
14428 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
14429 //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
14431 if( g_strrstr(klass, "Demux") == NULL &&
14432 g_strrstr(klass, "Codec/Decoder") == NULL &&
14433 g_strrstr(klass, "Depayloader") == NULL &&
14434 g_strrstr(klass, "Parse") == NULL)
14442 static void __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
14444 mm_player_t* player = (mm_player_t*) data;
14445 GstCaps *caps = NULL;
14446 GstStructure *str = NULL;
14451 return_if_fail ( pad )
14452 return_if_fail ( unused )
14453 return_if_fail ( data )
14455 caps = gst_pad_query_caps(pad, NULL);
14459 str = gst_caps_get_structure(caps, 0);
14463 name = gst_structure_get_name(str);
14466 debug_log("name=%s\n", name);
14468 if ( ! __mmplayer_try_to_plug(player, pad, caps) )
14470 debug_error("failed to autoplug for type (%s)\n", name);
14471 gst_caps_unref(caps);
14475 gst_caps_unref(caps);
14477 __mmplayer_pipeline_complete( NULL, (gpointer)player );
14484 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
14488 const char *stream_type;
14489 gchar *version_field = NULL;
14493 return_if_fail ( player );
14494 return_if_fail ( caps );
14496 str = gst_caps_get_structure(caps, 0);
14500 stream_type = gst_structure_get_name(str);
14501 if ( !stream_type )
14505 /* set unlinked mime type for downloadable codec */
14506 if (g_str_has_prefix(stream_type, "video/"))
14508 if (g_str_has_prefix(stream_type, "video/mpeg"))
14510 gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
14511 version_field = MM_PLAYER_MPEG_VNAME;
14513 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
14515 gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
14516 version_field = MM_PLAYER_WMV_VNAME;
14519 else if (g_str_has_prefix(stream_type, "video/x-divx"))
14521 gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
14522 version_field = MM_PLAYER_DIVX_VNAME;
14527 player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
14531 player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
14534 else if (g_str_has_prefix(stream_type, "audio/"))
14536 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
14538 gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
14539 version_field = MM_PLAYER_MPEG_VNAME;
14541 else if (g_str_has_prefix(stream_type, "audio/x-wma"))
14543 gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
14544 version_field = MM_PLAYER_WMA_VNAME;
14549 player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
14553 player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
14560 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
14562 mm_player_t* player = (mm_player_t*) data;
14563 GstCaps *caps = NULL;
14564 GstStructure *str = NULL;
14568 return_if_fail ( player );
14569 return_if_fail ( pad );
14571 GST_OBJECT_LOCK (pad);
14572 if ((caps = gst_pad_get_current_caps(pad)))
14573 gst_caps_ref(caps);
14574 GST_OBJECT_UNLOCK (pad);
14576 if ( NULL == caps )
14578 caps = gst_pad_query_caps(pad, NULL);
14579 if ( !caps ) return;
14582 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
14584 str = gst_caps_get_structure(caps, 0);
14588 name = gst_structure_get_name(str);
14592 player->num_dynamic_pad++;
14593 debug_log("stream count inc : %d\n", player->num_dynamic_pad);
14595 /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
14596 * If want to play it, remove this code.
14598 if (g_strrstr(name, "application"))
14600 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
14602 /* If id3/ape tag comes, keep going */
14603 debug_log("application mime exception : id3/ape tag");
14607 /* Otherwise, we assume that this stream is subtile. */
14608 debug_log(" application mime type pad is closed.");
14612 else if (g_strrstr(name, "audio"))
14614 gint samplerate = 0, channels = 0;
14616 if (player->audiodec_linked)
14618 gst_caps_unref(caps);
14619 debug_log("multi tracks. skip to plug");
14623 /* set stream information */
14624 /* if possible, set it here because the caps is not distrubed by resampler. */
14625 gst_structure_get_int (str, "rate", &samplerate);
14626 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
14628 gst_structure_get_int (str, "channels", &channels);
14629 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
14631 debug_log("audio samplerate : %d channels : %d", samplerate, channels);
14633 else if (g_strrstr(name, "video"))
14636 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
14638 /* don't make video because of not required */
14639 if (stype == MM_DISPLAY_SURFACE_NULL)
14641 debug_log("no video because it's not required");
14645 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
14648 if ( ! __mmplayer_try_to_plug(player, pad, caps) )
14650 debug_error("failed to autoplug for type (%s)", name);
14652 __mmplayer_set_unlinked_mime_type(player, caps);
14655 gst_caps_unref(caps);
14661 /* test API for tuning audio gain. this API should be
14662 * deprecated before the day of final release
14665 _mmplayer_set_volume_tune(MMHandleType hplayer, MMPlayerVolumeType volume)
14667 mm_player_t* player = (mm_player_t*) hplayer;
14668 gint error = MM_ERROR_NONE;
14670 gboolean isMidi = FALSE;
14675 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14676 return_val_if_fail( player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED )
14678 debug_log("clip type=%d(1-midi, 0-others), volume [L]=%d:[R]=%d\n",
14679 player->profile.play_mode, volume.level[0], volume.level[1]);
14681 isMidi = ( player->profile.play_mode == MM_PLAYER_MODE_MIDI ) ? TRUE : FALSE;
14688 /* is it proper volume level? */
14689 for (i = 0; i < MM_VOLUME_CHANNEL_NUM; ++i)
14691 if (volume.level[i] < 0 || volume.level[i] > vol_max) {
14692 debug_log("Invalid Volume level!!!! \n");
14693 return MM_ERROR_INVALID_ARGUMENT;
14699 if ( player->pipeline->mainbin )
14701 GstElement *midi_element = player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst;
14703 if ( midi_element && ( strstr(GST_ELEMENT_NAME(midi_element), "midiparse")) )
14705 debug_log("setting volume (%d) level to midi plugin\n", volume.level[0]);
14707 g_object_set(midi_element, "volume", volume.level[0], NULL);
14713 if ( player->pipeline->audiobin )
14715 GstElement *sink_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
14717 /* Set to Avsysaudiosink element */
14718 if ( sink_element )
14720 gint vol_value = 0;
14721 gboolean mute = FALSE;
14722 vol_value = volume.level[0];
14724 g_object_set(G_OBJECT(sink_element), "tuningvolume", vol_value, NULL);
14726 mute = (vol_value == 0)? TRUE:FALSE;
14728 g_object_set(G_OBJECT(sink_element), "mute", mute, NULL);
14740 __mmplayer_dump_pipeline_state( mm_player_t* player )
14742 GstIterator*iter = NULL;
14743 gboolean done = FALSE;
14745 GValue item = {0, };
14746 GstElement *element = NULL;
14747 GstElementFactory *factory = NULL;
14749 GstState state = GST_STATE_VOID_PENDING;
14750 GstState pending = GST_STATE_VOID_PENDING;
14751 GstClockTime time = 200*GST_MSECOND;
14755 return_val_if_fail ( player &&
14756 player->pipeline &&
14757 player->pipeline->mainbin,
14760 iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) );
14762 if ( iter != NULL )
14765 switch ( gst_iterator_next (iter, &item) )
14767 case GST_ITERATOR_OK:
14768 element = g_value_get_object(&item);
14769 gst_element_get_state(element,&state, &pending,time);
14771 factory = gst_element_get_factory (element) ;
14774 debug_error("%s:%s : From:%s To:%s refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(element) ,
14775 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(element));
14777 g_value_reset (&item);
14779 case GST_ITERATOR_RESYNC:
14780 gst_iterator_resync (iter);
14782 case GST_ITERATOR_ERROR:
14785 case GST_ITERATOR_DONE:
14792 element = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
14794 gst_element_get_state(element,&state, &pending,time);
14796 factory = gst_element_get_factory (element) ;
14800 debug_error("%s:%s : From:%s To:%s refcount : %d\n",
14801 GST_OBJECT_NAME(factory),
14802 GST_ELEMENT_NAME(element),
14803 gst_element_state_get_name(state),
14804 gst_element_state_get_name(pending),
14805 GST_OBJECT_REFCOUNT_VALUE(element) );
14808 g_value_unset(&item);
14811 gst_iterator_free (iter);
14820 __mmplayer_check_subtitle( mm_player_t* player )
14822 MMHandleType attrs = 0;
14823 char *subtitle_uri = NULL;
14827 return_val_if_fail( player, FALSE );
14829 /* get subtitle attribute */
14830 attrs = MMPLAYER_GET_ATTRS(player);
14834 mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
14835 if ( !subtitle_uri || !strlen(subtitle_uri))
14838 debug_log ("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
14839 player->is_external_subtitle_present = TRUE;
14847 __mmplayer_can_extract_pcm( mm_player_t* player )
14849 MMHandleType attrs = 0;
14850 gboolean is_drm = FALSE;
14851 gboolean sound_extraction = FALSE;
14853 return_val_if_fail ( player, FALSE );
14855 attrs = MMPLAYER_GET_ATTRS(player);
14858 debug_error("fail to get attributes.");
14862 /* check file is drm or not */
14863 if (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm"))
14864 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
14866 /* get sound_extraction property */
14867 mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
14869 if ( ! sound_extraction || is_drm )
14871 debug_log("checking pcm extraction mode : %d, drm : %d", sound_extraction, is_drm);
14879 __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error )
14881 MMMessageParamType msg_param;
14882 gchar *msg_src_element;
14886 return_val_if_fail( player, FALSE );
14887 return_val_if_fail( error, FALSE );
14889 /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
14891 memset (&msg_param, 0, sizeof(MMMessageParamType));
14893 if ( error->domain == GST_CORE_ERROR )
14895 msg_param.code = __gst_handle_core_error( player, error->code );
14897 else if ( error->domain == GST_LIBRARY_ERROR )
14899 msg_param.code = __gst_handle_library_error( player, error->code );
14901 else if ( error->domain == GST_RESOURCE_ERROR )
14903 msg_param.code = __gst_handle_resource_error( player, error->code );
14905 else if ( error->domain == GST_STREAM_ERROR )
14907 msg_param.code = __gst_handle_stream_error( player, error, message );
14911 debug_warning("This error domain is not defined.\n");
14913 /* we treat system error as an internal error */
14914 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
14917 if ( message->src )
14919 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
14921 msg_param.data = (void *) error->message;
14923 debug_error("-Msg src : [%s] Domain : [%s] Error : [%s] Code : [%d] is tranlated to error code : [0x%x]\n",
14924 msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg_param.code);
14928 if (msg_param.code == MM_ERROR_NONE)
14931 /* post error to application */
14932 if ( ! player->msg_posted )
14934 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
14935 /* don't post more if one was sent already */
14936 player->msg_posted = TRUE;
14940 debug_log("skip error post because it's sent already.\n");
14949 __mmplayer_handle_streaming_error ( mm_player_t* player, GstMessage * message )
14952 MMMessageParamType msg_param;
14953 gchar *msg_src_element = NULL;
14954 GstStructure *s = NULL;
14955 guint error_id = 0;
14956 gchar *error_string = NULL;
14960 return_val_if_fail ( player, FALSE );
14961 return_val_if_fail ( message, FALSE );
14963 s = malloc( sizeof(GstStructure) );
14964 memcpy ( s, gst_message_get_structure ( message ), sizeof(GstStructure));
14966 if ( !gst_structure_get_uint (s, "error_id", &error_id) )
14967 error_id = MMPLAYER_STREAMING_ERROR_NONE;
14969 switch ( error_id )
14971 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
14972 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
14974 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
14975 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
14977 case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
14978 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
14980 case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
14981 msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
14983 case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
14984 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
14986 case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
14987 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
14989 case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
14990 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
14992 case MMPLAYER_STREAMING_ERROR_INVALID_URL:
14993 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
14995 case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
14996 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
14998 case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
14999 msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
15001 case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
15002 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
15004 case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
15005 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
15007 case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
15008 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
15010 case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
15011 msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
15013 case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
15014 msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
15016 case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
15017 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
15019 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
15020 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
15022 case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
15023 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
15025 case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
15026 msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
15028 case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
15029 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
15031 case MMPLAYER_STREAMING_ERROR_GONE:
15032 msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
15034 case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
15035 msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
15037 case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
15038 msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
15040 case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
15041 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
15043 case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
15044 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
15046 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
15047 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
15049 case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
15050 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
15052 case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
15053 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
15055 case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
15056 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
15058 case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
15059 msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
15061 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
15062 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
15064 case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
15065 msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
15067 case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
15068 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
15070 case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
15071 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
15073 case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
15074 msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
15076 case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
15077 msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
15079 case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
15080 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
15082 case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
15083 msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
15085 case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
15086 msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
15088 case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
15089 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
15091 case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
15092 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
15094 case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
15095 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
15097 case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
15098 msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
15100 case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
15101 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
15103 case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
15104 msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
15108 MMPLAYER_FREEIF(s);
15109 return MM_ERROR_PLAYER_STREAMING_FAIL;
15113 error_string = g_strdup(gst_structure_get_string (s, "error_string"));
15114 if ( error_string )
15115 msg_param.data = (void *) error_string;
15117 if ( message->src )
15119 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
15121 debug_error("-Msg src : [%s] Code : [%x] Error : [%s] \n",
15122 msg_src_element, msg_param.code, (char*)msg_param.data );
15125 /* post error to application */
15126 if ( ! player->msg_posted )
15128 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
15130 /* don't post more if one was sent already */
15131 player->msg_posted = TRUE;
15135 debug_log("skip error post because it's sent already.\n");
15138 MMPLAYER_FREEIF(s);
15140 g_free(error_string);
15147 __gst_handle_core_error( mm_player_t* player, int code )
15149 gint trans_err = MM_ERROR_NONE;
15153 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15157 case GST_CORE_ERROR_MISSING_PLUGIN:
15158 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15159 case GST_CORE_ERROR_STATE_CHANGE:
15160 case GST_CORE_ERROR_SEEK:
15161 case GST_CORE_ERROR_NOT_IMPLEMENTED:
15162 case GST_CORE_ERROR_FAILED:
15163 case GST_CORE_ERROR_TOO_LAZY:
15164 case GST_CORE_ERROR_PAD:
15165 case GST_CORE_ERROR_THREAD:
15166 case GST_CORE_ERROR_NEGOTIATION:
15167 case GST_CORE_ERROR_EVENT:
15168 case GST_CORE_ERROR_CAPS:
15169 case GST_CORE_ERROR_TAG:
15170 case GST_CORE_ERROR_CLOCK:
15171 case GST_CORE_ERROR_DISABLED:
15173 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
15183 __gst_handle_library_error( mm_player_t* player, int code )
15185 gint trans_err = MM_ERROR_NONE;
15189 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15193 case GST_LIBRARY_ERROR_FAILED:
15194 case GST_LIBRARY_ERROR_TOO_LAZY:
15195 case GST_LIBRARY_ERROR_INIT:
15196 case GST_LIBRARY_ERROR_SHUTDOWN:
15197 case GST_LIBRARY_ERROR_SETTINGS:
15198 case GST_LIBRARY_ERROR_ENCODE:
15200 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
15211 __gst_handle_resource_error( mm_player_t* player, int code )
15213 gint trans_err = MM_ERROR_NONE;
15217 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15221 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
15222 trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
15224 case GST_RESOURCE_ERROR_NOT_FOUND:
15225 case GST_RESOURCE_ERROR_OPEN_READ:
15226 if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
15227 || MMPLAYER_IS_RTSP_STREAMING(player))
15229 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
15232 case GST_RESOURCE_ERROR_READ:
15233 if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
15234 || MMPLAYER_IS_RTSP_STREAMING(player))
15236 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
15239 case GST_RESOURCE_ERROR_WRITE:
15240 case GST_RESOURCE_ERROR_FAILED:
15241 case GST_RESOURCE_ERROR_SEEK:
15242 case GST_RESOURCE_ERROR_TOO_LAZY:
15243 case GST_RESOURCE_ERROR_BUSY:
15244 case GST_RESOURCE_ERROR_OPEN_WRITE:
15245 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
15246 case GST_RESOURCE_ERROR_CLOSE:
15247 case GST_RESOURCE_ERROR_SYNC:
15248 case GST_RESOURCE_ERROR_SETTINGS:
15250 trans_err = MM_ERROR_PLAYER_INTERNAL;
15261 __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message )
15263 gint trans_err = MM_ERROR_NONE;
15267 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
15268 return_val_if_fail( error, MM_ERROR_INVALID_ARGUMENT );
15269 return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
15271 switch ( error->code )
15273 case GST_STREAM_ERROR_FAILED:
15274 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
15275 case GST_STREAM_ERROR_DECODE:
15276 case GST_STREAM_ERROR_WRONG_TYPE:
15277 case GST_STREAM_ERROR_DECRYPT:
15278 case GST_STREAM_ERROR_DECRYPT_NOKEY:
15279 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
15280 trans_err = __gst_transform_gsterror( player, message, error );
15283 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
15284 case GST_STREAM_ERROR_TOO_LAZY:
15285 case GST_STREAM_ERROR_ENCODE:
15286 case GST_STREAM_ERROR_DEMUX:
15287 case GST_STREAM_ERROR_MUX:
15288 case GST_STREAM_ERROR_FORMAT:
15290 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
15299 /* NOTE : decide gstreamer state whether there is some playable track or not. */
15301 __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error )
15303 gchar *src_element_name = NULL;
15304 GstElement *src_element = NULL;
15305 GstElementFactory *factory = NULL;
15306 const gchar* klass = NULL;
15311 return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
15312 return_val_if_fail ( message->src, MM_ERROR_INVALID_ARGUMENT );
15313 return_val_if_fail ( error, MM_ERROR_INVALID_ARGUMENT );
15315 src_element = GST_ELEMENT_CAST(message->src);
15316 if ( !src_element )
15317 goto INTERNAL_ERROR;
15319 src_element_name = GST_ELEMENT_NAME(src_element);
15320 if ( !src_element_name )
15321 goto INTERNAL_ERROR;
15323 factory = gst_element_get_factory(src_element);
15325 goto INTERNAL_ERROR;
15327 klass = gst_element_factory_get_klass(factory);
15329 goto INTERNAL_ERROR;
15331 debug_log("error code=%d, msg=%s, src element=%s, class=%s\n",
15332 error->code, error->message, src_element_name, klass);
15336 if (player->selector) {
15337 int msg_src_pos = 0;
15338 gint active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
15339 debug_log ("current active pad index -%d", active_pad_index);
15341 if (src_element_name) {
15344 if (player->audio_decoders) {
15345 GList *adec = player->audio_decoders;
15346 for ( ;adec ; adec = g_list_next(adec)) {
15347 gchar *name = adec->data;
15349 debug_log("found audio decoder name = %s", name);
15350 if (g_strrstr(name, src_element_name)) {
15357 debug_log("active pad = %d, error src index = %d", active_pad_index, msg_src_pos);
15360 if (active_pad_index != msg_src_pos) {
15361 debug_log("skip error because error is posted from no activated track");
15362 return MM_ERROR_NONE;
15368 switch ( error->code )
15370 case GST_STREAM_ERROR_DECODE:
15372 /* Demuxer can't parse one track because it's corrupted.
15373 * So, the decoder for it is not linked.
15374 * But, it has one playable track.
15376 if ( g_strrstr(klass, "Demux") )
15378 if ( player->can_support_codec == FOUND_PLUGIN_VIDEO )
15380 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
15382 else if ( player->can_support_codec == FOUND_PLUGIN_AUDIO )
15384 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15388 if ( player->pipeline->audiobin ) // PCM
15390 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15394 goto CODEC_NOT_FOUND;
15398 return MM_ERROR_PLAYER_INVALID_STREAM;
15402 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
15403 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
15404 case GST_STREAM_ERROR_WRONG_TYPE:
15405 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15407 case GST_STREAM_ERROR_FAILED:
15409 /* Decoder Custom Message */
15410 if ( strstr(error->message, "ongoing") )
15412 if ( strncasecmp(klass, "audio", 5) )
15414 if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) )
15416 debug_log("Video can keep playing.\n");
15417 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
15421 goto CODEC_NOT_FOUND;
15425 else if ( strncasecmp(klass, "video", 5) )
15427 if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) )
15429 debug_log("Audio can keep playing.\n");
15430 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15434 goto CODEC_NOT_FOUND;
15438 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15442 case GST_STREAM_ERROR_DECRYPT:
15443 case GST_STREAM_ERROR_DECRYPT_NOKEY:
15445 debug_error("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
15447 if ( strstr(error->message, "rights expired") )
15449 return MM_ERROR_PLAYER_DRM_EXPIRED;
15451 else if ( strstr(error->message, "no rights") )
15453 return MM_ERROR_PLAYER_DRM_NO_LICENSE;
15455 else if ( strstr(error->message, "has future rights") )
15457 return MM_ERROR_PLAYER_DRM_FUTURE_USE;
15459 else if ( strstr(error->message, "opl violation") )
15461 return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
15463 return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
15473 return MM_ERROR_PLAYER_INVALID_STREAM;
15476 return MM_ERROR_PLAYER_INTERNAL;
15479 debug_log("not found any available codec. Player should be destroyed.\n");
15480 return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
15484 __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms )
15486 return_if_fail( player );
15489 /* post now if delay is zero */
15490 if ( delay_in_ms == 0 || player->set_mode.pcm_extraction)
15492 debug_log("eos delay is zero. posting EOS now\n");
15493 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15495 if ( player->set_mode.pcm_extraction )
15496 __mmplayer_cancel_eos_timer(player);
15501 /* cancel if existing */
15502 __mmplayer_cancel_eos_timer( player );
15504 /* init new timeout */
15505 /* NOTE : consider give high priority to this timer */
15506 debug_log("posting EOS message after [%d] msec\n", delay_in_ms);
15508 player->eos_timer = g_timeout_add( delay_in_ms,
15509 __mmplayer_eos_timer_cb, player );
15511 player->context.global_default = g_main_context_default ();
15512 debug_log("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
15514 /* check timer is valid. if not, send EOS now */
15515 if ( player->eos_timer == 0 )
15517 debug_warning("creating timer for delayed EOS has failed. sending EOS now\n");
15518 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15523 __mmplayer_cancel_eos_timer( mm_player_t* player )
15525 return_if_fail( player );
15527 if ( player->eos_timer )
15529 debug_log("cancel eos timer");
15530 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
15531 player->eos_timer = 0;
15538 __mmplayer_eos_timer_cb(gpointer u_data)
15540 mm_player_t* player = NULL;
15541 player = (mm_player_t*) u_data;
15543 return_val_if_fail( player, FALSE );
15545 if ( player->play_count > 1 )
15547 gint ret_value = 0;
15548 ret_value = __gst_set_position( player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
15549 if (ret_value == MM_ERROR_NONE)
15551 MMHandleType attrs = 0;
15552 attrs = MMPLAYER_GET_ATTRS(player);
15554 /* we successeded to rewind. update play count and then wait for next EOS */
15555 player->play_count--;
15557 mm_attrs_set_int_by_name(attrs, "profile_play_count", player->play_count);
15558 mmf_attrs_commit ( attrs );
15562 debug_error("seeking to 0 failed in repeat play");
15568 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15571 /* we are returning FALSE as we need only one posting */
15575 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force)
15577 gint antishock = FALSE;
15578 MMHandleType attrs = 0;
15582 return_if_fail ( player && player->pipeline );
15584 /* It should be passed for video only clip */
15585 if ( ! player->pipeline->audiobin )
15588 if ( ( g_strrstr(player->ini.name_of_audiosink, "avsysaudiosink")) )
15590 attrs = MMPLAYER_GET_ATTRS(player);
15593 debug_error("fail to get attributes.\n");
15597 mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock);
15599 if (player->sm.antishock) {
15601 player->sm.antishock = 0;
15604 debug_log("setting antishock as (%d)\n", antishock);
15606 if ( disable_by_force )
15608 debug_log("but, antishock is disabled by force when is seeked\n");
15613 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "fadeup", antishock, NULL);
15623 __mmplayer_link_decoder( mm_player_t* player, GstPad *srcpad)
15625 const gchar* name = NULL;
15626 GstStructure* str = NULL;
15627 GstCaps* srccaps = NULL;
15631 return_val_if_fail( player, FALSE );
15632 return_val_if_fail ( srcpad, FALSE );
15634 /* to check any of the decoder (video/audio) need to be linked to parser*/
15635 srccaps = gst_pad_query_caps( srcpad, NULL);
15639 str = gst_caps_get_structure( srccaps, 0 );
15643 name = gst_structure_get_name(str);
15647 if (strstr(name, "video"))
15649 if(player->videodec_linked)
15651 debug_msg("Video decoder already linked\n");
15655 if (strstr(name, "audio"))
15657 if(player->audiodec_linked)
15659 debug_msg("Audio decoder already linked\n");
15664 gst_caps_unref( srccaps );
15672 gst_caps_unref( srccaps );
15678 __mmplayer_link_sink( mm_player_t* player , GstPad *srcpad)
15680 const gchar* name = NULL;
15681 GstStructure* str = NULL;
15682 GstCaps* srccaps = NULL;
15686 return_val_if_fail ( player, FALSE );
15687 return_val_if_fail ( srcpad, FALSE );
15689 /* to check any of the decoder (video/audio) need to be linked to parser*/
15690 srccaps = gst_pad_query_caps( srcpad, NULL );
15694 str = gst_caps_get_structure( srccaps, 0 );
15698 name = gst_structure_get_name(str);
15702 if (strstr(name, "video"))
15704 if(player->videosink_linked)
15706 debug_msg("Video Sink already linked\n");
15710 if (strstr(name, "audio"))
15712 if(player->audiosink_linked)
15714 debug_msg("Audio Sink already linked\n");
15718 if (strstr(name, "text"))
15720 if(player->textsink_linked)
15722 debug_msg("Text Sink already linked\n");
15727 gst_caps_unref( srccaps );
15732 //return (!player->videosink_linked || !player->audiosink_linked);
15736 gst_caps_unref( srccaps );
15742 /* sending event to one of sinkelements */
15744 __gst_send_event_to_sink( mm_player_t* player, GstEvent* event )
15746 GstEvent * event2 = NULL;
15747 GList *sinks = NULL;
15748 gboolean res = FALSE;
15751 return_val_if_fail( player, FALSE );
15752 return_val_if_fail ( event, FALSE );
15754 if ( player->play_subtitle && !player->use_textoverlay)
15755 event2 = gst_event_copy((const GstEvent *)event);
15757 sinks = player->sink_elements;
15760 GstElement *sink = GST_ELEMENT_CAST (sinks->data);
15762 if (GST_IS_ELEMENT(sink))
15764 /* keep ref to the event */
15765 gst_event_ref (event);
15767 if ( (res = gst_element_send_event (sink, event)) )
15769 debug_log("sending event[%s] to sink element [%s] success!\n",
15770 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
15772 /* rtsp case, asyn_done is not called after seek during pause state */
15773 if (MMPLAYER_IS_RTSP_STREAMING(player))
15775 if (strstr(GST_EVENT_TYPE_NAME(event), "seek"))
15777 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
15779 debug_log("RTSP seek completed, after pause state..\n");
15780 player->doing_seek = FALSE;
15781 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
15788 if( MMPLAYER_IS_ES_BUFF_SRC(player))
15790 sinks = g_list_next (sinks);
15798 debug_log("sending event[%s] to sink element [%s] failed. try with next one.\n",
15799 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
15802 sinks = g_list_next (sinks);
15807 request pad name = sink0;
15809 request pad name = sink1; // external
15812 /* Note : Textbin is not linked to the video or audio bin.
15813 * It needs to send the event to the text sink seperatelly.
15815 if ( player->play_subtitle && !player->use_textoverlay)
15817 GstElement *text_sink = GST_ELEMENT_CAST (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
15819 if (GST_IS_ELEMENT(text_sink))
15821 /* keep ref to the event */
15822 gst_event_ref (event2);
15824 if ( (res != gst_element_send_event (text_sink, event2)) )
15826 debug_error("sending event[%s] to subtitle sink element [%s] failed!\n",
15827 GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
15831 debug_log("sending event[%s] to subtitle sink element [%s] success!\n",
15832 GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
15835 gst_event_unref (event2);
15839 gst_event_unref (event);
15847 __mmplayer_add_sink( mm_player_t* player, GstElement* sink )
15851 return_if_fail ( player );
15852 return_if_fail ( sink );
15854 player->sink_elements =
15855 g_list_append(player->sink_elements, sink);
15861 __mmplayer_del_sink( mm_player_t* player, GstElement* sink )
15865 return_if_fail ( player );
15866 return_if_fail ( sink );
15868 player->sink_elements =
15869 g_list_remove(player->sink_elements, sink);
15875 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
15876 GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
15877 gint64 cur, GstSeekType stop_type, gint64 stop )
15879 GstEvent* event = NULL;
15880 gboolean result = FALSE;
15884 return_val_if_fail( player, FALSE );
15886 __mmplayer_drop_subtitle(player, FALSE);
15888 event = gst_event_new_seek (rate, format, flags, cur_type,
15889 cur, stop_type, stop);
15891 result = __gst_send_event_to_sink( player, event );
15898 /* NOTE : be careful with calling this api. please refer to below glib comment
15899 * glib comment : Note that there is a bug in GObject that makes this function much
15900 * less useful than it might seem otherwise. Once gobject is disposed, the callback
15901 * will no longer be called, but, the signal handler is not currently disconnected.
15902 * If the instance is itself being freed at the same time than this doesn't matter,
15903 * since the signal will automatically be removed, but if instance persists,
15904 * then the signal handler will leak. You should not remove the signal yourself
15905 * because in a future versions of GObject, the handler will automatically be
15908 * It's possible to work around this problem in a way that will continue to work
15909 * with future versions of GObject by checking that the signal handler is still
15910 * connected before disconnected it:
15912 * if (g_signal_handler_is_connected (instance, id))
15913 * g_signal_handler_disconnect (instance, id);
15916 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
15918 GList* sig_list = NULL;
15919 MMPlayerSignalItem* item = NULL;
15923 return_if_fail( player );
15925 debug_log("release signals type : %d", type);
15927 if ((type < MM_PLAYER_SIGNAL_TYPE_AUTOPLUG) || (type >= MM_PLAYER_SIGNAL_TYPE_ALL))
15929 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
15930 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
15931 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
15932 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
15933 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
15937 sig_list = player->signals[type];
15939 for ( ; sig_list; sig_list = sig_list->next )
15941 item = sig_list->data;
15943 if ( item && item->obj && GST_IS_ELEMENT(item->obj) )
15945 if ( g_signal_handler_is_connected ( item->obj, item->sig ) )
15947 g_signal_handler_disconnect ( item->obj, item->sig );
15951 MMPLAYER_FREEIF( item );
15954 g_list_free ( player->signals[type] );
15955 player->signals[type] = NULL;
15962 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
15964 mm_player_t* player = 0;
15965 int prev_display_surface_type = 0;
15966 void *prev_display_overlay = NULL;
15967 const gchar *klass = NULL;
15968 gchar *cur_videosink_name = NULL;
15971 int num_of_dec = 2; /* DEC1, DEC2 */
15975 return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
15976 return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
15978 player = MM_PLAYER_CAST(handle);
15980 if (surface_type < MM_DISPLAY_SURFACE_X && surface_type > MM_DISPLAY_SURFACE_EVAS)
15982 debug_error("Not support this surface type(%d) for changing vidoesink", surface_type);
15984 return MM_ERROR_INVALID_ARGUMENT;
15987 /* load previous attributes */
15990 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &prev_display_surface_type);
15991 mm_attrs_get_data_by_name (player->attrs, "display_overlay", &prev_display_overlay);
15992 debug_log("[0: X surface, 1: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
15993 if (prev_display_surface_type == surface_type)
15995 debug_log("incoming display surface type is same as previous one, do nothing..");
15997 return MM_ERROR_NONE;
16002 debug_error("failed to load attributes");
16004 return MM_ERROR_PLAYER_INTERNAL;
16007 /* check videosink element is created */
16008 if (!player->pipeline || !player->pipeline->videobin ||
16009 !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
16011 debug_log("videosink element is not yet ready");
16013 /* videobin is not created yet, so we just set attributes related to display surface */
16014 debug_log("store display attribute for given surface type(%d)", surface_type);
16015 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
16016 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
16017 if ( mmf_attrs_commit ( player->attrs ) )
16019 debug_error("failed to commit attribute");
16021 return MM_ERROR_PLAYER_INTERNAL;
16024 return MM_ERROR_NONE;
16028 /* get player command status */
16029 if ( !(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE) )
16031 debug_error("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command",player->cmd);
16033 return MM_ERROR_PLAYER_INVALID_STATE;
16036 /* get a current videosink name */
16037 cur_videosink_name = GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
16039 /* surface change */
16040 for ( i = 0 ; i < num_of_dec ; i++)
16042 if ( player->pipeline->mainbin &&
16043 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst )
16045 klass = gst_element_factory_get_klass( gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) );
16046 if ((g_strrstr(klass, "Codec/Decoder/Video")))
16048 if ( !strncmp(cur_videosink_name, "x", 1) && (surface_type == MM_DISPLAY_SURFACE_EVAS) )
16050 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_evas, surface_type, display_overlay);
16057 debug_warning("success to changing display surface(%d)",surface_type);
16059 return MM_ERROR_NONE;
16062 else if (!strncmp(cur_videosink_name, "evas", 4) && (surface_type == MM_DISPLAY_SURFACE_X) )
16064 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_x, surface_type, display_overlay);
16071 debug_warning("success to changing display surface(%d)",surface_type);
16073 return MM_ERROR_NONE;
16078 debug_error("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface",surface_type, cur_videosink_name);
16079 ret = MM_ERROR_PLAYER_INTERNAL;
16088 /* rollback to previous attributes */
16089 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", prev_display_surface_type);
16090 mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(prev_display_overlay));
16091 if ( mmf_attrs_commit ( player->attrs ) )
16093 debug_error("failed to commit attributes to rollback");
16095 return MM_ERROR_PLAYER_INTERNAL;
16101 /* NOTE : It does not support some use cases, eg using colorspace converter */
16103 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
16105 GstPad *src_pad_dec = NULL;
16106 GstPad *sink_pad_videosink = NULL;
16107 GstPad *sink_pad_videobin = NULL;
16108 GstClock *clock = NULL;
16109 MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
16110 int ret = MM_ERROR_NONE;
16111 gboolean is_audiobin_created = TRUE;
16115 return_val_if_fail(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
16116 return_val_if_fail(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
16117 return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
16119 debug_log("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
16120 debug_log("surface type(%d), display overlay(%x)", surface_type, display_overlay);
16122 /* get information whether if audiobin is created */
16123 if ( !player->pipeline->audiobin ||
16124 !player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
16126 debug_warning("audiobin is null, this video content may not have audio data");
16127 is_audiobin_created = FALSE;
16130 /* get current state of player */
16131 previous_state = MMPLAYER_CURRENT_STATE(player);
16132 debug_log("previous state(%d)", previous_state);
16135 /* get src pad of decoder and block it */
16136 src_pad_dec = gst_element_get_static_pad (GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
16139 debug_error("failed to get src pad from decode in mainbin");
16140 return MM_ERROR_PLAYER_INTERNAL;
16143 if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
16145 debug_warning("trying to block pad(video)");
16146 // if (!gst_pad_set_blocked (src_pad_dec, TRUE))
16147 gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
16151 debug_error("failed to set block pad(video)");
16152 return MM_ERROR_PLAYER_INTERNAL;
16154 debug_warning("pad is blocked(video)");
16158 /* no data flows, so no need to do pad_block */
16159 if (player->doing_seek) {
16160 debug_warning("not completed seek(%d), do nothing", player->doing_seek);
16162 debug_log("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
16166 if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
16167 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin))))
16169 debug_error("failed to remove previous ghost_pad for videobin");
16170 return MM_ERROR_PLAYER_INTERNAL;
16173 /* change state of videobin to NULL */
16174 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
16175 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
16176 if (ret != GST_STATE_CHANGE_SUCCESS)
16178 debug_error("failed to change state of videobin to NULL");
16179 return MM_ERROR_PLAYER_INTERNAL;
16182 /* unlink between decoder and videobin and remove previous videosink from videobin */
16183 GST_ELEMENT_UNLINK(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst),GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
16184 if ( !gst_bin_remove (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst)) )
16186 debug_error("failed to remove former videosink from videobin");
16187 return MM_ERROR_PLAYER_INTERNAL;
16190 __mmplayer_del_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
16192 /* create a new videosink and add it to videobin */
16193 player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, videosink_element);
16194 gst_bin_add (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
16195 __mmplayer_add_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
16196 g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
16198 /* save attributes */
16201 /* set a new display surface type */
16202 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
16203 /* set a new diplay overlay */
16204 switch (surface_type)
16206 case MM_DISPLAY_SURFACE_X:
16207 debug_log("save attributes related to display surface to X : xid = %d", *(int*)display_overlay);
16208 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
16210 case MM_DISPLAY_SURFACE_EVAS:
16211 debug_log("save attributes related to display surface to EVAS : evas image object = %x", display_overlay);
16212 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
16215 debug_error("invalid type(%d) for changing display surface",surface_type);
16217 return MM_ERROR_INVALID_ARGUMENT;
16219 if ( mmf_attrs_commit ( player->attrs ) )
16221 debug_error("failed to commit");
16223 return MM_ERROR_PLAYER_INTERNAL;
16228 debug_error("player->attrs is null, failed to save attributes");
16230 return MM_ERROR_PLAYER_INTERNAL;
16233 /* update video param */
16234 if ( MM_ERROR_NONE != _mmplayer_update_video_param( player ) )
16236 debug_error("failed to update video param");
16237 return MM_ERROR_PLAYER_INTERNAL;
16240 /* change state of videobin to READY */
16241 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
16242 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
16243 if (ret != GST_STATE_CHANGE_SUCCESS)
16245 debug_error("failed to change state of videobin to READY");
16246 return MM_ERROR_PLAYER_INTERNAL;
16249 /* change ghostpad */
16250 sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
16251 if ( !sink_pad_videosink )
16253 debug_error("failed to get sink pad from videosink element");
16254 return MM_ERROR_PLAYER_INTERNAL;
16256 player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
16257 if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE))
16259 debug_error("failed to set active to ghost_pad");
16260 return MM_ERROR_PLAYER_INTERNAL;
16262 if ( FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
16264 debug_error("failed to change ghostpad for videobin");
16265 return MM_ERROR_PLAYER_INTERNAL;
16267 gst_object_unref(sink_pad_videosink);
16269 /* link decoder with videobin */
16270 sink_pad_videobin = gst_element_get_static_pad( GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
16271 if ( !sink_pad_videobin )
16273 debug_error("failed to get sink pad from videobin");
16274 return MM_ERROR_PLAYER_INTERNAL;
16276 if ( GST_PAD_LINK_OK != GST_PAD_LINK(src_pad_dec, sink_pad_videobin) )
16278 debug_error("failed to link");
16279 return MM_ERROR_PLAYER_INTERNAL;
16281 gst_object_unref(sink_pad_videobin);
16283 /* clock setting for a new videosink plugin */
16284 /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
16285 so we set it from audiosink plugin or pipeline(system clock) */
16286 if (!is_audiobin_created)
16288 debug_warning("audiobin is not created, get clock from pipeline..");
16289 clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
16293 clock = GST_ELEMENT_CLOCK (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
16298 GstClockTime base_time;
16299 debug_log("set the clock to videosink");
16300 gst_element_set_clock (GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
16301 clock = GST_ELEMENT_CLOCK (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
16304 debug_log("got clock of videosink");
16305 now = gst_clock_get_time ( clock );
16306 base_time = GST_ELEMENT_CAST (player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
16307 debug_log ("at time %" GST_TIME_FORMAT ", base %"
16308 GST_TIME_FORMAT, GST_TIME_ARGS (now), GST_TIME_ARGS (base_time));
16312 debug_error("failed to get clock of videosink after setting clock");
16313 return MM_ERROR_PLAYER_INTERNAL;
16318 debug_warning("failed to get clock, maybe it is the time before first playing");
16321 if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
16323 /* change state of videobin to PAUSED */
16324 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
16325 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
16326 if (ret != GST_STATE_CHANGE_FAILURE)
16328 debug_warning("change state of videobin to PLAYING, ret(%d)", ret);
16332 debug_error("failed to change state of videobin to PLAYING");
16333 return MM_ERROR_PLAYER_INTERNAL;
16336 /* release blocked and unref src pad of video decoder */
16338 if (!gst_pad_set_blocked (src_pad_dec, FALSE))
16340 debug_error("failed to set pad blocked FALSE(video)");
16341 return MM_ERROR_PLAYER_INTERNAL;
16344 debug_warning("pad is unblocked(video)");
16348 if (player->doing_seek) {
16349 debug_warning("not completed seek(%d)", player->doing_seek);
16351 /* change state of videobin to PAUSED */
16352 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
16353 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
16354 if (ret != GST_STATE_CHANGE_FAILURE)
16356 debug_warning("change state of videobin to PAUSED, ret(%d)", ret);
16360 debug_error("failed to change state of videobin to PLAYING");
16361 return MM_ERROR_PLAYER_INTERNAL;
16364 /* already skipped pad block */
16365 debug_log("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
16368 /* do get/set position for new videosink plugin */
16370 unsigned long position = 0;
16371 gint64 pos_msec = 0;
16373 debug_log("do get/set position for new videosink plugin");
16374 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
16376 debug_error("failed to get position");
16377 return MM_ERROR_PLAYER_INTERNAL;
16379 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
16380 /* accurate seek */
16381 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE ))
16383 debug_error("failed to set position");
16384 return MM_ERROR_PLAYER_INTERNAL;
16387 /* key unit seek */
16388 pos_msec = position * G_GINT64_CONSTANT(1000000);
16389 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
16390 GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT ),
16391 GST_SEEK_TYPE_SET, pos_msec,
16392 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
16395 debug_error("failed to set position");
16396 return MM_ERROR_PLAYER_INTERNAL;
16403 gst_object_unref (src_pad_dec);
16405 debug_log("success to change sink");
16409 return MM_ERROR_NONE;
16413 /* Note : if silent is true, then subtitle would not be displayed. :*/
16414 int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent)
16416 mm_player_t* player = (mm_player_t*) hplayer;
16420 /* check player handle */
16421 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16423 player->set_mode.subtitle_off = silent;
16425 debug_log("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
16429 return MM_ERROR_NONE;
16432 int _mmplayer_remove_audio_parser_decoder(mm_player_t* player,GstPad *inpad)
16434 int result = MM_ERROR_NONE;
16435 GstPad *peer = NULL,*pad = NULL;
16436 GstElement *Element = NULL;
16437 MMPlayerGstElement* mainbin = NULL;
16438 mainbin = player->pipeline->mainbin;
16441 if(!gst_pad_set_blocked(inpad,TRUE))
16443 result = MM_ERROR_PLAYER_INTERNAL;
16447 gst_pad_add_probe(inpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
16450 /*Getting pad connected to demuxer audio pad */
16451 peer = gst_pad_get_peer(inpad);
16452 /* Disconnecting Demuxer and its peer plugin [audio] */
16455 if(!gst_pad_unlink(inpad,peer))
16457 result = MM_ERROR_PLAYER_INTERNAL;
16463 result = MM_ERROR_PLAYER_INTERNAL;
16466 /*Removing elements between Demuxer and audiobin*/
16467 while(peer != NULL)
16469 gchar *Element_name = NULL;
16470 gchar *factory_name = NULL;
16471 GList *elements = NULL;
16472 GstElementFactory *factory = NULL;
16473 /*Getting peer element*/
16474 Element = gst_pad_get_parent_element(peer);
16475 if(Element == NULL)
16477 gst_object_unref(peer);
16478 result = MM_ERROR_PLAYER_INTERNAL;
16482 Element_name = gst_element_get_name(Element);
16483 factory = gst_element_get_factory(Element);
16484 /*checking the element is audio bin*/
16485 if(!strcmp(Element_name,"audiobin"))
16487 gst_object_unref(peer);
16488 result = MM_ERROR_NONE;
16489 g_free(Element_name);
16492 factory_name = GST_OBJECT_NAME(factory);
16493 pad = gst_element_get_static_pad(Element,"src");
16496 result = MM_ERROR_PLAYER_INTERNAL;
16497 g_free(Element_name);
16500 gst_object_unref(peer);
16501 peer = gst_pad_get_peer(pad);
16504 if(!gst_pad_unlink(pad,peer))
16506 gst_object_unref(peer);
16507 gst_object_unref(pad);
16508 result = MM_ERROR_PLAYER_INTERNAL;
16509 g_free(Element_name);
16513 elements = player->parsers;
16514 /* Removing the element form the list*/
16515 for ( ; elements; elements = g_list_next(elements))
16517 Element_name = elements->data;
16518 if(g_strrstr(Element_name,factory_name))
16520 player->parsers = g_list_remove(player->parsers,elements->data);
16523 gst_element_set_state(Element,GST_STATE_NULL);
16524 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),Element);
16525 gst_object_unref(pad);
16526 if(Element == mainbin[MMPLAYER_M_Q1].gst)
16528 mainbin[MMPLAYER_M_Q1].gst = NULL;
16530 else if(Element == mainbin[MMPLAYER_M_Q2].gst)
16532 mainbin[MMPLAYER_M_Q2].gst = NULL;
16534 else if(Element == mainbin[MMPLAYER_M_DEC1].gst)
16536 mainbin[MMPLAYER_M_DEC1].gst = NULL;
16538 else if(Element == mainbin[MMPLAYER_M_DEC2].gst)
16540 mainbin[MMPLAYER_M_DEC2].gst = NULL;
16542 gst_object_unref(Element);
16548 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
16550 MMPlayerGstElement* mainbin = NULL;
16551 MMPlayerGstElement* textbin = NULL;
16552 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
16553 GstState current_state = GST_STATE_VOID_PENDING;
16554 GstState element_state = GST_STATE_VOID_PENDING;
16555 GstState element_pending_state = GST_STATE_VOID_PENDING;
16557 GstEvent *event = NULL;
16558 int result = MM_ERROR_NONE;
16560 GstClock *curr_clock = NULL;
16561 GstClockTime base_time, start_time, curr_time;
16566 /* check player handle */
16567 return_val_if_fail ( player && player->pipeline , MM_ERROR_PLAYER_NOT_INITIALIZED);
16569 if (!(player->pipeline->mainbin) || !(player->pipeline->textbin))
16571 debug_error("Pipeline is not in proper state\n");
16572 result = MM_ERROR_PLAYER_NOT_INITIALIZED;
16576 mainbin = player->pipeline->mainbin;
16577 textbin = player->pipeline->textbin;
16579 current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
16581 // sync clock with current pipeline
16582 curr_clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
16583 curr_time = gst_clock_get_time (curr_clock);
16585 base_time = gst_element_get_base_time (GST_ELEMENT_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
16586 start_time = gst_element_get_start_time (GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
16588 debug_log ("base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
16589 GST_TIME_ARGS (base_time), GST_TIME_ARGS (start_time), GST_TIME_ARGS (curr_time));
16591 if (current_state > GST_STATE_READY)
16593 // sync state with current pipeline
16594 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
16595 gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_PAUSED);
16596 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
16598 ret = gst_element_get_state (mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
16599 if ( GST_STATE_CHANGE_FAILURE == ret )
16601 debug_error("fail to state change.\n");
16605 gst_element_set_base_time (textbin[MMPLAYER_T_BIN].gst, base_time);
16606 gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
16610 gst_element_set_clock (textbin[MMPLAYER_T_BIN].gst, curr_clock);
16611 gst_object_unref (curr_clock);
16614 // seek to current position
16615 if (!gst_element_query_position (mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time))
16617 result = MM_ERROR_PLAYER_INVALID_STATE;
16618 debug_error("gst_element_query_position failed, invalid state\n");
16622 debug_log("seek time = %lld\n", time);
16624 event = gst_event_new_seek (1.0, 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);
16627 __gst_send_event_to_sink(player, event);
16631 result = MM_ERROR_PLAYER_INTERNAL;
16632 debug_error("gst_event_new_seek failed\n");
16636 // sync state with current pipeline
16637 gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
16638 gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
16639 gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
16646 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
16648 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
16649 GstState current_state = GST_STATE_VOID_PENDING;
16651 MMHandleType attrs = 0;
16652 MMPlayerGstElement* mainbin = NULL;
16653 MMPlayerGstElement* textbin = NULL;
16655 gchar* subtitle_uri = NULL;
16656 int result = MM_ERROR_NONE;
16657 const gchar *charset = NULL;
16661 /* check player handle */
16662 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16663 return_val_if_fail( filepath, MM_ERROR_COMMON_INVALID_ARGUMENT );
16665 if (!(player->pipeline) || !(player->pipeline->mainbin))
16667 result = MM_ERROR_PLAYER_INVALID_STATE;
16668 debug_error("Pipeline is not in proper state\n");
16672 mainbin = player->pipeline->mainbin;
16673 textbin = player->pipeline->textbin;
16675 current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
16676 if (current_state < GST_STATE_READY)
16678 result = MM_ERROR_PLAYER_INVALID_STATE;
16679 debug_error("Pipeline is not in proper state\n");
16683 attrs = MMPLAYER_GET_ATTRS(player);
16686 debug_error("cannot get content attribute\n");
16687 result = MM_ERROR_PLAYER_INTERNAL;
16691 mm_attrs_get_string_by_name (attrs, "subtitle_uri", &subtitle_uri);
16692 if (!subtitle_uri || strlen(subtitle_uri) < 1)
16694 debug_error("subtitle uri is not proper filepath\n");
16695 result = MM_ERROR_PLAYER_INVALID_URI;
16699 debug_log("old subtitle file path is [%s]\n", subtitle_uri);
16700 debug_log("new subtitle file path is [%s]\n", filepath);
16702 if (!strcmp (filepath, subtitle_uri))
16704 debug_log("No need to swtich subtitle, as input filepath is same as current filepath\n");
16709 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16710 if (mmf_attrs_commit(player->attrs))
16712 debug_error("failed to commit.\n");
16717 //gst_pad_set_blocked_async(src-srcpad, TRUE)
16719 ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
16720 if (ret != GST_STATE_CHANGE_SUCCESS)
16722 debug_error("failed to change state of textbin to READY");
16723 result = MM_ERROR_PLAYER_INTERNAL;
16727 ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_READY);
16728 if (ret != GST_STATE_CHANGE_SUCCESS)
16730 debug_error("failed to change state of subparse to READY");
16731 result = MM_ERROR_PLAYER_INTERNAL;
16735 ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
16736 if (ret != GST_STATE_CHANGE_SUCCESS)
16738 debug_error("failed to change state of filesrc to READY");
16739 result = MM_ERROR_PLAYER_INTERNAL;
16743 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
16745 charset = util_get_charset(filepath);
16748 debug_log ("detected charset is %s\n", charset );
16749 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
16752 result = _mmplayer_sync_subtitle_pipeline(player);
16759 /* API to switch between external subtitles */
16760 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
16762 int result = MM_ERROR_NONE;
16763 mm_player_t* player = (mm_player_t*)hplayer;
16767 /* check player handle */
16768 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16770 if (!player->pipeline) // IDLE state
16772 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16773 if (mmf_attrs_commit(player->attrs))
16775 debug_error("failed to commit.\n");
16776 result= MM_ERROR_PLAYER_INTERNAL;
16779 else // curr state <> IDLE (READY, PAUSE, PLAYING..)
16781 if ( filepath == NULL )
16782 return MM_ERROR_COMMON_INVALID_ARGUMENT;
16784 if (!__mmplayer_check_subtitle(player))
16786 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16787 if (mmf_attrs_commit(player->attrs))
16789 debug_error("failed to commit.\n");
16790 result = MM_ERROR_PLAYER_INTERNAL;
16793 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
16794 debug_error("fail to create subtitle src\n");
16796 result = _mmplayer_sync_subtitle_pipeline(player);
16800 result = __mmplayer_change_external_subtitle_language(player, filepath);
16809 __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index)
16811 int result = MM_ERROR_NONE;
16812 gchar* change_pad_name = NULL;
16813 GstPad* sinkpad = NULL;
16814 MMPlayerGstElement* mainbin = NULL;
16815 enum MainElementID elemId = MMPLAYER_M_NUM;
16816 GstCaps* caps = NULL;
16817 gint total_track_num = 0;
16821 return_val_if_fail (player && player->pipeline && player->pipeline->mainbin,
16822 MM_ERROR_PLAYER_NOT_INITIALIZED);
16824 debug_log ("Change Track(%d) to %d\n", type, index);
16826 mainbin = player->pipeline->mainbin;
16828 if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
16830 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
16832 else if (type == MM_PLAYER_TRACK_TYPE_TEXT)
16834 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
16838 debug_error ("Track Type Error\n");
16842 if (mainbin[elemId].gst == NULL)
16844 result = MM_ERROR_PLAYER_NO_OP;
16845 debug_log ("Req track doesn't exist\n");
16849 total_track_num = player->selector[type].total_track_num;
16850 if (total_track_num <= 0)
16852 result = MM_ERROR_PLAYER_NO_OP;
16853 debug_log ("Language list is not available \n");
16857 if ((index < 0) || (index >= total_track_num))
16859 result = MM_ERROR_INVALID_ARGUMENT;
16860 debug_log ("Not a proper index : %d \n", index);
16864 /*To get the new pad from the selector*/
16865 change_pad_name = g_strdup_printf ("sink_%u", index);
16866 if (change_pad_name == NULL)
16868 result = MM_ERROR_PLAYER_INTERNAL;
16869 debug_log ("Pad does not exists\n");
16873 debug_log ("new active pad name: %s\n", change_pad_name);
16875 sinkpad = gst_element_get_static_pad (mainbin[elemId].gst, change_pad_name);
16876 if (sinkpad == NULL)
16878 debug_log ("sinkpad is NULL");
16879 result = MM_ERROR_PLAYER_INTERNAL;
16883 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
16884 g_object_set (mainbin[elemId].gst, "active-pad", sinkpad, NULL);
16886 caps = gst_pad_get_current_caps(sinkpad);
16887 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
16890 gst_object_unref (sinkpad);
16892 if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
16894 __mmplayer_set_audio_attrs (player, caps);
16899 MMPLAYER_FREEIF(change_pad_name);
16903 int _mmplayer_change_track_language (MMHandleType hplayer, MMPlayerTrackType type, int index)
16905 int result = MM_ERROR_NONE;
16906 mm_player_t* player = NULL;
16907 MMPlayerGstElement* mainbin = NULL;
16909 gint current_active_index = 0;
16911 GstState current_state = GST_STATE_VOID_PENDING;
16912 GstEvent* event = NULL;
16917 player = (mm_player_t*)hplayer;
16918 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
16920 if (!player->pipeline)
16922 debug_error ("Track %d pre setting -> %d\n", type, index);
16924 player->selector[type].active_pad_index = index;
16928 mainbin = player->pipeline->mainbin;
16930 current_active_index = player->selector[type].active_pad_index;
16932 /*If index is same as running index no need to change the pad*/
16933 if (current_active_index == index)
16938 if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time))
16940 result = MM_ERROR_PLAYER_INVALID_STATE;
16944 current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
16945 if (current_state < GST_STATE_PAUSED)
16947 result = MM_ERROR_PLAYER_INVALID_STATE;
16948 debug_warning ("Pipeline not in porper state\n");
16952 result = __mmplayer_change_selector_pad(player, type, index);
16953 if (result != MM_ERROR_NONE)
16955 debug_error ("change selector pad error\n");
16959 player->selector[type].active_pad_index = index;
16961 if (current_state == GST_STATE_PLAYING)
16963 event = gst_event_new_seek (1.0, 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);
16966 __gst_send_event_to_sink (player, event);
16970 result = MM_ERROR_PLAYER_INTERNAL;
16979 int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent)
16981 mm_player_t* player = (mm_player_t*) hplayer;
16985 /* check player handle */
16986 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16988 *silent = player->set_mode.subtitle_off;
16990 debug_log("subtitle is %s.\n", silent ? "ON" : "OFF");
16994 return MM_ERROR_NONE;
16998 __get_state_name ( int state )
17002 case MM_PLAYER_STATE_NULL:
17004 case MM_PLAYER_STATE_READY:
17006 case MM_PLAYER_STATE_PAUSED:
17008 case MM_PLAYER_STATE_PLAYING:
17010 case MM_PLAYER_STATE_NONE:
17018 __is_rtsp_streaming ( mm_player_t* player )
17020 return_val_if_fail ( player, FALSE );
17022 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP ) ? TRUE : FALSE;
17026 __is_wfd_streaming ( mm_player_t* player )
17028 return_val_if_fail ( player, FALSE );
17030 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_WFD ) ? TRUE : FALSE;
17034 __is_http_streaming ( mm_player_t* player )
17036 return_val_if_fail ( player, FALSE );
17038 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP ) ? TRUE : FALSE;
17042 __is_streaming ( mm_player_t* player )
17044 return_val_if_fail ( player, FALSE );
17046 return ( __is_http_progressive_down( player ) || __is_rtsp_streaming ( player ) || __is_wfd_streaming ( player ) || __is_http_streaming ( player )
17047 || __is_http_live_streaming ( player ) || __is_dash_streaming ( player ) || __is_smooth_streaming(player) ) ? TRUE : FALSE;
17051 __is_live_streaming ( mm_player_t* player )
17053 return_val_if_fail ( player, FALSE );
17055 return ( __is_rtsp_streaming ( player ) && player->streaming_type == STREAMING_SERVICE_LIVE ) ? TRUE : FALSE;
17059 __is_http_live_streaming( mm_player_t* player )
17061 return_val_if_fail( player, FALSE );
17063 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS ) ? TRUE : FALSE;
17067 __is_dash_streaming ( mm_player_t* player )
17069 return_val_if_fail ( player, FALSE );
17071 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH ) ? TRUE : FALSE;
17075 __is_smooth_streaming ( mm_player_t* player )
17077 return_val_if_fail ( player, FALSE );
17079 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_SS ) ? TRUE : FALSE;
17084 __is_http_progressive_down(mm_player_t* player)
17086 return_val_if_fail( player, FALSE );
17088 return ((player->pd_mode) ? TRUE:FALSE);
17093 __is_es_buff_src( mm_player_t* player )
17095 return_val_if_fail ( player, FALSE );
17097 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF) ? TRUE : FALSE;
17102 __has_suffix(mm_player_t* player, const gchar* suffix)
17104 return_val_if_fail( player, FALSE );
17105 return_val_if_fail( suffix, FALSE );
17107 gboolean ret = FALSE;
17108 gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
17109 gchar* t_suffix = g_ascii_strdown(suffix, -1);
17111 if ( g_str_has_suffix(player->profile.uri, suffix) )
17116 MMPLAYER_FREEIF(t_url);
17117 MMPLAYER_FREEIF(t_suffix);
17123 _mmplayer_set_display_zoom(MMHandleType hplayer, float level, int x, int y)
17125 mm_player_t* player = (mm_player_t*) hplayer;
17127 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17129 MMPLAYER_VIDEO_SINK_CHECK(player);
17131 debug_log("setting display zoom level = %f, offset = %d, %d", level, x, y);
17133 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", level, "zoom-pos-x", x, "zoom-pos-y", y, NULL);
17135 return MM_ERROR_NONE;
17138 _mmplayer_get_display_zoom(MMHandleType hplayer, float *level, int *x, int *y)
17141 mm_player_t* player = (mm_player_t*) hplayer;
17142 float _level = 0.0;
17146 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17148 MMPLAYER_VIDEO_SINK_CHECK(player);
17150 g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", &_level, "zoom-pos-x", &_x, "zoom-pos-y", &_y, NULL);
17152 debug_log("display zoom level = %f, start off x = %d, y = %d", _level, _x, _y);
17158 return MM_ERROR_NONE;
17162 _mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
17164 mm_player_t* player = (mm_player_t*) hplayer;
17166 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
17168 if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL)
17170 MMPLAYER_PRINT_STATE(player);
17171 debug_error("wrong-state : can't set the download mode to parse");
17172 return MM_ERROR_PLAYER_INVALID_STATE;
17175 debug_log("set video hub download mode to %s", (mode)?"ON":"OFF");
17176 player->video_hub_download_mode = mode;
17178 return MM_ERROR_NONE;
17182 _mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
17184 mm_player_t* player = (mm_player_t*) hplayer;
17186 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
17188 debug_log("enable sync handler : %s", (enable)?"ON":"OFF");
17189 player->sync_handler = enable;
17191 return MM_ERROR_NONE;
17195 _mmplayer_use_system_clock (MMHandleType hplayer)
17197 mm_player_t* player = (mm_player_t*) hplayer;
17199 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
17201 debug_log("change clock provider to system");
17203 // to use system clock
17204 player->ini.provide_clock_for_movie = FALSE;
17205 player->ini.provide_clock_for_music = FALSE;
17207 return MM_ERROR_NONE;
17211 _mmplayer_set_video_share_master_clock( MMHandleType hplayer,
17213 long long clock_delta,
17214 long long video_time,
17215 long long media_clock,
17216 long long audio_time)
17218 mm_player_t* player = (mm_player_t*) hplayer;
17219 MMPlayerGstElement* mainbin = NULL;
17220 GstClockTime start_time_audio = 0, start_time_video = 0;
17221 GstClockTimeDiff base_time = 0, new_base_time = 0;
17222 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
17223 gint64 api_delta = 0;
17224 gint64 position = 0, position_delta = 0;
17225 gint64 adj_base_time = 0;
17226 GstClock *curr_clock = NULL;
17227 GstClockTime curr_time = 0;
17228 gboolean query_ret = TRUE;
17229 int result = MM_ERROR_NONE;
17233 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
17234 return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
17235 return_val_if_fail ( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
17237 // debug_log("in(us) : %lld, %lld, %lld, %lld, %lld", clock, clock_delta, video_time, media_clock, audio_time);
17239 if ((video_time < 0) || (player->doing_seek))
17241 debug_log("skip setting master clock. %lld", video_time);
17245 mainbin = player->pipeline->mainbin;
17247 curr_clock = gst_pipeline_get_clock (GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
17248 curr_time = gst_clock_get_time (curr_clock);
17250 current_state = MMPLAYER_CURRENT_STATE(player);
17252 if ( current_state == MM_PLAYER_STATE_PLAYING )
17253 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
17255 if ( ( current_state != MM_PLAYER_STATE_PLAYING ) ||
17258 position = player->last_position;
17259 debug_log ("query fail. %lld", position);
17262 clock*= GST_USECOND;
17263 clock_delta *= GST_USECOND;
17265 api_delta = clock - curr_time;
17266 if ((player->video_share_api_delta == 0 ) || (player->video_share_api_delta > api_delta))
17268 player->video_share_api_delta = api_delta;
17272 clock_delta += (api_delta - player->video_share_api_delta);
17275 if ((player->video_share_clock_delta == 0 ) || (player->video_share_clock_delta > clock_delta))
17277 player->video_share_clock_delta = (gint64)clock_delta;
17279 position_delta = (position/GST_USECOND) - video_time;
17280 position_delta *= GST_USECOND;
17282 adj_base_time = position_delta;
17283 debug_log ("video_share_clock_delta = %lld, adj = %lld", player->video_share_clock_delta, adj_base_time);
17288 gint64 new_play_time = 0;
17289 gint64 network_delay =0;
17291 video_time *= GST_USECOND;
17293 network_delay = clock_delta - player->video_share_clock_delta;
17294 new_play_time = video_time + network_delay;
17296 adj_base_time = position - new_play_time;
17298 debug_log ("%lld(delay) = %lld - %lld / %lld(adj) = %lld(slave_pos) - %lld(master_pos) - %lld(delay)",
17299 network_delay, clock_delta, player->video_share_clock_delta, adj_base_time, position, video_time, network_delay);
17302 /* Adjust Current Stream Time with base_time of sink
17303 * 1. Set Start time to CLOCK NONE, to control the base time by MSL
17304 * 2. Set new base time
17305 * if adj_base_time is positive value, the stream time will be decreased.
17306 * 3. If seek event is occurred, the start time will be reset. */
17307 if ((player->pipeline->audiobin) &&
17308 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
17310 start_time_audio = gst_element_get_start_time (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
17312 if (start_time_audio != GST_CLOCK_TIME_NONE)
17314 debug_log ("audio sink : gst_element_set_start_time -> NONE");
17315 gst_element_set_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, GST_CLOCK_TIME_NONE);
17318 base_time = gst_element_get_base_time (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
17321 if ((player->pipeline->videobin) &&
17322 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
17324 start_time_video = gst_element_get_start_time (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
17326 if (start_time_video != GST_CLOCK_TIME_NONE)
17328 debug_log ("video sink : gst_element_set_start_time -> NONE");
17329 gst_element_set_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst, GST_CLOCK_TIME_NONE);
17332 // if videobin exist, get base_time from videobin.
17333 base_time = gst_element_get_base_time (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
17336 new_base_time = base_time + adj_base_time;
17338 if ((player->pipeline->audiobin) &&
17339 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
17340 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), (GstClockTime)new_base_time);
17342 if ((player->pipeline->videobin) &&
17343 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
17344 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), (GstClockTime)new_base_time);
17353 _mmplayer_get_video_share_master_clock( MMHandleType hplayer,
17354 long long *video_time,
17355 long long *media_clock,
17356 long long *audio_time)
17358 mm_player_t* player = (mm_player_t*) hplayer;
17359 MMPlayerGstElement* mainbin = NULL;
17360 GstClock *curr_clock = NULL;
17361 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
17362 gint64 position = 0;
17363 gboolean query_ret = TRUE;
17367 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
17368 return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
17369 return_val_if_fail ( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
17371 return_val_if_fail ( video_time, MM_ERROR_COMMON_INVALID_ARGUMENT );
17372 return_val_if_fail ( media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT );
17373 return_val_if_fail ( audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT );
17375 mainbin = player->pipeline->mainbin;
17377 curr_clock = gst_pipeline_get_clock (GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
17379 current_state = MMPLAYER_CURRENT_STATE(player);
17381 if ( current_state != MM_PLAYER_STATE_PAUSED )
17382 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
17384 if ( ( current_state == MM_PLAYER_STATE_PAUSED ) ||
17387 position = player->last_position;
17390 *media_clock = *video_time = *audio_time = (position/GST_USECOND);
17392 debug_log("media_clock: %lld, video_time: %lld (us)", *media_clock, *video_time);
17395 gst_object_unref (curr_clock);
17399 return MM_ERROR_NONE;
17403 _mmplayer_get_video_rotate_angle(MMHandleType hplayer, int *angle)
17405 mm_player_t* player = (mm_player_t*) hplayer;
17410 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17411 return_val_if_fail ( angle, MM_ERROR_COMMON_INVALID_ARGUMENT );
17413 if (player->v_stream_caps)
17415 GstStructure *str = NULL;
17417 str = gst_caps_get_structure (player->v_stream_caps, 0);
17418 if ( !gst_structure_get_int (str, "orientation", &org_angle))
17420 debug_log ("missing 'orientation' field in video caps");
17424 debug_log("orientation: %d", org_angle);
17425 *angle = org_angle;
17428 return MM_ERROR_NONE;
17432 __mmplayer_is_streaming(mm_player_t* player)
17434 gboolean result = FALSE;
17438 return_val_if_fail (player, FALSE);
17439 result = __is_streaming (player) ;
17446 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
17448 return_val_if_fail (player, FALSE);
17449 return_val_if_fail (element, FALSE);
17451 gchar *factory_name = GST_OBJECT_NAME (gst_element_get_factory(element));
17452 gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
17456 for ( idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++ )
17458 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx]))
17460 debug_log("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
17461 mm_player_dump_t *dump_s;
17462 dump_s = g_malloc (sizeof(mm_player_dump_t));
17464 if (dump_s == NULL)
17466 debug_error ("malloc fail");
17470 dump_s->dump_element_file = NULL;
17471 dump_s->dump_pad = NULL;
17472 dump_s->dump_pad = gst_element_get_static_pad (element, "sink");
17474 if (dump_s->dump_pad)
17476 memset (dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
17477 sprintf (dump_file_name, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
17478 dump_s->dump_element_file = fopen(dump_file_name,"w+");
17479 // dump_s->probe_handle_id = gst_pad_add_buffer_probe (dump_s->dump_pad, G_CALLBACK(__mmplayer_dump_buffer_probe_cb), dump_s->dump_element_file);
17480 /* add list for removed buffer probe and close FILE */
17481 player->dump_list = g_list_append (player->dump_list, dump_s);
17482 debug_log ("%s sink pad added buffer probe for dump", factory_name);
17489 debug_error ("failed to get %s sink pad added", factory_name);
17501 __mmplayer_dump_buffer_probe_cb(GstPad *pad, GstBuffer *buffer, gpointer u_data)
17503 FILE *dump_data = (FILE *) u_data;
17504 // int written = 0;
17506 return_val_if_fail ( dump_data, FALSE );
17508 // debug_log ("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS( GST_BUFFER_TIMESTAMP(buffer)));
17510 fwrite ( GST_BUFFER_DATA(buffer), 1, GST_BUFFER_SIZE(buffer), dump_data);
17517 __mmplayer_release_dump_list (GList *dump_list)
17521 GList *d_list = dump_list;
17522 for ( ;d_list ; d_list = g_list_next(d_list))
17524 mm_player_dump_t *dump_s = d_list->data;
17525 if (dump_s->dump_pad)
17527 if (dump_s->probe_handle_id)
17529 gst_pad_remove_probe (dump_s->dump_pad, dump_s->probe_handle_id);
17533 if (dump_s->dump_element_file)
17535 fclose(dump_s->dump_element_file);
17536 dump_s->dump_element_file = NULL;
17538 MMPLAYER_FREEIF(dump_s);
17540 g_list_free(dump_list);
17546 _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
17548 mm_player_t* player = (mm_player_t*) hplayer;
17552 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
17553 return_val_if_fail ( exist, MM_ERROR_INVALID_ARGUMENT );
17555 *exist = player->has_closed_caption;
17559 return MM_ERROR_NONE;
17563 _mmplayer_enable_media_packet_video_stream(MMHandleType hplayer, bool enable)
17565 mm_player_t* player = (mm_player_t*) hplayer;
17569 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
17570 return_val_if_fail (enable == TRUE || enable == FALSE, MM_ERROR_INVALID_ARGUMENT);
17572 player->set_mode.media_packet_video_stream = enable;
17576 return MM_ERROR_NONE;
17579 void * _mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer)
17583 /* increase ref count of gst buffer */
17585 ret = gst_buffer_ref((GstBuffer *)buffer);
17591 void _mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer)
17595 gst_buffer_unref((GstBuffer *)buffer);
17602 __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data)
17604 mm_player_t *player = (mm_player_t*)user_data;
17605 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
17607 return_if_fail ( player );
17609 debug_msg("app-src: feed audio\n");
17611 if (player->media_stream_buffer_status_cb[type])
17613 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
17618 __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data)
17620 mm_player_t *player = (mm_player_t*)user_data;
17621 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
17623 return_if_fail ( player );
17625 debug_msg("app-src: feed video\n");
17627 if (player->media_stream_buffer_status_cb[type])
17629 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
17634 __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data)
17636 mm_player_t *player = (mm_player_t*)user_data;
17637 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
17639 return_if_fail ( player );
17641 debug_msg("app-src: feed subtitle\n");
17643 if (player->media_stream_buffer_status_cb[type])
17645 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param);
17650 __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data)
17652 mm_player_t *player = (mm_player_t*)user_data;
17653 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
17655 return_if_fail ( player );
17657 debug_msg("app-src: audio buffer is full.\n");
17659 if (player->media_stream_buffer_status_cb[type])
17661 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
17666 __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data)
17668 mm_player_t *player = (mm_player_t*)user_data;
17669 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
17671 return_if_fail ( player );
17673 debug_msg("app-src: video buffer is full.\n");
17675 if (player->media_stream_buffer_status_cb[type])
17677 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param);
17682 __gst_seek_audio_data (GstElement * appsrc, guint64 position, gpointer user_data)
17684 mm_player_t *player = (mm_player_t*)user_data;
17685 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
17687 return_val_if_fail( player, FALSE );
17689 debug_log("app-src: seek audio data\n");
17691 if (player->media_stream_seek_data_cb[type])
17693 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
17700 __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data)
17702 mm_player_t *player = (mm_player_t*)user_data;
17703 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
17705 return_val_if_fail( player, FALSE );
17707 debug_log("app-src: seek video data\n");
17709 if (player->media_stream_seek_data_cb[type])
17711 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);
17718 __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data)
17720 mm_player_t *player = (mm_player_t*)user_data;
17721 MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
17723 return_val_if_fail( player, FALSE );
17725 debug_log("app-src: seek subtitle data\n");
17727 if (player->media_stream_seek_data_cb[type])
17729 player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param);